From e36407cb1e47892814d2d18ec82a8761a31ab928 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 27 Jun 2018 17:37:23 +0200 Subject: [PATCH] Tutorials updated to use release 2.2.0 --- openvidu-getaroom/web/index.html | 2 +- .../web/openvidu-browser-2.1.0.js | 10290 ---------------- .../web/openvidu-browser-2.2.0.js | 7371 +++++++++++ openvidu-hello-world/web/index.html | 2 +- .../web/openvidu-browser-2.1.0.js | 10290 ---------------- .../web/openvidu-browser-2.2.0.js | 7371 +++++++++++ openvidu-insecure-angular/package-lock.json | 4027 +++++- openvidu-insecure-angular/package.json | 4 +- openvidu-insecure-js/web/index.html | 2 +- .../web/openvidu-browser-2.1.0.js | 10290 ---------------- .../web/openvidu-browser-2.2.0.js | 7371 +++++++++++ openvidu-js-java/.classpath | 17 + .../.settings/org.eclipse.jdt.core.prefs | 2 + openvidu-js-java/pom.xml | 4 +- .../src/main/resources/static/index.html | 2 +- .../static/openvidu-browser-2.1.0.js | 10290 ---------------- .../static/openvidu-browser-2.2.0.js | 7371 +++++++++++ openvidu-js-node/package-lock.json | 493 + openvidu-js-node/package.json | 4 +- openvidu-js-node/public/index.html | 2 +- .../public/openvidu-browser-2.1.0.js | 10290 ---------------- .../public/openvidu-browser-2.2.0.js | 7371 +++++++++++ openvidu-mvc-java/pom.xml | 4 +- .../static/openvidu-browser-2.1.0.js | 10290 ---------------- .../static/openvidu-browser-2.2.0.js | 7371 +++++++++++ .../src/main/resources/templates/session.html | 2 +- openvidu-mvc-node/package-lock.json | 2543 ++++ openvidu-mvc-node/package.json | 4 +- .../public/openvidu-browser-2.1.0.js | 10290 ---------------- .../public/openvidu-browser-2.2.0.js | 7371 +++++++++++ openvidu-mvc-node/views/session.ejs | 2 +- openvidu-recording-java/pom.xml | 4 +- .../src/main/resources/static/index.html | 2 +- .../static/openvidu-browser-2.1.0.js | 10290 ---------------- .../static/openvidu-browser-2.2.0.js | 7371 +++++++++++ openvidu-recording-node/package-lock.json | 454 + openvidu-recording-node/package.json | 6 +- openvidu-recording-node/public/index.html | 2 +- .../public/openvidu-browser-2.1.0.js | 10290 ---------------- .../public/openvidu-browser-2.2.0.js | 7371 +++++++++++ 40 files changed, 73763 insertions(+), 92770 deletions(-) delete mode 100644 openvidu-getaroom/web/openvidu-browser-2.1.0.js create mode 100644 openvidu-getaroom/web/openvidu-browser-2.2.0.js delete mode 100644 openvidu-hello-world/web/openvidu-browser-2.1.0.js create mode 100644 openvidu-hello-world/web/openvidu-browser-2.2.0.js delete mode 100644 openvidu-insecure-js/web/openvidu-browser-2.1.0.js create mode 100644 openvidu-insecure-js/web/openvidu-browser-2.2.0.js delete mode 100644 openvidu-js-java/src/main/resources/static/openvidu-browser-2.1.0.js create mode 100644 openvidu-js-java/src/main/resources/static/openvidu-browser-2.2.0.js create mode 100644 openvidu-js-node/package-lock.json delete mode 100644 openvidu-js-node/public/openvidu-browser-2.1.0.js create mode 100644 openvidu-js-node/public/openvidu-browser-2.2.0.js delete mode 100644 openvidu-mvc-java/src/main/resources/static/openvidu-browser-2.1.0.js create mode 100644 openvidu-mvc-java/src/main/resources/static/openvidu-browser-2.2.0.js create mode 100644 openvidu-mvc-node/package-lock.json delete mode 100644 openvidu-mvc-node/public/openvidu-browser-2.1.0.js create mode 100644 openvidu-mvc-node/public/openvidu-browser-2.2.0.js delete mode 100644 openvidu-recording-java/src/main/resources/static/openvidu-browser-2.1.0.js create mode 100644 openvidu-recording-java/src/main/resources/static/openvidu-browser-2.2.0.js create mode 100644 openvidu-recording-node/package-lock.json delete mode 100644 openvidu-recording-node/public/openvidu-browser-2.1.0.js create mode 100644 openvidu-recording-node/public/openvidu-browser-2.2.0.js diff --git a/openvidu-getaroom/web/index.html b/openvidu-getaroom/web/index.html index a242f682..8c398d2f 100644 --- a/openvidu-getaroom/web/index.html +++ b/openvidu-getaroom/web/index.html @@ -14,7 +14,7 @@ - + diff --git a/openvidu-getaroom/web/openvidu-browser-2.1.0.js b/openvidu-getaroom/web/openvidu-browser-2.1.0.js deleted file mode 100644 index 3f2f3477..00000000 --- a/openvidu-getaroom/web/openvidu-browser-2.1.0.js +++ /dev/null @@ -1,10290 +0,0 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - // At least give some kind of context to the user - var err = new Error('Unhandled "error" event. (' + er + ')'); - err.context = er; - throw err; - } - return false; - } - - handler = events[type]; - - if (!handler) - return false; - - var isFn = typeof handler === 'function'; - len = arguments.length; - switch (len) { - // fast cases - case 1: - emitNone(handler, isFn, this); - break; - case 2: - emitOne(handler, isFn, this, arguments[1]); - break; - case 3: - emitTwo(handler, isFn, this, arguments[1], arguments[2]); - break; - case 4: - emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); - break; - // slower - default: - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - emitMany(handler, isFn, this, args); - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = target._events; - if (!events) { - events = target._events = objectCreate(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener) { - target.emit('newListener', type, - listener.listener ? listener.listener : listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (!existing) { - // Optimize the case of one listener. Don't need the extra array object. - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - } else { - // If we've already got an array, just append. - if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - } - - // Check for listener leak - if (!existing.warned) { - m = $getMaxListeners(target); - if (m && m > 0 && existing.length > m) { - existing.warned = true; - var w = new Error('Possible EventEmitter memory leak detected. ' + - existing.length + ' "' + String(type) + '" listeners ' + - 'added. Use emitter.setMaxListeners() to ' + - 'increase limit.'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - if (typeof console === 'object' && console.warn) { - console.warn('%s: %s', w.name, w.message); - } - } - } - } - - return target; -} - -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - switch (arguments.length) { - case 0: - return this.listener.call(this.target); - case 1: - return this.listener.call(this.target, arguments[0]); - case 2: - return this.listener.call(this.target, arguments[0], arguments[1]); - case 3: - return this.listener.call(this.target, arguments[0], arguments[1], - arguments[2]); - default: - var args = new Array(arguments.length); - for (var i = 0; i < args.length; ++i) - args[i] = arguments[i]; - this.listener.apply(this.target, args); - } - } -} - -function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; - var wrapped = bind.call(onceWrapper, state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -EventEmitter.prototype.once = function once(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - -// Emits a 'removeListener' event if and only if the listener was removed. -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - var list, events, position, i, originalListener; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = this._events; - if (!events) - return this; - - list = events[type]; - if (!list) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - position = -1; - - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else - spliceOne(list, position); - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener) - this.emit('removeListener', type, originalListener || listener); - } - - return this; - }; - -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - var listeners, events, i; - - events = this._events; - if (!events) - return this; - - // not listening for removeListener, no need to emit - if (!events.removeListener) { - if (arguments.length === 0) { - this._events = objectCreate(null); - this._eventsCount = 0; - } else if (events[type]) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else - delete events[type]; - } - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - var keys = objectKeys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = objectCreate(null); - this._eventsCount = 0; - return this; - } - - listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - var events = target._events; - - if (!events) - return []; - - var evlistener = events[type]; - if (!evlistener) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); -} - -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } -}; - -EventEmitter.prototype.listenerCount = listenerCount; -function listenerCount(type) { - var events = this._events; - - if (events) { - var evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener) { - return evlistener.length; - } - } - - return 0; -} - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; -}; - -// About 1.5x faster than the two-arg version of Array#splice(). -function spliceOne(list, index) { - for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) - list[i] = list[k]; - list.pop(); -} - -function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) - copy[i] = arr[i]; - return copy; -} - -function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; -} - -function objectCreatePolyfill(proto) { - var F = function() {}; - F.prototype = proto; - return new F; -} -function objectKeysPolyfill(obj) { - var keys = []; - for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { - keys.push(k); - } - return k; -} -function functionBindPolyfill(context) { - var fn = this; - return function () { - return fn.apply(context, arguments); - }; -} - -},{}],2:[function(require,module,exports){ -/* jshint node: true */ -'use strict'; - -var normalice = require('normalice'); - -/** - # freeice - - The `freeice` module is a simple way of getting random STUN or TURN server - for your WebRTC application. The list of servers (just STUN at this stage) - were sourced from this [gist](https://gist.github.com/zziuni/3741933). - - ## Example Use - - The following demonstrates how you can use `freeice` with - [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): - - <<< examples/quickconnect.js - - As the `freeice` module generates ice servers in a list compliant with the - WebRTC spec you will be able to use it with raw `RTCPeerConnection` - constructors and other WebRTC libraries. - - ## Hey, don't use my STUN/TURN server! - - If for some reason your free STUN or TURN server ends up in the - list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or - [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) - that is used in this module, you can feel - free to open an issue on this repository and those servers will be removed - within 24 hours (or sooner). This is the quickest and probably the most - polite way to have something removed (and provides us some visibility - if someone opens a pull request requesting that a server is added). - - ## Please add my server! - - If you have a server that you wish to add to the list, that's awesome! I'm - sure I speak on behalf of a whole pile of WebRTC developers who say thanks. - To get it into the list, feel free to either open a pull request or if you - find that process a bit daunting then just create an issue requesting - the addition of the server (make sure you provide all the details, and if - you have a Terms of Service then including that in the PR/issue would be - awesome). - - ## I know of a free server, can I add it? - - Sure, if you do your homework and make sure it is ok to use (I'm currently - in the process of reviewing the terms of those STUN servers included from - the original list). If it's ok to go, then please see the previous entry - for how to add it. - - ## Current List of Servers - - * current as at the time of last `README.md` file generation - - ### STUN - - <<< stun.json - - ### TURN - - <<< turn.json - -**/ - -var freeice = module.exports = function(opts) { - // if a list of servers has been provided, then use it instead of defaults - var servers = { - stun: (opts || {}).stun || require('./stun.json'), - turn: (opts || {}).turn || require('./turn.json') - }; - - var stunCount = (opts || {}).stunCount || 2; - var turnCount = (opts || {}).turnCount || 0; - var selected; - - function getServers(type, count) { - var out = []; - var input = [].concat(servers[type]); - var idx; - - while (input.length && out.length < count) { - idx = (Math.random() * input.length) | 0; - out = out.concat(input.splice(idx, 1)); - } - - return out.map(function(url) { - //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up - if ((typeof url !== 'string') && (! (url instanceof String))) { - return url; - } else { - return normalice(type + ':' + url); - } - }); - } - - // add stun servers - selected = [].concat(getServers('stun', stunCount)); - - if (turnCount) { - selected = selected.concat(getServers('turn', turnCount)); - } - - return selected; -}; - -},{"./stun.json":3,"./turn.json":4,"normalice":8}],3:[function(require,module,exports){ -module.exports=[ - "stun.l.google.com:19302", - "stun1.l.google.com:19302", - "stun2.l.google.com:19302", - "stun3.l.google.com:19302", - "stun4.l.google.com:19302", - "stun.ekiga.net", - "stun.ideasip.com", - "stun.schlund.de", - "stun.stunprotocol.org:3478", - "stun.voiparound.com", - "stun.voipbuster.com", - "stun.voipstunt.com", - "stun.voxgratia.org", - "stun.services.mozilla.com" -] - -},{}],4:[function(require,module,exports){ -module.exports=[] - -},{}],5:[function(require,module,exports){ -var WildEmitter = require('wildemitter'); - -function getMaxVolume (analyser, fftBins) { - var maxVolume = -Infinity; - analyser.getFloatFrequencyData(fftBins); - - for(var i=4, ii=fftBins.length; i < ii; i++) { - if (fftBins[i] > maxVolume && fftBins[i] < 0) { - maxVolume = fftBins[i]; - } - }; - - return maxVolume; -} - - -var audioContextType; -if (typeof window !== 'undefined') { - audioContextType = window.AudioContext || window.webkitAudioContext; -} -// use a single audio context due to hardware limits -var audioContext = null; -module.exports = function(stream, options) { - var harker = new WildEmitter(); - - - // make it not break in non-supported browsers - if (!audioContextType) return harker; - - //Config - var options = options || {}, - smoothing = (options.smoothing || 0.1), - interval = (options.interval || 50), - threshold = options.threshold, - play = options.play, - history = options.history || 10, - running = true; - - //Setup Audio Context - if (!audioContext) { - audioContext = new audioContextType(); - } - var sourceNode, fftBins, analyser; - - analyser = audioContext.createAnalyser(); - analyser.fftSize = 512; - analyser.smoothingTimeConstant = smoothing; - fftBins = new Float32Array(analyser.frequencyBinCount); - - if (stream.jquery) stream = stream[0]; - if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { - //Audio Tag - sourceNode = audioContext.createMediaElementSource(stream); - if (typeof play === 'undefined') play = true; - threshold = threshold || -50; - } else { - //WebRTC Stream - sourceNode = audioContext.createMediaStreamSource(stream); - threshold = threshold || -50; - } - - sourceNode.connect(analyser); - if (play) analyser.connect(audioContext.destination); - - harker.speaking = false; - - harker.suspend = function() { - audioContext.suspend(); - } - harker.resume = function() { - audioContext.resume(); - } - Object.defineProperty(harker, 'state', { get: function() { - return audioContext.state; - }}); - audioContext.onstatechange = function() { - harker.emit('state_change', audioContext.state); - } - - harker.setThreshold = function(t) { - threshold = t; - }; - - harker.setInterval = function(i) { - interval = i; - }; - - harker.stop = function() { - running = false; - harker.emit('volume_change', -100, threshold); - if (harker.speaking) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - analyser.disconnect(); - sourceNode.disconnect(); - }; - harker.speakingHistory = []; - for (var i = 0; i < history; i++) { - harker.speakingHistory.push(0); - } - - // Poll the analyser node to determine if speaking - // and emit events if changed - var looper = function() { - setTimeout(function() { - - //check if stop has been called - if(!running) { - return; - } - - var currentVolume = getMaxVolume(analyser, fftBins); - - harker.emit('volume_change', currentVolume, threshold); - - var history = 0; - if (currentVolume > threshold && !harker.speaking) { - // trigger quickly, short history - for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history >= 2) { - harker.speaking = true; - harker.emit('speaking'); - } - } else if (currentVolume < threshold && harker.speaking) { - for (var i = 0; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history == 0) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - } - harker.speakingHistory.shift(); - harker.speakingHistory.push(0 + (currentVolume > threshold)); - - looper(); - }, interval); - }; - looper(); - - - return harker; -} - -},{"wildemitter":24}],6:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],7:[function(require,module,exports){ -/*! - * @name JavaScript/NodeJS Merge v1.2.0 - * @author yeikos - * @repository https://github.com/yeikos/js.merge - - * Copyright 2014 yeikos - MIT license - * https://raw.github.com/yeikos/js.merge/master/LICENSE - */ - -;(function(isNode) { - - /** - * Merge one or more objects - * @param bool? clone - * @param mixed,... arguments - * @return object - */ - - var Public = function(clone) { - - return merge(clone === true, false, arguments); - - }, publicName = 'merge'; - - /** - * Merge two or more objects recursively - * @param bool? clone - * @param mixed,... arguments - * @return object - */ - - Public.recursive = function(clone) { - - return merge(clone === true, true, arguments); - - }; - - /** - * Clone the input removing any reference - * @param mixed input - * @return mixed - */ - - Public.clone = function(input) { - - var output = input, - type = typeOf(input), - index, size; - - if (type === 'array') { - - output = []; - size = input.length; - - for (index=0;index 1) { - url = parts[1]; - parts = parts[0].split(':'); - - // add the output credential and username - output.username = parts[0]; - output.credential = (input || {}).credential || parts[1] || ''; - } - - output.url = protocol + url; - output.urls = [ output.url ]; - - return output; -}; - -},{}],9:[function(require,module,exports){ -(function (global){ -/*! - * Platform.js - * Copyright 2014-2018 Benjamin Tan - * Copyright 2011-2013 John-David Dalton - * Available under MIT license - */ -;(function() { - 'use strict'; - - /** Used to determine if values are of the language type `Object`. */ - var objectTypes = { - 'function': true, - 'object': true - }; - - /** Used as a reference to the global object. */ - var root = (objectTypes[typeof window] && window) || this; - - /** Backup possible global object. */ - var oldRoot = root; - - /** Detect free variable `exports`. */ - var freeExports = objectTypes[typeof exports] && exports; - - /** Detect free variable `module`. */ - var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; - - /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ - var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; - if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { - root = freeGlobal; - } - - /** - * Used as the maximum length of an array-like object. - * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) - * for more details. - */ - var maxSafeInteger = Math.pow(2, 53) - 1; - - /** Regular expression to detect Opera. */ - var reOpera = /\bOpera/; - - /** Possible global object. */ - var thisBinding = this; - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** Used to check for own properties of an object. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Used to resolve the internal `[[Class]]` of values. */ - var toString = objectProto.toString; - - /*--------------------------------------------------------------------------*/ - - /** - * Capitalizes a string value. - * - * @private - * @param {string} string The string to capitalize. - * @returns {string} The capitalized string. - */ - function capitalize(string) { - string = String(string); - return string.charAt(0).toUpperCase() + string.slice(1); - } - - /** - * A utility function to clean up the OS name. - * - * @private - * @param {string} os The OS name to clean up. - * @param {string} [pattern] A `RegExp` pattern matching the OS name. - * @param {string} [label] A label for the OS. - */ - function cleanupOS(os, pattern, label) { - // Platform tokens are defined at: - // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - var data = { - '10.0': '10', - '6.4': '10 Technical Preview', - '6.3': '8.1', - '6.2': '8', - '6.1': 'Server 2008 R2 / 7', - '6.0': 'Server 2008 / Vista', - '5.2': 'Server 2003 / XP 64-bit', - '5.1': 'XP', - '5.01': '2000 SP1', - '5.0': '2000', - '4.0': 'NT', - '4.90': 'ME' - }; - // Detect Windows version from platform tokens. - if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && - (data = data[/[\d.]+$/.exec(os)])) { - os = 'Windows ' + data; - } - // Correct character case and cleanup string. - os = String(os); - - if (pattern && label) { - os = os.replace(RegExp(pattern, 'i'), label); - } - - os = format( - os.replace(/ ce$/i, ' CE') - .replace(/\bhpw/i, 'web') - .replace(/\bMacintosh\b/, 'Mac OS') - .replace(/_PowerPC\b/i, ' OS') - .replace(/\b(OS X) [^ \d]+/i, '$1') - .replace(/\bMac (OS X)\b/, '$1') - .replace(/\/(\d)/, ' $1') - .replace(/_/g, '.') - .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') - .replace(/\bx86\.64\b/gi, 'x86_64') - .replace(/\b(Windows Phone) OS\b/, '$1') - .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') - .split(' on ')[0] - ); - - return os; - } - - /** - * An iteration utility for arrays and objects. - * - * @private - * @param {Array|Object} object The object to iterate over. - * @param {Function} callback The function called per iteration. - */ - function each(object, callback) { - var index = -1, - length = object ? object.length : 0; - - if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { - while (++index < length) { - callback(object[index], index, object); - } - } else { - forOwn(object, callback); - } - } - - /** - * Trim and conditionally capitalize string values. - * - * @private - * @param {string} string The string to format. - * @returns {string} The formatted string. - */ - function format(string) { - string = trim(string); - return /^(?:webOS|i(?:OS|P))/.test(string) - ? string - : capitalize(string); - } - - /** - * Iterates over an object's own properties, executing the `callback` for each. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} callback The function executed per own property. - */ - function forOwn(object, callback) { - for (var key in object) { - if (hasOwnProperty.call(object, key)) { - callback(object[key], key, object); - } - } - } - - /** - * Gets the internal `[[Class]]` of a value. - * - * @private - * @param {*} value The value. - * @returns {string} The `[[Class]]`. - */ - function getClassOf(value) { - return value == null - ? capitalize(value) - : toString.call(value).slice(8, -1); - } - - /** - * Host objects can return type values that are different from their actual - * data type. The objects we are concerned with usually return non-primitive - * types of "object", "function", or "unknown". - * - * @private - * @param {*} object The owner of the property. - * @param {string} property The property to check. - * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. - */ - function isHostType(object, property) { - var type = object != null ? typeof object[property] : 'number'; - return !/^(?:boolean|number|string|undefined)$/.test(type) && - (type == 'object' ? !!object[property] : true); - } - - /** - * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. - * - * @private - * @param {string} string The string to qualify. - * @returns {string} The qualified string. - */ - function qualify(string) { - return String(string).replace(/([ -])(?!$)/g, '$1?'); - } - - /** - * A bare-bones `Array#reduce` like utility function. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {*} The accumulated result. - */ - function reduce(array, callback) { - var accumulator = null; - each(array, function(value, index) { - accumulator = callback(accumulator, value, index, array); - }); - return accumulator; - } - - /** - * Removes leading and trailing whitespace from a string. - * - * @private - * @param {string} string The string to trim. - * @returns {string} The trimmed string. - */ - function trim(string) { - return String(string).replace(/^ +| +$/g, ''); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Creates a new platform object. - * - * @memberOf platform - * @param {Object|string} [ua=navigator.userAgent] The user agent string or - * context object. - * @returns {Object} A platform object. - */ - function parse(ua) { - - /** The environment context object. */ - var context = root; - - /** Used to flag when a custom context is provided. */ - var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; - - // Juggle arguments. - if (isCustomContext) { - context = ua; - ua = null; - } - - /** Browser navigator object. */ - var nav = context.navigator || {}; - - /** Browser user agent string. */ - var userAgent = nav.userAgent || ''; - - ua || (ua = userAgent); - - /** Used to flag when `thisBinding` is the [ModuleScope]. */ - var isModuleScope = isCustomContext || thisBinding == oldRoot; - - /** Used to detect if browser is like Chrome. */ - var likeChrome = isCustomContext - ? !!nav.likeChrome - : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); - - /** Internal `[[Class]]` value shortcuts. */ - var objectClass = 'Object', - airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', - enviroClass = isCustomContext ? objectClass : 'Environment', - javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), - phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; - - /** Detect Java environments. */ - var java = /\bJava/.test(javaClass) && context.java; - - /** Detect Rhino. */ - var rhino = java && getClassOf(context.environment) == enviroClass; - - /** A character to represent alpha. */ - var alpha = java ? 'a' : '\u03b1'; - - /** A character to represent beta. */ - var beta = java ? 'b' : '\u03b2'; - - /** Browser document object. */ - var doc = context.document || {}; - - /** - * Detect Opera browser (Presto-based). - * http://www.howtocreate.co.uk/operaStuff/operaObject.html - * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini - */ - var opera = context.operamini || context.opera; - - /** Opera `[[Class]]`. */ - var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) - ? operaClass - : (opera = null); - - /*------------------------------------------------------------------------*/ - - /** Temporary variable used over the script's lifetime. */ - var data; - - /** The CPU architecture. */ - var arch = ua; - - /** Platform description array. */ - var description = []; - - /** Platform alpha/beta indicator. */ - var prerelease = null; - - /** A flag to indicate that environment features should be used to resolve the platform. */ - var useFeatures = ua == userAgent; - - /** The browser/environment version. */ - var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); - - /** A flag to indicate if the OS ends with "/ Version" */ - var isSpecialCasedOS; - - /* Detectable layout engines (order is important). */ - var layout = getLayout([ - { 'label': 'EdgeHTML', 'pattern': 'Edge' }, - 'Trident', - { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, - 'iCab', - 'Presto', - 'NetFront', - 'Tasman', - 'KHTML', - 'Gecko' - ]); - - /* Detectable browser names (order is important). */ - var name = getName([ - 'Adobe AIR', - 'Arora', - 'Avant Browser', - 'Breach', - 'Camino', - 'Electron', - 'Epiphany', - 'Fennec', - 'Flock', - 'Galeon', - 'GreenBrowser', - 'iCab', - 'Iceweasel', - 'K-Meleon', - 'Konqueror', - 'Lunascape', - 'Maxthon', - { 'label': 'Microsoft Edge', 'pattern': 'Edge' }, - 'Midori', - 'Nook Browser', - 'PaleMoon', - 'PhantomJS', - 'Raven', - 'Rekonq', - 'RockMelt', - { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' }, - 'SeaMonkey', - { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Sleipnir', - 'SlimBrowser', - { 'label': 'SRWare Iron', 'pattern': 'Iron' }, - 'Sunrise', - 'Swiftfox', - 'Waterfox', - 'WebPositive', - 'Opera Mini', - { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, - 'Opera', - { 'label': 'Opera', 'pattern': 'OPR' }, - 'Chrome', - { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, - { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, - { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' }, - { 'label': 'IE', 'pattern': 'IEMobile' }, - { 'label': 'IE', 'pattern': 'MSIE' }, - 'Safari' - ]); - - /* Detectable products (order is important). */ - var product = getProduct([ - { 'label': 'BlackBerry', 'pattern': 'BB10' }, - 'BlackBerry', - { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, - { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, - { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, - { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, - { 'label': 'Galaxy S5', 'pattern': 'SM-G900' }, - { 'label': 'Galaxy S6', 'pattern': 'SM-G920' }, - { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' }, - { 'label': 'Galaxy S7', 'pattern': 'SM-G930' }, - { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' }, - 'Google TV', - 'Lumia', - 'iPad', - 'iPod', - 'iPhone', - 'Kindle', - { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Nexus', - 'Nook', - 'PlayBook', - 'PlayStation Vita', - 'PlayStation', - 'TouchPad', - 'Transformer', - { 'label': 'Wii U', 'pattern': 'WiiU' }, - 'Wii', - 'Xbox One', - { 'label': 'Xbox 360', 'pattern': 'Xbox' }, - 'Xoom' - ]); - - /* Detectable manufacturers. */ - var manufacturer = getManufacturer({ - 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, - 'Archos': {}, - 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, - 'Asus': { 'Transformer': 1 }, - 'Barnes & Noble': { 'Nook': 1 }, - 'BlackBerry': { 'PlayBook': 1 }, - 'Google': { 'Google TV': 1, 'Nexus': 1 }, - 'HP': { 'TouchPad': 1 }, - 'HTC': {}, - 'LG': {}, - 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, - 'Motorola': { 'Xoom': 1 }, - 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, - 'Nokia': { 'Lumia': 1 }, - 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, - 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 } - }); - - /* Detectable operating systems (order is important). */ - var os = getOS([ - 'Windows Phone', - 'Android', - 'CentOS', - { 'label': 'Chrome OS', 'pattern': 'CrOS' }, - 'Debian', - 'Fedora', - 'FreeBSD', - 'Gentoo', - 'Haiku', - 'Kubuntu', - 'Linux Mint', - 'OpenBSD', - 'Red Hat', - 'SuSE', - 'Ubuntu', - 'Xubuntu', - 'Cygwin', - 'Symbian OS', - 'hpwOS', - 'webOS ', - 'webOS', - 'Tablet OS', - 'Tizen', - 'Linux', - 'Mac OS X', - 'Macintosh', - 'Mac', - 'Windows 98;', - 'Windows ' - ]); - - /*------------------------------------------------------------------------*/ - - /** - * Picks the layout engine from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected layout engine. - */ - function getLayout(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the manufacturer from an array of guesses. - * - * @private - * @param {Array} guesses An object of guesses. - * @returns {null|string} The detected manufacturer. - */ - function getManufacturer(guesses) { - return reduce(guesses, function(result, value, key) { - // Lookup the manufacturer by product or scan the UA for the manufacturer. - return result || ( - value[product] || - value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || - RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) - ) && key; - }); - } - - /** - * Picks the browser name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected browser name. - */ - function getName(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the OS name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected OS name. - */ - function getOS(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) - )) { - result = cleanupOS(result, pattern, guess.label || guess); - } - return result; - }); - } - - /** - * Picks the product name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected product name. - */ - function getProduct(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || - RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) || - RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) - )) { - // Split by forward slash and append product version if needed. - if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { - result[0] += ' ' + result[1]; - } - // Correct character case and cleanup string. - guess = guess.label || guess; - result = format(result[0] - .replace(RegExp(pattern, 'i'), guess) - .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') - .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); - } - return result; - }); - } - - /** - * Resolves the version using an array of UA patterns. - * - * @private - * @param {Array} patterns An array of UA patterns. - * @returns {null|string} The detected version. - */ - function getVersion(patterns) { - return reduce(patterns, function(result, pattern) { - return result || (RegExp(pattern + - '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; - }); - } - - /** - * Returns `platform.description` when the platform object is coerced to a string. - * - * @name toString - * @memberOf platform - * @returns {string} Returns `platform.description` if available, else an empty string. - */ - function toStringPlatform() { - return this.description || ''; - } - - /*------------------------------------------------------------------------*/ - - // Convert layout to an array so we can add extra details. - layout && (layout = [layout]); - - // Detect product names that contain their manufacturer's name. - if (manufacturer && !product) { - product = getProduct([manufacturer]); - } - // Clean up Google TV. - if ((data = /\bGoogle TV\b/.exec(product))) { - product = data[0]; - } - // Detect simulators. - if (/\bSimulator\b/i.test(ua)) { - product = (product ? product + ' ' : '') + 'Simulator'; - } - // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. - if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { - description.push('running in Turbo/Uncompressed mode'); - } - // Detect IE Mobile 11. - if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) { - data = parse(ua.replace(/like iPhone OS/, '')); - manufacturer = data.manufacturer; - product = data.product; - } - // Detect iOS. - else if (/^iP/.test(product)) { - name || (name = 'Safari'); - os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) - ? ' ' + data[1].replace(/_/g, '.') - : ''); - } - // Detect Kubuntu. - else if (name == 'Konqueror' && !/buntu/i.test(os)) { - os = 'Kubuntu'; - } - // Detect Android browsers. - else if ((manufacturer && manufacturer != 'Google' && - ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) || - (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) { - name = 'Android Browser'; - os = /\bAndroid\b/.test(os) ? os : 'Android'; - } - // Detect Silk desktop/accelerated modes. - else if (name == 'Silk') { - if (!/\bMobi/i.test(ua)) { - os = 'Android'; - description.unshift('desktop mode'); - } - if (/Accelerated *= *true/i.test(ua)) { - description.unshift('accelerated'); - } - } - // Detect PaleMoon identifying as Firefox. - else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { - description.push('identifying as Firefox ' + data[1]); - } - // Detect Firefox OS and products running Firefox. - else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { - os || (os = 'Firefox OS'); - product || (product = data[1]); - } - // Detect false positives for Firefox/Safari. - else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { - // Escape the `/` for Firefox 1. - if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { - // Clear name of false positives. - name = null; - } - // Reassign a generic name. - if ((data = product || manufacturer || os) && - (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { - name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; - } - } - // Add Chrome version to description for Electron. - else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) { - description.push('Chromium ' + data); - } - // Detect non-Opera (Presto-based) versions (order is important). - if (!version) { - version = getVersion([ - '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))', - 'Version', - qualify(name), - '(?:Firefox|Minefield|NetFront)' - ]); - } - // Detect stubborn layout engines. - if ((data = - layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || - /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || - /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || - !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || - layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' - )) { - layout = [data]; - } - // Detect Windows Phone 7 desktop mode. - if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { - name += ' Mobile'; - os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); - description.unshift('desktop mode'); - } - // Detect Windows Phone 8.x desktop mode. - else if (/\bWPDesktop\b/i.test(ua)) { - name = 'IE Mobile'; - os = 'Windows Phone 8.x'; - description.unshift('desktop mode'); - version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); - } - // Detect IE 11 identifying as other browsers. - else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { - if (name) { - description.push('identifying as ' + name + (version ? ' ' + version : '')); - } - name = 'IE'; - version = data[1]; - } - // Leverage environment features. - if (useFeatures) { - // Detect server-side environments. - // Rhino has a global function while others have a global object. - if (isHostType(context, 'global')) { - if (java) { - data = java.lang.System; - arch = data.getProperty('os.arch'); - os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); - } - if (rhino) { - try { - version = context.require('ringo/engine').version.join('.'); - name = 'RingoJS'; - } catch(e) { - if ((data = context.system) && data.global.system == context.system) { - name = 'Narwhal'; - os || (os = data[0].os || null); - } - } - if (!name) { - name = 'Rhino'; - } - } - else if ( - typeof context.process == 'object' && !context.process.browser && - (data = context.process) - ) { - if (typeof data.versions == 'object') { - if (typeof data.versions.electron == 'string') { - description.push('Node ' + data.versions.node); - name = 'Electron'; - version = data.versions.electron; - } else if (typeof data.versions.nw == 'string') { - description.push('Chromium ' + version, 'Node ' + data.versions.node); - name = 'NW.js'; - version = data.versions.nw; - } - } - if (!name) { - name = 'Node.js'; - arch = data.arch; - os = data.platform; - version = /[\d.]+/.exec(data.version); - version = version ? version[0] : null; - } - } - } - // Detect Adobe AIR. - else if (getClassOf((data = context.runtime)) == airRuntimeClass) { - name = 'Adobe AIR'; - os = data.flash.system.Capabilities.os; - } - // Detect PhantomJS. - else if (getClassOf((data = context.phantom)) == phantomClass) { - name = 'PhantomJS'; - version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); - } - // Detect IE compatibility modes. - else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { - // We're in compatibility mode when the Trident version + 4 doesn't - // equal the document mode. - version = [version, doc.documentMode]; - if ((data = +data[1] + 4) != version[1]) { - description.push('IE ' + version[1] + ' mode'); - layout && (layout[1] = ''); - version[1] = data; - } - version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; - } - // Detect IE 11 masking as other browsers. - else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) { - description.push('masking as ' + name + ' ' + version); - name = 'IE'; - version = '11.0'; - layout = ['Trident']; - os = 'Windows'; - } - os = os && format(os); - } - // Detect prerelease phases. - if (version && (data = - /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || - /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || - /\bMinefield\b/i.test(ua) && 'a' - )) { - prerelease = /b/i.test(data) ? 'beta' : 'alpha'; - version = version.replace(RegExp(data + '\\+?$'), '') + - (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); - } - // Detect Firefox Mobile. - if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) { - name = 'Firefox Mobile'; - } - // Obscure Maxthon's unreliable version. - else if (name == 'Maxthon' && version) { - version = version.replace(/\.[\d.]+/, '.x'); - } - // Detect Xbox 360 and Xbox One. - else if (/\bXbox\b/i.test(product)) { - if (product == 'Xbox 360') { - os = null; - } - if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { - description.unshift('mobile mode'); - } - } - // Add mobile postfix. - else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && - (os == 'Windows CE' || /Mobi/i.test(ua))) { - name += ' Mobile'; - } - // Detect IE platform preview. - else if (name == 'IE' && useFeatures) { - try { - if (context.external === null) { - description.unshift('platform preview'); - } - } catch(e) { - description.unshift('embedded'); - } - } - // Detect BlackBerry OS version. - // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp - else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = - (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || - version - )) { - data = [data, /BB10/.test(ua)]; - os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; - version = null; - } - // Detect Opera identifying/masking itself as another browser. - // http://www.opera.com/support/kb/view/843/ - else if (this != forOwn && product != 'Wii' && ( - (useFeatures && opera) || - (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || - (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || - (name == 'IE' && ( - (os && !/^Win/.test(os) && version > 5.5) || - /\bWindows XP\b/.test(os) && version > 8 || - version == 8 && !/\bTrident\b/.test(ua) - )) - ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { - // When "identifying", the UA contains both Opera and the other browser's name. - data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); - if (reOpera.test(name)) { - if (/\bIE\b/.test(data) && os == 'Mac OS') { - os = null; - } - data = 'identify' + data; - } - // When "masking", the UA contains only the other browser's name. - else { - data = 'mask' + data; - if (operaClass) { - name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); - } else { - name = 'Opera'; - } - if (/\bIE\b/.test(data)) { - os = null; - } - if (!useFeatures) { - version = null; - } - } - layout = ['Presto']; - description.push(data); - } - // Detect WebKit Nightly and approximate Chrome/Safari versions. - if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - // Correct build number for numeric comparison. - // (e.g. "532.5" becomes "532.05") - data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; - // Nightly builds are postfixed with a "+". - if (name == 'Safari' && data[1].slice(-1) == '+') { - name = 'WebKit Nightly'; - prerelease = 'alpha'; - version = data[1].slice(0, -1); - } - // Clear incorrect browser versions. - else if (version == data[1] || - version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - version = null; - } - // Use the full Chrome version when available. - data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]; - // Detect Blink layout engine. - if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { - layout = ['Blink']; - } - // Detect JavaScriptCore. - // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi - if (!useFeatures || (!likeChrome && !data[1])) { - layout && (layout[1] = 'like Safari'); - data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8'); - } else { - layout && (layout[1] = 'like Chrome'); - data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); - } - // Add the postfix of ".x" or "+" for approximate versions. - layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); - // Obscure version for some Safari 1-2 releases. - if (name == 'Safari' && (!version || parseInt(version) > 45)) { - version = data; - } - } - // Detect Opera desktop modes. - if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { - name += ' '; - description.unshift('desktop mode'); - if (data == 'zvav') { - name += 'Mini'; - version = null; - } else { - name += 'Mobile'; - } - os = os.replace(RegExp(' *' + data + '$'), ''); - } - // Detect Chrome desktop mode. - else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { - description.unshift('desktop mode'); - name = 'Chrome Mobile'; - version = null; - - if (/\bOS X\b/.test(os)) { - manufacturer = 'Apple'; - os = 'iOS 4.3+'; - } else { - os = null; - } - } - // Strip incorrect OS versions. - if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && - ua.indexOf('/' + data + '-') > -1) { - os = trim(os.replace(data, '')); - } - // Add layout engine. - if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( - /Browser|Lunascape|Maxthon/.test(name) || - name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || - /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) { - // Don't add layout details to description if they are falsey. - (data = layout[layout.length - 1]) && description.push(data); - } - // Combine contextual information. - if (description.length) { - description = ['(' + description.join('; ') + ')']; - } - // Append manufacturer to description. - if (manufacturer && product && product.indexOf(manufacturer) < 0) { - description.push('on ' + manufacturer); - } - // Append product to description. - if (product) { - description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); - } - // Parse the OS into an object. - if (os) { - data = / ([\d.+]+)$/.exec(os); - isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; - os = { - 'architecture': 32, - 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, - 'version': data ? data[1] : null, - 'toString': function() { - var version = this.version; - return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); - } - }; - } - // Add browser/OS architecture. - if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { - if (os) { - os.architecture = 64; - os.family = os.family.replace(RegExp(' *' + data), ''); - } - if ( - name && (/\bWOW64\b/i.test(ua) || - (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) - ) { - description.unshift('32-bit'); - } - } - // Chrome 39 and above on OS X is always 64-bit. - else if ( - os && /^OS X/.test(os.family) && - name == 'Chrome' && parseFloat(version) >= 39 - ) { - os.architecture = 64; - } - - ua || (ua = null); - - /*------------------------------------------------------------------------*/ - - /** - * The platform object. - * - * @name platform - * @type Object - */ - var platform = {}; - - /** - * The platform description. - * - * @memberOf platform - * @type string|null - */ - platform.description = ua; - - /** - * The name of the browser's layout engine. - * - * The list of common layout engines include: - * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit" - * - * @memberOf platform - * @type string|null - */ - platform.layout = layout && layout[0]; - - /** - * The name of the product's manufacturer. - * - * The list of manufacturers include: - * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry", - * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo", - * "Nokia", "Samsung" and "Sony" - * - * @memberOf platform - * @type string|null - */ - platform.manufacturer = manufacturer; - - /** - * The name of the browser/environment. - * - * The list of common browser names include: - * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE", - * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk", - * "Opera Mini" and "Opera" - * - * Mobile versions of some browsers have "Mobile" appended to their name: - * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile" - * - * @memberOf platform - * @type string|null - */ - platform.name = name; - - /** - * The alpha/beta release indicator. - * - * @memberOf platform - * @type string|null - */ - platform.prerelease = prerelease; - - /** - * The name of the product hosting the browser. - * - * The list of common products include: - * - * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle", - * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer" - * - * @memberOf platform - * @type string|null - */ - platform.product = product; - - /** - * The browser's user agent string. - * - * @memberOf platform - * @type string|null - */ - platform.ua = ua; - - /** - * The browser/environment version. - * - * @memberOf platform - * @type string|null - */ - platform.version = name && version; - - /** - * The name of the operating system. - * - * @memberOf platform - * @type Object - */ - platform.os = os || { - - /** - * The CPU architecture the OS is built for. - * - * @memberOf platform.os - * @type number|null - */ - 'architecture': null, - - /** - * The family of the OS. - * - * Common values include: - * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", - * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", - * "Android", "iOS" and "Windows Phone" - * - * @memberOf platform.os - * @type string|null - */ - 'family': null, - - /** - * The version of the OS. - * - * @memberOf platform.os - * @type string|null - */ - 'version': null, - - /** - * Returns the OS string. - * - * @memberOf platform.os - * @returns {string} The OS string. - */ - 'toString': function() { return 'null'; } - }; - - platform.parse = parse; - platform.toString = toStringPlatform; - - if (platform.version) { - description.unshift(version); - } - if (platform.name) { - description.unshift(name); - } - if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { - description.push(product ? '(' + os + ')' : 'on ' + os); - } - if (description.length) { - platform.description = description.join(' '); - } - return platform; - } - - /*--------------------------------------------------------------------------*/ - - // Export platform. - var platform = parse(); - - // Some AMD build optimizers, like r.js, check for condition patterns like the following: - if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose platform on the global object to prevent errors when platform is - // loaded by a script tag in the presence of an AMD loader. - // See http://requirejs.org/docs/errors.html#mismatch for more details. - root.platform = platform; - - // Define as an anonymous module so platform can be aliased through path mapping. - define(function() { - return platform; - }); - } - // Check for `exports` after `define` in case a build optimizer adds an `exports` object. - else if (freeExports && freeModule) { - // Export for CommonJS support. - forOwn(platform, function(value, key) { - freeExports[key] = value; - }); - } - else { - // Export to the global object. - root.platform = platform; - } -}.call(this)); - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],10:[function(require,module,exports){ -var grammar = module.exports = { - v: [{ - name: 'version', - reg: /^(\d*)$/ - }], - o: [{ //o=- 20518 0 IN IP4 203.0.113.1 - // NB: sessionId will be a String in most cases because it is huge - name: 'origin', - reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, - names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], - format: "%s %s %d %s IP%d %s" - }], - // default parsing of these only (though some of these feel outdated) - s: [{ name: 'name' }], - i: [{ name: 'description' }], - u: [{ name: 'uri' }], - e: [{ name: 'email' }], - p: [{ name: 'phone' }], - z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly.. - r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly - //k: [{}], // outdated thing ignored - t: [{ //t=0 0 - name: 'timing', - reg: /^(\d*) (\d*)/, - names: ['start', 'stop'], - format: "%d %d" - }], - c: [{ //c=IN IP4 10.47.197.26 - name: 'connection', - reg: /^IN IP(\d) (\S*)/, - names: ['version', 'ip'], - format: "IN IP%d %s" - }], - b: [{ //b=AS:4000 - push: 'bandwidth', - reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, - names: ['type', 'limit'], - format: "%s:%s" - }], - m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31 - // NB: special - pushes to session - // TODO: rtp/fmtp should be filtered by the payloads found here? - reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/, - names: ['type', 'port', 'protocol', 'payloads'], - format: "%s %d %s %s" - }], - a: [ - { //a=rtpmap:110 opus/48000/2 - push: 'rtp', - reg: /^rtpmap:(\d*) ([\w\-]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, - names: ['payload', 'codec', 'rate', 'encoding'], - format: function (o) { - return (o.encoding) ? - "rtpmap:%d %s/%s/%s": - o.rate ? - "rtpmap:%d %s/%s": - "rtpmap:%d %s"; - } - }, - { - //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 - //a=fmtp:111 minptime=10; useinbandfec=1 - push: 'fmtp', - reg: /^fmtp:(\d*) ([\S| ]*)/, - names: ['payload', 'config'], - format: "fmtp:%d %s" - }, - { //a=control:streamid=0 - name: 'control', - reg: /^control:(.*)/, - format: "control:%s" - }, - { //a=rtcp:65179 IN IP4 193.84.77.194 - name: 'rtcp', - reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, - names: ['port', 'netType', 'ipVer', 'address'], - format: function (o) { - return (o.address != null) ? - "rtcp:%d %s IP%d %s": - "rtcp:%d"; - } - }, - { //a=rtcp-fb:98 trr-int 100 - push: 'rtcpFbTrrInt', - reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, - names: ['payload', 'value'], - format: "rtcp-fb:%d trr-int %d" - }, - { //a=rtcp-fb:98 nack rpsi - push: 'rtcpFb', - reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, - names: ['payload', 'type', 'subtype'], - format: function (o) { - return (o.subtype != null) ? - "rtcp-fb:%s %s %s": - "rtcp-fb:%s %s"; - } - }, - { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset - //a=extmap:1/recvonly URI-gps-string - push: 'ext', - reg: /^extmap:([\w_\/]*) (\S*)(?: (\S*))?/, - names: ['value', 'uri', 'config'], // value may include "/direction" suffix - format: function (o) { - return (o.config != null) ? - "extmap:%s %s %s": - "extmap:%s %s"; - } - }, - { - //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 - push: 'crypto', - reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, - names: ['id', 'suite', 'config', 'sessionConfig'], - format: function (o) { - return (o.sessionConfig != null) ? - "crypto:%d %s %s %s": - "crypto:%d %s %s"; - } - }, - { //a=setup:actpass - name: 'setup', - reg: /^setup:(\w*)/, - format: "setup:%s" - }, - { //a=mid:1 - name: 'mid', - reg: /^mid:([^\s]*)/, - format: "mid:%s" - }, - { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a - name: 'msid', - reg: /^msid:(.*)/, - format: "msid:%s" - }, - { //a=ptime:20 - name: 'ptime', - reg: /^ptime:(\d*)/, - format: "ptime:%d" - }, - { //a=maxptime:60 - name: 'maxptime', - reg: /^maxptime:(\d*)/, - format: "maxptime:%d" - }, - { //a=sendrecv - name: 'direction', - reg: /^(sendrecv|recvonly|sendonly|inactive)/ - }, - { //a=ice-lite - name: 'icelite', - reg: /^(ice-lite)/ - }, - { //a=ice-ufrag:F7gI - name: 'iceUfrag', - reg: /^ice-ufrag:(\S*)/, - format: "ice-ufrag:%s" - }, - { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g - name: 'icePwd', - reg: /^ice-pwd:(\S*)/, - format: "ice-pwd:%s" - }, - { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 - name: 'fingerprint', - reg: /^fingerprint:(\S*) (\S*)/, - names: ['type', 'hash'], - format: "fingerprint:%s %s" - }, - { - //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host - //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 - //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 - //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 - //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 - push:'candidates', - reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?/, - names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation'], - format: function (o) { - var str = "candidate:%s %d %s %d %s %d typ %s"; - - str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v"; - - // NB: candidate has three optional chunks, so %void middles one if it's missing - str += (o.tcptype != null) ? " tcptype %s" : "%v"; - - if (o.generation != null) { - str += " generation %d"; - } - return str; - } - }, - { //a=end-of-candidates (keep after the candidates line for readability) - name: 'endOfCandidates', - reg: /^(end-of-candidates)/ - }, - { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... - name: 'remoteCandidates', - reg: /^remote-candidates:(.*)/, - format: "remote-candidates:%s" - }, - { //a=ice-options:google-ice - name: 'iceOptions', - reg: /^ice-options:(\S*)/, - format: "ice-options:%s" - }, - { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 - push: "ssrcs", - reg: /^ssrc:(\d*) ([\w_]*):(.*)/, - names: ['id', 'attribute', 'value'], - format: "ssrc:%d %s:%s" - }, - { //a=ssrc-group:FEC 1 2 - push: "ssrcGroups", - reg: /^ssrc-group:(\w*) (.*)/, - names: ['semantics', 'ssrcs'], - format: "ssrc-group:%s %s" - }, - { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV - name: "msidSemantic", - reg: /^msid-semantic:\s?(\w*) (\S*)/, - names: ['semantic', 'token'], - format: "msid-semantic: %s %s" // space after ":" is not accidental - }, - { //a=group:BUNDLE audio video - push: 'groups', - reg: /^group:(\w*) (.*)/, - names: ['type', 'mids'], - format: "group:%s %s" - }, - { //a=rtcp-mux - name: 'rtcpMux', - reg: /^(rtcp-mux)/ - }, - { //a=rtcp-rsize - name: 'rtcpRsize', - reg: /^(rtcp-rsize)/ - }, - { // any a= that we don't understand is kepts verbatim on media.invalid - push: 'invalid', - names: ["value"] - } - ] -}; - -// set sensible defaults to avoid polluting the grammar with boring details -Object.keys(grammar).forEach(function (key) { - var objs = grammar[key]; - objs.forEach(function (obj) { - if (!obj.reg) { - obj.reg = /(.*)/; - } - if (!obj.format) { - obj.format = "%s"; - } - }); -}); - -},{}],11:[function(require,module,exports){ -var parser = require('./parser'); -var writer = require('./writer'); - -exports.write = writer; -exports.parse = parser.parse; -exports.parseFmtpConfig = parser.parseFmtpConfig; -exports.parsePayloads = parser.parsePayloads; -exports.parseRemoteCandidates = parser.parseRemoteCandidates; - -},{"./parser":12,"./writer":13}],12:[function(require,module,exports){ -var toIntIfInt = function (v) { - return String(Number(v)) === v ? Number(v) : v; -}; - -var attachProperties = function (match, location, names, rawName) { - if (rawName && !names) { - location[rawName] = toIntIfInt(match[1]); - } - else { - for (var i = 0; i < names.length; i += 1) { - if (match[i+1] != null) { - location[names[i]] = toIntIfInt(match[i+1]); - } - } - } -}; - -var parseReg = function (obj, location, content) { - var needsBlank = obj.name && obj.names; - if (obj.push && !location[obj.push]) { - location[obj.push] = []; - } - else if (needsBlank && !location[obj.name]) { - location[obj.name] = {}; - } - var keyLocation = obj.push ? - {} : // blank object that will be pushed - needsBlank ? location[obj.name] : location; // otherwise, named location or root - - attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name); - - if (obj.push) { - location[obj.push].push(keyLocation); - } -}; - -var grammar = require('./grammar'); -var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/); - -exports.parse = function (sdp) { - var session = {} - , media = [] - , location = session; // points at where properties go under (one of the above) - - // parse lines we understand - sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) { - var type = l[0]; - var content = l.slice(2); - if (type === 'm') { - media.push({rtp: [], fmtp: []}); - location = media[media.length-1]; // point at latest media line - } - - for (var j = 0; j < (grammar[type] || []).length; j += 1) { - var obj = grammar[type][j]; - if (obj.reg.test(content)) { - return parseReg(obj, location, content); - } - } - }); - - session.media = media; // link it up - return session; -}; - -var fmtpReducer = function (acc, expr) { - var s = expr.split('='); - if (s.length === 2) { - acc[s[0]] = toIntIfInt(s[1]); - } - return acc; -}; - -exports.parseFmtpConfig = function (str) { - return str.split(/\;\s?/).reduce(fmtpReducer, {}); -}; - -exports.parsePayloads = function (str) { - return str.split(' ').map(Number); -}; - -exports.parseRemoteCandidates = function (str) { - var candidates = []; - var parts = str.split(' ').map(toIntIfInt); - for (var i = 0; i < parts.length; i += 3) { - candidates.push({ - component: parts[i], - ip: parts[i + 1], - port: parts[i + 2] - }); - } - return candidates; -}; - -},{"./grammar":10}],13:[function(require,module,exports){ -var grammar = require('./grammar'); - -// customized util.format - discards excess arguments and can void middle ones -var formatRegExp = /%[sdv%]/g; -var format = function (formatStr) { - var i = 1; - var args = arguments; - var len = args.length; - return formatStr.replace(formatRegExp, function (x) { - if (i >= len) { - return x; // missing argument - } - var arg = args[i]; - i += 1; - switch (x) { - case '%%': - return '%'; - case '%s': - return String(arg); - case '%d': - return Number(arg); - case '%v': - return ''; - } - }); - // NB: we discard excess arguments - they are typically undefined from makeLine -}; - -var makeLine = function (type, obj, location) { - var str = obj.format instanceof Function ? - (obj.format(obj.push ? location : location[obj.name])) : - obj.format; - - var args = [type + '=' + str]; - if (obj.names) { - for (var i = 0; i < obj.names.length; i += 1) { - var n = obj.names[i]; - if (obj.name) { - args.push(location[obj.name][n]); - } - else { // for mLine and push attributes - args.push(location[obj.names[i]]); - } - } - } - else { - args.push(location[obj.name]); - } - return format.apply(null, args); -}; - -// RFC specified order -// TODO: extend this with all the rest -var defaultOuterOrder = [ - 'v', 'o', 's', 'i', - 'u', 'e', 'p', 'c', - 'b', 't', 'r', 'z', 'a' -]; -var defaultInnerOrder = ['i', 'c', 'b', 'a']; - - -module.exports = function (session, opts) { - opts = opts || {}; - // ensure certain properties exist - if (session.version == null) { - session.version = 0; // "v=0" must be there (only defined version atm) - } - if (session.name == null) { - session.name = " "; // "s= " must be there if no meaningful name set - } - session.media.forEach(function (mLine) { - if (mLine.payloads == null) { - mLine.payloads = ""; - } - }); - - var outerOrder = opts.outerOrder || defaultOuterOrder; - var innerOrder = opts.innerOrder || defaultInnerOrder; - var sdp = []; - - // loop through outerOrder for matching properties on session - outerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in session && session[obj.name] != null) { - sdp.push(makeLine(type, obj, session)); - } - else if (obj.push in session && session[obj.push] != null) { - session[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - - // then for each media line, follow the innerOrder - session.media.forEach(function (mLine) { - sdp.push(makeLine('m', grammar.m[0], mLine)); - - innerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in mLine && mLine[obj.name] != null) { - sdp.push(makeLine(type, obj, mLine)); - } - else if (obj.push in mLine && mLine[obj.push] != null) { - mLine[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - }); - - return sdp.join('\r\n') + '\r\n'; -}; - -},{"./grammar":10}],14:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -module.exports = function arrayEquals(array) { - // if the other array is a falsy value, return - if (!array) - return false; - - // compare lengths - can save a lot of time - if (this.length != array.length) - return false; - - for (var i = 0, l = this.length; i < l; i++) { - // Check if we have nested arrays - if (this[i] instanceof Array && array[i] instanceof Array) { - // recurse into the nested arrays - if (!arrayEquals.apply(this[i], [array[i]])) - return false; - } else if (this[i] != array[i]) { - // Warning - two different object instances will never be equal: - // {x:20} != {x:20} - return false; - } - } - return true; -}; - - -},{}],15:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -exports.Interop = require('./interop'); - -},{"./interop":16}],16:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* global RTCSessionDescription */ -/* global RTCIceCandidate */ -/* jshint -W097 */ -"use strict"; - -var transform = require('./transform'); -var arrayEquals = require('./array-equals'); - -function Interop() { - - /** - * This map holds the most recent Unified Plan offer/answer SDP that was - * converted to Plan B, with the SDP type ('offer' or 'answer') as keys and - * the SDP string as values. - * - * @type {{}} - */ - this.cache = { - mlB2UMap : {}, - mlU2BMap : {} - }; -} - -module.exports = Interop; - -/** - * Changes the candidate args to match with the related Unified Plan - */ -Interop.prototype.candidateToUnifiedPlan = function(candidate) { - var cand = new RTCIceCandidate(candidate); - - cand.sdpMLineIndex = this.cache.mlB2UMap[cand.sdpMLineIndex]; - /* TODO: change sdpMid to (audio|video)-SSRC */ - - return cand; -}; - -/** - * Changes the candidate args to match with the related Plan B - */ -Interop.prototype.candidateToPlanB = function(candidate) { - var cand = new RTCIceCandidate(candidate); - - if (cand.sdpMid.indexOf('audio') === 0) { - cand.sdpMid = 'audio'; - } else if (cand.sdpMid.indexOf('video') === 0) { - cand.sdpMid = 'video'; - } else { - throw new Error('candidate with ' + cand.sdpMid + ' not allowed'); - } - - cand.sdpMLineIndex = this.cache.mlU2BMap[cand.sdpMLineIndex]; - - return cand; -}; - -/** - * Returns the index of the first m-line with the given media type and with a - * direction which allows sending, in the last Unified Plan description with - * type "answer" converted to Plan B. Returns {null} if there is no saved - * answer, or if none of its m-lines with the given type allow sending. - * @param type the media type ("audio" or "video"). - * @returns {*} - */ -Interop.prototype.getFirstSendingIndexFromAnswer = function(type) { - if (!this.cache.answer) { - return null; - } - - var session = transform.parse(this.cache.answer); - if (session && session.media && Array.isArray(session.media)){ - for (var i = 0; i < session.media.length; i++) { - if (session.media[i].type == type && - (!session.media[i].direction /* default to sendrecv */ || - session.media[i].direction === 'sendrecv' || - session.media[i].direction === 'sendonly')){ - return i; - } - } - } - - return null; -}; - -/** - * This method transforms a Unified Plan SDP to an equivalent Plan B SDP. A - * PeerConnection wrapper transforms the SDP to Plan B before passing it to the - * application. - * - * @param desc - * @returns {*} - */ -Interop.prototype.toPlanB = function(desc) { - var self = this; - //#region Preliminary input validation. - - if (typeof desc !== 'object' || desc === null || - typeof desc.sdp !== 'string') { - console.warn('An empty description was passed as an argument.'); - return desc; - } - - // Objectify the SDP for easier manipulation. - var session = transform.parse(desc.sdp); - - // If the SDP contains no media, there's nothing to transform. - if (typeof session.media === 'undefined' || - !Array.isArray(session.media) || session.media.length === 0) { - console.warn('The description has no media.'); - return desc; - } - - // Try some heuristics to "make sure" this is a Unified Plan SDP. Plan B - // SDP has a video, an audio and a data "channel" at most. - if (session.media.length <= 3 && session.media.every(function(m) { - return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; - })) { - console.warn('This description does not look like Unified Plan.'); - return desc; - } - - //#endregion - - // HACK https://bugzilla.mozilla.org/show_bug.cgi?id=1113443 - var sdp = desc.sdp; - var rewrite = false; - for (var i = 0; i < session.media.length; i++) { - var uLine = session.media[i]; - uLine.rtp.forEach(function(rtp) { - if (rtp.codec === 'NULL') - { - rewrite = true; - var offer = transform.parse(self.cache.offer); - rtp.codec = offer.media[i].rtp[0].codec; - } - }); - } - if (rewrite) { - sdp = transform.write(session); - } - - // Unified Plan SDP is our "precious". Cache it for later use in the Plan B - // -> Unified Plan transformation. - this.cache[desc.type] = sdp; - - //#region Convert from Unified Plan to Plan B. - - // We rebuild the session.media array. - var media = session.media; - session.media = []; - - // Associative array that maps channel types to channel objects for fast - // access to channel objects by their type, e.g. type2bl['audio']->channel - // obj. - var type2bl = {}; - - // Used to build the group:BUNDLE value after the channels construction - // loop. - var types = []; - - media.forEach(function(uLine) { - // rtcp-mux is required in the Plan B SDP. - if ((typeof uLine.rtcpMux !== 'string' || - uLine.rtcpMux !== 'rtcp-mux') && - uLine.direction !== 'inactive') { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'without the rtcp-mux attribute were found.'); - } - - // If we don't have a channel for this uLine.type OR the selected is - // inactive, then select this uLine as the channel basis. - if (typeof type2bl[uLine.type] === 'undefined' || - type2bl[uLine.type].direction === 'inactive') { - type2bl[uLine.type] = uLine; - } - - if (uLine.protocol != type2bl[uLine.type].protocol) { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'have different protocols and this library does not have ' + - 'support for that'); - } - - if (uLine.payloads != type2bl[uLine.type].payloads) { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'have different payloads and this library does not have ' + - 'support for that'); - } - - }); - - // Implode the Unified Plan m-lines/tracks into Plan B channels. - media.forEach(function(uLine) { - if (uLine.type === 'application') { - session.media.push(uLine); - types.push(uLine.mid); - return; - } - - // Add sources to the channel and handle a=msid. - if (typeof uLine.sources === 'object') { - Object.keys(uLine.sources).forEach(function(ssrc) { - if (typeof type2bl[uLine.type].sources !== 'object') - type2bl[uLine.type].sources = {}; - - // Assign the sources to the channel. - type2bl[uLine.type].sources[ssrc] = - uLine.sources[ssrc]; - - if (typeof uLine.msid !== 'undefined') { - // In Plan B the msid is an SSRC attribute. Also, we don't - // care about the obsolete label and mslabel attributes. - // - // Note that it is not guaranteed that the uLine will - // have an msid. recvonly channels in particular don't have - // one. - type2bl[uLine.type].sources[ssrc].msid = - uLine.msid; - } - // NOTE ssrcs in ssrc groups will share msids, as - // draft-uberti-rtcweb-plan-00 mandates. - }); - } - - // Add ssrc groups to the channel. - if (typeof uLine.ssrcGroups !== 'undefined' && - Array.isArray(uLine.ssrcGroups)) { - - // Create the ssrcGroups array, if it's not defined. - if (typeof type2bl[uLine.type].ssrcGroups === 'undefined' || - !Array.isArray(type2bl[uLine.type].ssrcGroups)) { - type2bl[uLine.type].ssrcGroups = []; - } - - type2bl[uLine.type].ssrcGroups = - type2bl[uLine.type].ssrcGroups.concat( - uLine.ssrcGroups); - } - - if (type2bl[uLine.type] === uLine) { - // Plan B mids are in ['audio', 'video', 'data'] - uLine.mid = uLine.type; - - // Plan B doesn't support/need the bundle-only attribute. - delete uLine.bundleOnly; - - // In Plan B the msid is an SSRC attribute. - delete uLine.msid; - - if (uLine.type == media[0].type) { - types.unshift(uLine.type); - // Add the channel to the new media array. - session.media.unshift(uLine); - } else { - types.push(uLine.type); - // Add the channel to the new media array. - session.media.push(uLine); - } - } - }); - - if (typeof session.groups !== 'undefined') { - // We regenerate the BUNDLE group with the new mids. - session.groups.some(function(group) { - if (group.type === 'BUNDLE') { - group.mids = types.join(' '); - return true; - } - }); - } - - // msid semantic - session.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - var resStr = transform.write(session); - - return new RTCSessionDescription({ - type: desc.type, - sdp: resStr - }); - - //#endregion -}; - -/* follow rules defined in RFC4145 */ -function addSetupAttr(uLine) { - if (typeof uLine.setup === 'undefined') { - return; - } - - if (uLine.setup === "active") { - uLine.setup = "passive"; - } else if (uLine.setup === "passive") { - uLine.setup = "active"; - } -} - -/** - * This method transforms a Plan B SDP to an equivalent Unified Plan SDP. A - * PeerConnection wrapper transforms the SDP to Unified Plan before passing it - * to FF. - * - * @param desc - * @returns {*} - */ -Interop.prototype.toUnifiedPlan = function(desc) { - var self = this; - //#region Preliminary input validation. - - if (typeof desc !== 'object' || desc === null || - typeof desc.sdp !== 'string') { - console.warn('An empty description was passed as an argument.'); - return desc; - } - - var session = transform.parse(desc.sdp); - - // If the SDP contains no media, there's nothing to transform. - if (typeof session.media === 'undefined' || - !Array.isArray(session.media) || session.media.length === 0) { - console.warn('The description has no media.'); - return desc; - } - - // Try some heuristics to "make sure" this is a Plan B SDP. Plan B SDP has - // a video, an audio and a data "channel" at most. - if (session.media.length > 3 || !session.media.every(function(m) { - return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; - })) { - console.warn('This description does not look like Plan B.'); - return desc; - } - - // Make sure this Plan B SDP can be converted to a Unified Plan SDP. - var mids = []; - session.media.forEach(function(m) { - mids.push(m.mid); - }); - - var hasBundle = false; - if (typeof session.groups !== 'undefined' && - Array.isArray(session.groups)) { - hasBundle = session.groups.every(function(g) { - return g.type !== 'BUNDLE' || - arrayEquals.apply(g.mids.sort(), [mids.sort()]); - }); - } - - if (!hasBundle) { - var mustBeBundle = false; - - session.media.forEach(function(m) { - if (m.direction !== 'inactive') { - mustBeBundle = true; - } - }); - - if (mustBeBundle) { - throw new Error("Cannot convert to Unified Plan because m-lines that" + - " are not bundled were found."); - } - } - - //#endregion - - - //#region Convert from Plan B to Unified Plan. - - // Unfortunately, a Plan B offer/answer doesn't have enough information to - // rebuild an equivalent Unified Plan offer/answer. - // - // For example, if this is a local answer (in Unified Plan style) that we - // convert to Plan B prior to handing it over to the application (the - // PeerConnection wrapper called us, for instance, after a successful - // createAnswer), we want to remember the m-line at which we've seen the - // (local) SSRC. That's because when the application wants to do call the - // SLD method, forcing us to do the inverse transformation (from Plan B to - // Unified Plan), we need to know to which m-line to assign the (local) - // SSRC. We also need to know all the other m-lines that the original - // answer had and include them in the transformed answer as well. - // - // Another example is if this is a remote offer that we convert to Plan B - // prior to giving it to the application, we want to remember the mid at - // which we've seen the (remote) SSRC. - // - // In the iteration that follows, we use the cached Unified Plan (if it - // exists) to assign mids to ssrcs. - - var type; - if (desc.type === 'answer') { - type = 'offer'; - } else if (desc.type === 'offer') { - type = 'answer'; - } else { - throw new Error("Type '" + desc.type + "' not supported."); - } - - var cached; - if (typeof this.cache[type] !== 'undefined') { - cached = transform.parse(this.cache[type]); - } - - var recvonlySsrcs = { - audio: {}, - video: {} - }; - - // A helper map that sends mids to m-line objects. We use it later to - // rebuild the Unified Plan style session.media array. - var mid2ul = {}; - var bIdx = 0; - var uIdx = 0; - - var sources2ul = {}; - - var candidates; - var iceUfrag; - var icePwd; - var fingerprint; - var payloads = {}; - var rtcpFb = {}; - var rtp = {}; - - session.media.forEach(function(bLine) { - if ((typeof bLine.rtcpMux !== 'string' || - bLine.rtcpMux !== 'rtcp-mux') && - bLine.direction !== 'inactive') { - throw new Error("Cannot convert to Unified Plan because m-lines " + - "without the rtcp-mux attribute were found."); - } - - if (bLine.type === 'application') { - mid2ul[bLine.mid] = bLine; - return; - } - - // With rtcp-mux and bundle all the channels should have the same ICE - // stuff. - var sources = bLine.sources; - var ssrcGroups = bLine.ssrcGroups; - var port = bLine.port; - - /* Chrome adds different candidates even using bundle, so we concat the candidates list */ - if (typeof bLine.candidates != 'undefined') { - if (typeof candidates != 'undefined') { - candidates = candidates.concat(bLine.candidates); - } else { - candidates = bLine.candidates; - } - } - - if ((typeof iceUfrag != 'undefined') && (typeof bLine.iceUfrag != 'undefined') && (iceUfrag != bLine.iceUfrag)) { - throw new Error("Only BUNDLE supported, iceUfrag must be the same for all m-lines.\n" + - "\tLast iceUfrag: " + iceUfrag + "\n" + - "\tNew iceUfrag: " + bLine.iceUfrag - ); - } - - if (typeof bLine.iceUfrag != 'undefined') { - iceUfrag = bLine.iceUfrag; - } - - if ((typeof icePwd != 'undefined') && (typeof bLine.icePwd != 'undefined') && (icePwd != bLine.icePwd)) { - throw new Error("Only BUNDLE supported, icePwd must be the same for all m-lines.\n" + - "\tLast icePwd: " + icePwd + "\n" + - "\tNew icePwd: " + bLine.icePwd - ); - } - - if (typeof bLine.icePwd != 'undefined') { - icePwd = bLine.icePwd; - } - - if ((typeof fingerprint != 'undefined') && (typeof bLine.fingerprint != 'undefined') && - (fingerprint.type != bLine.fingerprint.type || fingerprint.hash != bLine.fingerprint.hash)) { - throw new Error("Only BUNDLE supported, fingerprint must be the same for all m-lines.\n" + - "\tLast fingerprint: " + JSON.stringify(fingerprint) + "\n" + - "\tNew fingerprint: " + JSON.stringify(bLine.fingerprint) - ); - } - - if (typeof bLine.fingerprint != 'undefined') { - fingerprint = bLine.fingerprint; - } - - payloads[bLine.type] = bLine.payloads; - rtcpFb[bLine.type] = bLine.rtcpFb; - rtp[bLine.type] = bLine.rtp; - - // inverted ssrc group map - var ssrc2group = {}; - if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) { - ssrcGroups.forEach(function (ssrcGroup) { - // XXX This might brake if an SSRC is in more than one group - // for some reason. - if (typeof ssrcGroup.ssrcs !== 'undefined' && - Array.isArray(ssrcGroup.ssrcs)) { - ssrcGroup.ssrcs.forEach(function (ssrc) { - if (typeof ssrc2group[ssrc] === 'undefined') { - ssrc2group[ssrc] = []; - } - - ssrc2group[ssrc].push(ssrcGroup); - }); - } - }); - } - - // ssrc to m-line index. - var ssrc2ml = {}; - - if (typeof sources === 'object') { - - // We'll use the "bLine" object as a prototype for each new "mLine" - // that we create, but first we need to clean it up a bit. - delete bLine.sources; - delete bLine.ssrcGroups; - delete bLine.candidates; - delete bLine.iceUfrag; - delete bLine.icePwd; - delete bLine.fingerprint; - delete bLine.port; - delete bLine.mid; - - // Explode the Plan B channel sources with one m-line per source. - Object.keys(sources).forEach(function(ssrc) { - - // The (unified) m-line for this SSRC. We either create it from - // scratch or, if it's a grouped SSRC, we re-use a related - // mline. In other words, if the source is grouped with another - // source, put the two together in the same m-line. - var uLine; - - // We assume here that we are the answerer in the O/A, so any - // offers which we translate come from the remote side, while - // answers are local. So the check below is to make that we - // handle receive-only SSRCs in a special way only if they come - // from the remote side. - if (desc.type==='offer') { - // We want to detect SSRCs which are used by a remote peer - // in an m-line with direction=recvonly (i.e. they are - // being used for RTCP only). - // This information would have gotten lost if the remote - // peer used Unified Plan and their local description was - // translated to Plan B. So we use the lack of an MSID - // attribute to deduce a "receive only" SSRC. - if (!sources[ssrc].msid) { - recvonlySsrcs[bLine.type][ssrc] = sources[ssrc]; - // Receive-only SSRCs must not create new m-lines. We - // will assign them to an existing m-line later. - return; - } - } - - if (typeof ssrc2group[ssrc] !== 'undefined' && - Array.isArray(ssrc2group[ssrc])) { - ssrc2group[ssrc].some(function (ssrcGroup) { - // ssrcGroup.ssrcs *is* an Array, no need to check - // again here. - return ssrcGroup.ssrcs.some(function (related) { - if (typeof ssrc2ml[related] === 'object') { - uLine = ssrc2ml[related]; - return true; - } - }); - }); - } - - if (typeof uLine === 'object') { - // the m-line already exists. Just add the source. - uLine.sources[ssrc] = sources[ssrc]; - delete sources[ssrc].msid; - } else { - // Use the "bLine" as a prototype for the "uLine". - uLine = Object.create(bLine); - ssrc2ml[ssrc] = uLine; - - if (typeof sources[ssrc].msid !== 'undefined') { - // Assign the msid of the source to the m-line. Note - // that it is not guaranteed that the source will have - // msid. In particular "recvonly" sources don't have an - // msid. Note that "recvonly" is a term only defined - // for m-lines. - uLine.msid = sources[ssrc].msid; - delete sources[ssrc].msid; - } - - // We assign one SSRC per media line. - uLine.sources = {}; - uLine.sources[ssrc] = sources[ssrc]; - uLine.ssrcGroups = ssrc2group[ssrc]; - - // Use the cached Unified Plan SDP (if it exists) to assign - // SSRCs to mids. - if (typeof cached !== 'undefined' && - typeof cached.media !== 'undefined' && - Array.isArray(cached.media)) { - - cached.media.forEach(function (m) { - if (typeof m.sources === 'object') { - Object.keys(m.sources).forEach(function (s) { - if (s === ssrc) { - uLine.mid = m.mid; - } - }); - } - }); - } - - if (typeof uLine.mid === 'undefined') { - - // If this is an SSRC that we see for the first time - // assign it a new mid. This is typically the case when - // this method is called to transform a remote - // description for the first time or when there is a - // new SSRC in the remote description because a new - // peer has joined the conference. Local SSRCs should - // have already been added to the map in the toPlanB - // method. - // - // Because FF generates answers in Unified Plan style, - // we MUST already have a cached answer with all the - // local SSRCs mapped to some m-line/mid. - - uLine.mid = [bLine.type, '-', ssrc].join(''); - } - - // Include the candidates in the 1st media line. - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - uLine.port = port; - - mid2ul[uLine.mid] = uLine; - sources2ul[uIdx] = uLine.sources; - - self.cache.mlU2BMap[uIdx] = bIdx; - if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { - self.cache.mlB2UMap[bIdx] = uIdx; - } - uIdx++; - } - }); - } else { - var uLine = bLine; - - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - uLine.port = port; - - mid2ul[uLine.mid] = uLine; - - self.cache.mlU2BMap[uIdx] = bIdx; - if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { - self.cache.mlB2UMap[bIdx] = uIdx; - } - } - - bIdx++; - }); - - // Rebuild the media array in the right order and add the missing mLines - // (missing from the Plan B SDP). - session.media = []; - mids = []; // reuse - - if (desc.type === 'answer') { - - // The media lines in the answer must match the media lines in the - // offer. The order is important too. Here we assume that Firefox is - // the answerer, so we merely have to use the reconstructed (unified) - // answer to update the cached (unified) answer accordingly. - // - // In the general case, one would have to use the cached (unified) - // offer to find the m-lines that are missing from the reconstructed - // answer, potentially grabbing them from the cached (unified) answer. - // One has to be careful with this approach because inactive m-lines do - // not always have an mid, making it tricky (impossible?) to find where - // exactly and which m-lines are missing from the reconstructed answer. - - for (var i = 0; i < cached.media.length; i++) { - var uLine = cached.media[i]; - - delete uLine.msid; - delete uLine.sources; - delete uLine.ssrcGroups; - - if (typeof sources2ul[i] === 'undefined') { - if (!uLine.direction - || uLine.direction === 'sendrecv') - uLine.direction = 'recvonly'; - else if (uLine.direction === 'sendonly') - uLine.direction = 'inactive'; - } else { - if (!uLine.direction - || uLine.direction === 'sendrecv') - uLine.direction = 'sendrecv'; - else if (uLine.direction === 'recvonly') - uLine.direction = 'sendonly'; - } - - uLine.sources = sources2ul[i]; - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - - uLine.rtp = rtp[uLine.type]; - uLine.payloads = payloads[uLine.type]; - uLine.rtcpFb = rtcpFb[uLine.type]; - - session.media.push(uLine); - - if (typeof uLine.mid === 'string') { - // inactive lines don't/may not have an mid. - mids.push(uLine.mid); - } - } - } else { - - // SDP offer/answer (and the JSEP spec) forbids removing an m-section - // under any circumstances. If we are no longer interested in sending a - // track, we just remove the msid and ssrc attributes and set it to - // either a=recvonly (as the reofferer, we must use recvonly if the - // other side was previously sending on the m-section, but we can also - // leave the possibility open if it wasn't previously in use), or - // a=inactive. - - if (typeof cached !== 'undefined' && - typeof cached.media !== 'undefined' && - Array.isArray(cached.media)) { - cached.media.forEach(function(uLine) { - mids.push(uLine.mid); - if (typeof mid2ul[uLine.mid] !== 'undefined') { - session.media.push(mid2ul[uLine.mid]); - } else { - delete uLine.msid; - delete uLine.sources; - delete uLine.ssrcGroups; - - if (!uLine.direction - || uLine.direction === 'sendrecv') { - uLine.direction = 'sendonly'; - } - if (!uLine.direction - || uLine.direction === 'recvonly') { - uLine.direction = 'inactive'; - } - - addSetupAttr (uLine); - session.media.push(uLine); - } - }); - } - - // Add all the remaining (new) m-lines of the transformed SDP. - Object.keys(mid2ul).forEach(function(mid) { - if (mids.indexOf(mid) === -1) { - mids.push(mid); - if (mid2ul[mid].direction === 'recvonly') { - // This is a remote recvonly channel. Add its SSRC to the - // appropriate sendrecv or sendonly channel. - // TODO(gp) what if we don't have sendrecv/sendonly - // channel? - - var done = false; - - session.media.some(function (uLine) { - if ((uLine.direction === 'sendrecv' || - uLine.direction === 'sendonly') && - uLine.type === mid2ul[mid].type) { - // mid2ul[mid] shouldn't have any ssrc-groups - Object.keys(mid2ul[mid].sources).forEach( - function (ssrc) { - uLine.sources[ssrc] = - mid2ul[mid].sources[ssrc]; - }); - - done = true; - return true; - } - }); - - if (!done) { - session.media.push(mid2ul[mid]); - } - } else { - session.media.push(mid2ul[mid]); - } - } - }); - } - - // After we have constructed the Plan Unified m-lines we can figure out - // where (in which m-line) to place the 'recvonly SSRCs'. - // Note: we assume here that we are the answerer in the O/A, so any offers - // which we translate come from the remote side, while answers are local - // (and so our last local description is cached as an 'answer'). - ["audio", "video"].forEach(function (type) { - if (!session || !session.media || !Array.isArray(session.media)) - return; - - var idx = null; - if (Object.keys(recvonlySsrcs[type]).length > 0) { - idx = self.getFirstSendingIndexFromAnswer(type); - if (idx === null){ - // If this is the first offer we receive, we don't have a - // cached answer. Assume that we will be sending media using - // the first m-line for each media type. - - for (var i = 0; i < session.media.length; i++) { - if (session.media[i].type === type) { - idx = i; - break; - } - } - } - } - - if (idx && session.media.length > idx) { - var mLine = session.media[idx]; - Object.keys(recvonlySsrcs[type]).forEach(function(ssrc) { - if (mLine.sources && mLine.sources[ssrc]) { - console.warn("Replacing an existing SSRC."); - } - if (!mLine.sources) { - mLine.sources = {}; - } - - mLine.sources[ssrc] = recvonlySsrcs[type][ssrc]; - }); - } - }); - - if (typeof session.groups !== 'undefined') { - // We regenerate the BUNDLE group (since we regenerated the mids) - session.groups.some(function(group) { - if (group.type === 'BUNDLE') { - group.mids = mids.join(' '); - return true; - } - }); - } - - // msid semantic - session.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - var resStr = transform.write(session); - - // Cache the transformed SDP (Unified Plan) for later re-use in this - // function. - this.cache[desc.type] = resStr; - - return new RTCSessionDescription({ - type: desc.type, - sdp: resStr - }); - - //#endregion -}; - -},{"./array-equals":14,"./transform":17}],17:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var transform = require('sdp-transform'); - -exports.write = function(session, opts) { - - if (typeof session !== 'undefined' && - typeof session.media !== 'undefined' && - Array.isArray(session.media)) { - - session.media.forEach(function (mLine) { - // expand sources to ssrcs - if (typeof mLine.sources !== 'undefined' && - Object.keys(mLine.sources).length !== 0) { - mLine.ssrcs = []; - Object.keys(mLine.sources).forEach(function (ssrc) { - var source = mLine.sources[ssrc]; - Object.keys(source).forEach(function (attribute) { - mLine.ssrcs.push({ - id: ssrc, - attribute: attribute, - value: source[attribute] - }); - }); - }); - delete mLine.sources; - } - - // join ssrcs in ssrc groups - if (typeof mLine.ssrcGroups !== 'undefined' && - Array.isArray(mLine.ssrcGroups)) { - mLine.ssrcGroups.forEach(function (ssrcGroup) { - if (typeof ssrcGroup.ssrcs !== 'undefined' && - Array.isArray(ssrcGroup.ssrcs)) { - ssrcGroup.ssrcs = ssrcGroup.ssrcs.join(' '); - } - }); - } - }); - } - - // join group mids - if (typeof session !== 'undefined' && - typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { - - session.groups.forEach(function (g) { - if (typeof g.mids !== 'undefined' && Array.isArray(g.mids)) { - g.mids = g.mids.join(' '); - } - }); - } - - return transform.write(session, opts); -}; - -exports.parse = function(sdp) { - var session = transform.parse(sdp); - - if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && - Array.isArray(session.media)) { - - session.media.forEach(function (mLine) { - // group sources attributes by ssrc - if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) { - mLine.sources = {}; - mLine.ssrcs.forEach(function (ssrc) { - if (!mLine.sources[ssrc.id]) - mLine.sources[ssrc.id] = {}; - mLine.sources[ssrc.id][ssrc.attribute] = ssrc.value; - }); - - delete mLine.ssrcs; - } - - // split ssrcs in ssrc groups - if (typeof mLine.ssrcGroups !== 'undefined' && - Array.isArray(mLine.ssrcGroups)) { - mLine.ssrcGroups.forEach(function (ssrcGroup) { - if (typeof ssrcGroup.ssrcs === 'string') { - ssrcGroup.ssrcs = ssrcGroup.ssrcs.split(' '); - } - }); - } - }); - } - // split group mids - if (typeof session !== 'undefined' && - typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { - - session.groups.forEach(function (g) { - if (typeof g.mids === 'string') { - g.mids = g.mids.split(' '); - } - }); - } - - return session; -}; - - -},{"sdp-transform":11}],18:[function(require,module,exports){ -/*! - * UAParser.js v0.7.18 - * Lightweight JavaScript-based User-Agent string parser - * https://github.com/faisalman/ua-parser-js - * - * Copyright © 2012-2016 Faisal Salman - * Dual licensed under GPLv2 or MIT - */ - -(function (window, undefined) { - - 'use strict'; - - ////////////// - // Constants - ///////////// - - - var LIBVERSION = '0.7.18', - EMPTY = '', - UNKNOWN = '?', - FUNC_TYPE = 'function', - UNDEF_TYPE = 'undefined', - OBJ_TYPE = 'object', - STR_TYPE = 'string', - MAJOR = 'major', // deprecated - MODEL = 'model', - NAME = 'name', - TYPE = 'type', - VENDOR = 'vendor', - VERSION = 'version', - ARCHITECTURE= 'architecture', - CONSOLE = 'console', - MOBILE = 'mobile', - TABLET = 'tablet', - SMARTTV = 'smarttv', - WEARABLE = 'wearable', - EMBEDDED = 'embedded'; - - - /////////// - // Helper - ////////// - - - var util = { - extend : function (regexes, extensions) { - var margedRegexes = {}; - for (var i in regexes) { - if (extensions[i] && extensions[i].length % 2 === 0) { - margedRegexes[i] = extensions[i].concat(regexes[i]); - } else { - margedRegexes[i] = regexes[i]; - } - } - return margedRegexes; - }, - has : function (str1, str2) { - if (typeof str1 === "string") { - return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; - } else { - return false; - } - }, - lowerize : function (str) { - return str.toLowerCase(); - }, - major : function (version) { - return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g,'').split(".")[0] : undefined; - }, - trim : function (str) { - return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); - } - }; - - - /////////////// - // Map helper - ////////////// - - - var mapper = { - - rgx : function (ua, arrays) { - - //var result = {}, - var i = 0, j, k, p, q, matches, match;//, args = arguments; - - /*// construct object barebones - for (p = 0; p < args[1].length; p++) { - q = args[1][p]; - result[typeof q === OBJ_TYPE ? q[0] : q] = undefined; - }*/ - - // loop through all regexes maps - while (i < arrays.length && !matches) { - - var regex = arrays[i], // even sequence (0,2,4,..) - props = arrays[i + 1]; // odd sequence (1,3,5,..) - j = k = 0; - - // try matching uastring with regexes - while (j < regex.length && !matches) { - - matches = regex[j++].exec(ua); - - if (!!matches) { - for (p = 0; p < props.length; p++) { - match = matches[++k]; - q = props[p]; - // check if given property is actually array - if (typeof q === OBJ_TYPE && q.length > 0) { - if (q.length == 2) { - if (typeof q[1] == FUNC_TYPE) { - // assign modified match - this[q[0]] = q[1].call(this, match); - } else { - // assign given value, ignore regex match - this[q[0]] = q[1]; - } - } else if (q.length == 3) { - // check whether function or regex - if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { - // call function (usually string mapper) - this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; - } else { - // sanitize match using given regex - this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; - } - } else if (q.length == 4) { - this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; - } - } else { - this[q] = match ? match : undefined; - } - } - } - } - i += 2; - } - // console.log(this); - //return this; - }, - - str : function (str, map) { - - for (var i in map) { - // check if array - if (typeof map[i] === OBJ_TYPE && map[i].length > 0) { - for (var j = 0; j < map[i].length; j++) { - if (util.has(map[i][j], str)) { - return (i === UNKNOWN) ? undefined : i; - } - } - } else if (util.has(map[i], str)) { - return (i === UNKNOWN) ? undefined : i; - } - } - return str; - } - }; - - - /////////////// - // String map - ////////////// - - - var maps = { - - browser : { - oldsafari : { - version : { - '1.0' : '/8', - '1.2' : '/1', - '1.3' : '/3', - '2.0' : '/412', - '2.0.2' : '/416', - '2.0.3' : '/417', - '2.0.4' : '/419', - '?' : '/' - } - } - }, - - device : { - amazon : { - model : { - 'Fire Phone' : ['SD', 'KF'] - } - }, - sprint : { - model : { - 'Evo Shift 4G' : '7373KT' - }, - vendor : { - 'HTC' : 'APA', - 'Sprint' : 'Sprint' - } - } - }, - - os : { - windows : { - version : { - 'ME' : '4.90', - 'NT 3.11' : 'NT3.51', - 'NT 4.0' : 'NT4.0', - '2000' : 'NT 5.0', - 'XP' : ['NT 5.1', 'NT 5.2'], - 'Vista' : 'NT 6.0', - '7' : 'NT 6.1', - '8' : 'NT 6.2', - '8.1' : 'NT 6.3', - '10' : ['NT 6.4', 'NT 10.0'], - 'RT' : 'ARM' - } - } - } - }; - - - ////////////// - // Regex map - ///////////// - - - var regexes = { - - browser : [[ - - // Presto based - /(opera\smini)\/([\w\.-]+)/i, // Opera Mini - /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet - /(opera).+version\/([\w\.]+)/i, // Opera > 9.80 - /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 - ], [NAME, VERSION], [ - - /(opios)[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0 - ], [[NAME, 'Opera Mini'], VERSION], [ - - /\s(opr)\/([\w\.]+)/i // Opera Webkit - ], [[NAME, 'Opera'], VERSION], [ - - // Mixed - /(kindle)\/([\w\.]+)/i, // Kindle - /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]*)/i, - // Lunascape/Maxthon/Netfront/Jasmine/Blazer - - // Trident based - /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i, - // Avant/IEMobile/SlimBrowser/Baidu - /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer - - // Webkit/KHTML based - /(rekonq)\/([\w\.]*)/i, // Rekonq - /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark)\/([\w\.-]+)/i - // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser - ], [NAME, VERSION], [ - - /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11 - ], [[NAME, 'IE'], VERSION], [ - - /(edge|edgios|edgea)\/((\d+)?[\w\.]+)/i // Microsoft Edge - ], [[NAME, 'Edge'], VERSION], [ - - /(yabrowser)\/([\w\.]+)/i // Yandex - ], [[NAME, 'Yandex'], VERSION], [ - - /(puffin)\/([\w\.]+)/i // Puffin - ], [[NAME, 'Puffin'], VERSION], [ - - /((?:[\s\/])uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i - // UCBrowser - ], [[NAME, 'UCBrowser'], VERSION], [ - - /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon - ], [[NAME, /_/g, ' '], VERSION], [ - - /(micromessenger)\/([\w\.]+)/i // WeChat - ], [[NAME, 'WeChat'], VERSION], [ - - /(qqbrowserlite)\/([\w\.]+)/i // QQBrowserLite - ], [NAME, VERSION], [ - - /(QQ)\/([\d\.]+)/i // QQ, aka ShouQ - ], [NAME, VERSION], [ - - /m?(qqbrowser)[\/\s]?([\w\.]+)/i // QQBrowser - ], [NAME, VERSION], [ - - /(BIDUBrowser)[\/\s]?([\w\.]+)/i // Baidu Browser - ], [NAME, VERSION], [ - - /(2345Explorer)[\/\s]?([\w\.]+)/i // 2345 Browser - ], [NAME, VERSION], [ - - /(MetaSr)[\/\s]?([\w\.]+)/i // SouGouBrowser - ], [NAME], [ - - /(LBBROWSER)/i // LieBao Browser - ], [NAME], [ - - /xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser - ], [VERSION, [NAME, 'MIUI Browser']], [ - - /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android - ], [VERSION, [NAME, 'Facebook']], [ - - /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless - ], [VERSION, [NAME, 'Chrome Headless']], [ - - /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView - ], [[NAME, /(.+)/, '$1 WebView'], VERSION], [ - - /((?:oculus|samsung)browser)\/([\w\.]+)/i - ], [[NAME, /(.+(?:g|us))(.+)/, '$1 $2'], VERSION], [ // Oculus / Samsung Browser - - /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)*/i // Android Browser - ], [VERSION, [NAME, 'Android Browser']], [ - - /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i - // Chrome/OmniWeb/Arora/Tizen/Nokia - ], [NAME, VERSION], [ - - /(dolfin)\/([\w\.]+)/i // Dolphin - ], [[NAME, 'Dolphin'], VERSION], [ - - /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS - ], [[NAME, 'Chrome'], VERSION], [ - - /(coast)\/([\w\.]+)/i // Opera Coast - ], [[NAME, 'Opera Coast'], VERSION], [ - - /fxios\/([\w\.-]+)/i // Firefox for iOS - ], [VERSION, [NAME, 'Firefox']], [ - - /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari - ], [VERSION, [NAME, 'Mobile Safari']], [ - - /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile - ], [VERSION, NAME], [ - - /webkit.+?(gsa)\/([\w\.]+).+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Google Search Appliance on iOS - ], [[NAME, 'GSA'], VERSION], [ - - /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 - ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [ - - /(konqueror)\/([\w\.]+)/i, // Konqueror - /(webkit|khtml)\/([\w\.]+)/i - ], [NAME, VERSION], [ - - // Gecko based - /(navigator|netscape)\/([\w\.-]+)/i // Netscape - ], [[NAME, 'Netscape'], VERSION], [ - /(swiftfox)/i, // Swiftfox - /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i, - // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror - /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([\w\.-]+)$/i, - - // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix - /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla - - // Other - /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i, - // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir - /(links)\s\(([\w\.]+)/i, // Links - /(gobrowser)\/?([\w\.]*)/i, // GoBrowser - /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser - /(mosaic)[\/\s]([\w\.]+)/i // Mosaic - ], [NAME, VERSION] - - /* ///////////////////// - // Media players BEGIN - //////////////////////// - - , [ - - /(apple(?:coremedia|))\/((\d+)[\w\._]+)/i, // Generic Apple CoreMedia - /(coremedia) v((\d+)[\w\._]+)/i - ], [NAME, VERSION], [ - - /(aqualung|lyssna|bsplayer)\/((\d+)?[\w\.-]+)/i // Aqualung/Lyssna/BSPlayer - ], [NAME, VERSION], [ - - /(ares|ossproxy)\s((\d+)[\w\.-]+)/i // Ares/OSSProxy - ], [NAME, VERSION], [ - - /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/((\d+)[\w\.-]+)/i, - // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC - // NSPlayer/PSP-InternetRadioPlayer/Videos - /(clementine|music player daemon)\s((\d+)[\w\.-]+)/i, // Clementine/MPD - /(lg player|nexplayer)\s((\d+)[\d\.]+)/i, - /player\/(nexplayer|lg player)\s((\d+)[\w\.-]+)/i // NexPlayer/LG Player - ], [NAME, VERSION], [ - /(nexplayer)\s((\d+)[\w\.-]+)/i // Nexplayer - ], [NAME, VERSION], [ - - /(flrp)\/((\d+)[\w\.-]+)/i // Flip Player - ], [[NAME, 'Flip Player'], VERSION], [ - - /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i - // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit - ], [NAME], [ - - /(gstreamer) souphttpsrc (?:\([^\)]+\)){0,1} libsoup\/((\d+)[\w\.-]+)/i - // Gstreamer - ], [NAME, VERSION], [ - - /(htc streaming player)\s[\w_]+\s\/\s((\d+)[\d\.]+)/i, // HTC Streaming Player - /(java|python-urllib|python-requests|wget|libcurl)\/((\d+)[\w\.-_]+)/i, - // Java/urllib/requests/wget/cURL - /(lavf)((\d+)[\d\.]+)/i // Lavf (FFMPEG) - ], [NAME, VERSION], [ - - /(htc_one_s)\/((\d+)[\d\.]+)/i // HTC One S - ], [[NAME, /_/g, ' '], VERSION], [ - - /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+){0,1})/i - // MPlayer SVN - ], [NAME, VERSION], [ - - /(mplayer)(?:\s|\/|[unkow-]+)((\d+)[\w\.-]+)/i // MPlayer - ], [NAME, VERSION], [ - - /(mplayer)/i, // MPlayer (no other info) - /(yourmuze)/i, // YourMuze - /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime - ], [NAME], [ - - /(nero (?:home|scout))\/((\d+)[\w\.-]+)/i // Nero Home/Nero Scout - ], [NAME, VERSION], [ - - /(nokia\d+)\/((\d+)[\w\.-]+)/i // Nokia - ], [NAME, VERSION], [ - - /\s(songbird)\/((\d+)[\w\.-]+)/i // Songbird/Philips-Songbird - ], [NAME, VERSION], [ - - /(winamp)3 version ((\d+)[\w\.-]+)/i, // Winamp - /(winamp)\s((\d+)[\w\.-]+)/i, - /(winamp)mpeg\/((\d+)[\w\.-]+)/i - ], [NAME, VERSION], [ - - /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) - // inlight radio - ], [NAME], [ - - /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/((\d+)[\w\.-]+)/i - // QuickTime/RealMedia/RadioApp/RadioClientApplication/ - // SoundTap/Totem/Stagefright/Streamium - ], [NAME, VERSION], [ - - /(smp)((\d+)[\d\.]+)/i // SMP - ], [NAME, VERSION], [ - - /(vlc) media player - version ((\d+)[\w\.]+)/i, // VLC Videolan - /(vlc)\/((\d+)[\w\.-]+)/i, - /(xbmc|gvfs|xine|xmms|irapp)\/((\d+)[\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp - /(foobar2000)\/((\d+)[\d\.]+)/i, // Foobar2000 - /(itunes)\/((\d+)[\d\.]+)/i // iTunes - ], [NAME, VERSION], [ - - /(wmplayer)\/((\d+)[\w\.-]+)/i, // Windows Media Player - /(windows-media-player)\/((\d+)[\w\.-]+)/i - ], [[NAME, /-/g, ' '], VERSION], [ - - /windows\/((\d+)[\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i - // Windows Media Server - ], [VERSION, [NAME, 'Windows']], [ - - /(com\.riseupradioalarm)\/((\d+)[\d\.]*)/i // RiseUP Radio Alarm - ], [NAME, VERSION], [ - - /(rad.io)\s((\d+)[\d\.]+)/i, // Rad.io - /(radio.(?:de|at|fr))\s((\d+)[\d\.]+)/i - ], [[NAME, 'rad.io'], VERSION] - - ////////////////////// - // Media players END - ////////////////////*/ - - ], - - cpu : [[ - - /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 - ], [[ARCHITECTURE, 'amd64']], [ - - /(ia32(?=;))/i // IA32 (quicktime) - ], [[ARCHITECTURE, util.lowerize]], [ - - /((?:i[346]|x)86)[;\)]/i // IA32 - ], [[ARCHITECTURE, 'ia32']], [ - - // PocketPC mistakenly identified as PowerPC - /windows\s(ce|mobile);\sppc;/i - ], [[ARCHITECTURE, 'arm']], [ - - /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC - ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [ - - /(sun4\w)[;\)]/i // SPARC - ], [[ARCHITECTURE, 'sparc']], [ - - /((?:avr32|ia64(?=;))|68k(?=\))|arm(?:64|(?=v\d+;))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)/i - // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC - ], [[ARCHITECTURE, util.lowerize]] - ], - - device : [[ - - /\((ipad|playbook);[\w\s\);-]+(rim|apple)/i // iPad/PlayBook - ], [MODEL, VENDOR, [TYPE, TABLET]], [ - - /applecoremedia\/[\w\.]+ \((ipad)/ // iPad - ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ - - /(apple\s{0,1}tv)/i // Apple TV - ], [[MODEL, 'Apple TV'], [VENDOR, 'Apple']], [ - - /(archos)\s(gamepad2?)/i, // Archos - /(hp).+(touchpad)/i, // HP TouchPad - /(hp).+(tablet)/i, // HP Tablet - /(kindle)\/([\w\.]+)/i, // Kindle - /\s(nook)[\w\s]+build\/(\w+)/i, // Nook - /(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /(kf[A-z]+)\sbuild\/.+silk\//i // Kindle Fire HD - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ - /(sd|kf)[0349hijorstuw]+\sbuild\/.+silk\//i // Fire Phone - ], [[MODEL, mapper.str, maps.device.amazon.model], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ - - /\((ip[honed|\s\w*]+);.+(apple)/i // iPod/iPhone - ], [MODEL, VENDOR, [TYPE, MOBILE]], [ - /\((ip[honed|\s\w*]+);/i // iPod/iPhone - ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ - - /(blackberry)[\s-]?(\w+)/i, // BlackBerry - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]*)/i, - // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron - /(hp)\s([\w\s]+\w)/i, // HP iPAQ - /(asus)-?(\w+)/i // Asus - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /\(bb10;\s(\w+)/i // BlackBerry 10 - ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ - // Asus Tablets - /android.+(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7|padfone)/i - ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [ - - /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony - /(sony)?(?:sgp.+)\sbuild\//i - ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [ - /android.+\s([c-g]\d{4}|so[-l]\w+)\sbuild\//i - ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - - /\s(ouya)\s/i, // Ouya - /(nintendo)\s([wids3u]+)/i // Nintendo - ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ - - /android.+;\s(shield)\sbuild/i // Nvidia - ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ - - /(playstation\s[34portablevi]+)/i // Playstation - ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ - - /(sprint\s(\w+))/i // Sprint Phones - ], [[VENDOR, mapper.str, maps.device.sprint.vendor], [MODEL, mapper.str, maps.device.sprint.model], [TYPE, MOBILE]], [ - - /(lenovo)\s?(S(?:5000|6000)+(?:[-][\w+]))/i // Lenovo tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC - /(zte)-(\w*)/i, // ZTE - /(alcatel|geeksphone|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]*)/i - // Alcatel/GeeksPhone/Lenovo/Nexian/Panasonic/Sony - ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ - - /(nexus\s9)/i // HTC Nexus 9 - ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ - - /d\/huawei([\w\s-]+)[;\)]/i, - /(nexus\s6p)/i // Huawei - ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ - - /(microsoft);\s(lumia[\s\w]+)/i // Microsoft Lumia - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /[\s\(;](xbox(?:\sone)?)[\s\);]/i // Microsoft Xbox - ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [ - /(kin\.[onetw]{3})/i // Microsoft Kin - ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ - - // Motorola - /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?:?(\s4g)?)[\w\s]+build\//i, - /mot[\s-]?(\w*)/i, - /(XT\d{3,4}) build\//i, - /(nexus\s6)/i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ - /android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [ - - /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices - ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ - - /hbbtv.+maple;(\d+)/i - ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [ - - /\(dtv[\);].+(aquos)/i // Sharp - ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [ - - /android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10))/i, - /((SM-T\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung - /smart-tv.+(samsung)/i - ], [VENDOR, [TYPE, SMARTTV], MODEL], [ - /((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+))/i, - /(sam[sung]*)[\s-]*(\w+-?[\w-]*)/i, - /sec-((sgh\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [ - - /sie-(\w*)/i // Siemens - ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ - - /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia - /(nokia)[\s_-]?([\w-]*)/i - ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [ - - /android\s3\.[\s\w;-]{10}(a\d{3})/i // Acer - ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ - - /android.+([vl]k\-?\d{3})\s+build/i // LG Tablet - ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [ - /android\s3\.[\s\w;-]{10}(lg?)-([06cv9]{3,4})/i // LG Tablet - ], [[VENDOR, 'LG'], MODEL, [TYPE, TABLET]], [ - /(lg) netcast\.tv/i // LG SmartTV - ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ - /(nexus\s[45])/i, // LG - /lg[e;\s\/-]+(\w*)/i, - /android.+lg(\-?[\d\w]+)\s+build/i - ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [ - - /android.+(ideatab[a-z0-9\-\s]+)/i // Lenovo - ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ - - /linux;.+((jolla));/i // Jolla - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /((pebble))app\/[\d\.]+\s/i // Pebble - ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ - - /android.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /crkey/i // Google Chromecast - ], [[MODEL, 'Chromecast'], [VENDOR, 'Google']], [ - - /android.+;\s(glass)\s\d/i // Google Glass - ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [ - - /android.+;\s(pixel c)\s/i // Google Pixel C - ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ - - /android.+;\s(pixel xl|pixel)\s/i // Google Pixel - ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ - - /android.+;\s(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models - /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi - /android.+(mi[\s\-_]*(?:one|one[\s_]plus|note lte)?[\s_]*(?:\d?\w?)[\s_]*(?:plus)?)\s+build/i, // Xiaomi Mi - /android.+(redmi[\s\-_]*(?:note)?(?:[\s_]*[\w\s]+))\s+build/i // Redmi Phones - ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ - /android.+(mi[\s\-_]*(?:pad)(?:[\s_]*[\w\s]+))\s+build/i // Mi Pad tablets - ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ - /android.+;\s(m[1-5]\snote)\sbuild/i // Meizu Tablet - ], [MODEL, [VENDOR, 'Meizu'], [TYPE, TABLET]], [ - - /android.+a000(1)\s+build/i, // OnePlus - /android.+oneplus\s(a\d{4})\s+build/i - ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(RCT[\d\w]+)\s+build/i // RCA Tablets - ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ - - /android.+[;\/\s]+(Venue[\d\s]{2,7})\s+build/i // Dell Venue Tablets - ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Q[T|M][\d\w]+)\s+build/i // Verizon Tablet - ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ - - /android.+[;\/]\s+(Barnes[&\s]+Noble\s+|BN[RT])(V?.*)\s+build/i // Barnes & Noble Tablet - ], [[VENDOR, 'Barnes & Noble'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s+(TM\d{3}.*\b)\s+build/i // Barnes & Noble Tablet - ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ - - /android.+;\s(k88)\sbuild/i // ZTE K Series Tablet - ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(gen\d{3})\s+build.*49h/i // Swiss GEN Mobile - ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(zur\d{3})\s+build/i // Swiss ZUR Tablet - ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((Zeki)?TB.*\b)\s+build/i // Zeki Tablets - ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ - - /(android).+[;\/]\s+([YR]\d{2})\s+build/i, - /android.+[;\/]\s+(Dragon[\-\s]+Touch\s+|DT)(\w{5})\sbuild/i // Dragon Touch Tablet - ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*(NS-?\w{0,9})\sbuild/i // Insignia Tablets - ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((NX|Next)-?\w{0,9})\s+build/i // NextBook Tablets - ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Xtreme\_)?(V(1[045]|2[015]|30|40|60|7[05]|90))\s+build/i - ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones - - /android.+[;\/]\s*(LVTEL\-)?(V1[12])\s+build/i // LvTel Phones - ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(V(100MD|700NA|7011|917G).*\b)\s+build/i // Envizen Tablets - ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Le[\s\-]+Pan)[\s\-]+(\w{1,9})\s+build/i // Le Pan Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Trio[\s\-]*.*)\s+build/i // MachSpeed Tablets - ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Trinity)[\-\s]*(T\d{3})\s+build/i // Trinity Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*TU_(1491)\s+build/i // Rotor Tablets - ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ - - /android.+(KS(.+))\s+build/i // Amazon Kindle Tablets - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ - - /android.+(Gigaset)[\s\-]+(Q\w{1,9})\s+build/i // Gigaset Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet - /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile - ], [[TYPE, util.lowerize], VENDOR, MODEL], [ - - /(android[\w\.\s\-]{0,9});.+build/i // Generic Android Device - ], [MODEL, [VENDOR, 'Generic']] - - - /*////////////////////////// - // TODO: move to string map - //////////////////////////// - - /(C6603)/i // Sony Xperia Z C6603 - ], [[MODEL, 'Xperia Z C6603'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - /(C6903)/i // Sony Xperia Z 1 - ], [[MODEL, 'Xperia Z 1'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - - /(SM-G900[F|H])/i // Samsung Galaxy S5 - ], [[MODEL, 'Galaxy S5'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G7102)/i // Samsung Galaxy Grand 2 - ], [[MODEL, 'Galaxy Grand 2'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G530H)/i // Samsung Galaxy Grand Prime - ], [[MODEL, 'Galaxy Grand Prime'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G313HZ)/i // Samsung Galaxy V - ], [[MODEL, 'Galaxy V'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-T805)/i // Samsung Galaxy Tab S 10.5 - ], [[MODEL, 'Galaxy Tab S 10.5'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ - /(SM-G800F)/i // Samsung Galaxy S5 Mini - ], [[MODEL, 'Galaxy S5 Mini'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-T311)/i // Samsung Galaxy Tab 3 8.0 - ], [[MODEL, 'Galaxy Tab 3 8.0'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ - - /(T3C)/i // Advan Vandroid T3C - ], [MODEL, [VENDOR, 'Advan'], [TYPE, TABLET]], [ - /(ADVAN T1J\+)/i // Advan Vandroid T1J+ - ], [[MODEL, 'Vandroid T1J+'], [VENDOR, 'Advan'], [TYPE, TABLET]], [ - /(ADVAN S4A)/i // Advan Vandroid S4A - ], [[MODEL, 'Vandroid S4A'], [VENDOR, 'Advan'], [TYPE, MOBILE]], [ - - /(V972M)/i // ZTE V972M - ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [ - - /(i-mobile)\s(IQ\s[\d\.]+)/i // i-mobile IQ - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /(IQ6.3)/i // i-mobile IQ IQ 6.3 - ], [[MODEL, 'IQ 6.3'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ - /(i-mobile)\s(i-style\s[\d\.]+)/i // i-mobile i-STYLE - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /(i-STYLE2.1)/i // i-mobile i-STYLE 2.1 - ], [[MODEL, 'i-STYLE 2.1'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ - - /(mobiistar touch LAI 512)/i // mobiistar touch LAI 512 - ], [[MODEL, 'Touch LAI 512'], [VENDOR, 'mobiistar'], [TYPE, MOBILE]], [ - - ///////////// - // END TODO - ///////////*/ - - ], - - engine : [[ - - /windows.+\sedge\/([\w\.]+)/i // EdgeHTML - ], [VERSION, [NAME, 'EdgeHTML']], [ - - /(presto)\/([\w\.]+)/i, // Presto - /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m - /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links - /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab - ], [NAME, VERSION], [ - - /rv\:([\w\.]{1,9}).+(gecko)/i // Gecko - ], [VERSION, NAME] - ], - - os : [[ - - // Windows based - /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes) - ], [NAME, VERSION], [ - /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT - /(windows\sphone(?:\sos)*)[\s\/]?([\d\.\s\w]*)/i, // Windows Phone - /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i - ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ - /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i - ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ - - // Mobile/Embedded OS - /\((bb)(10);/i // BlackBerry 10 - ], [[NAME, 'BlackBerry'], VERSION], [ - /(blackberry)\w*\/?([\w\.]*)/i, // Blackberry - /(tizen)[\/\s]([\w\.]+)/i, // Tizen - /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]*)/i, - // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki - /linux;.+(sailfish);/i // Sailfish OS - ], [NAME, VERSION], [ - /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]*)/i // Symbian - ], [[NAME, 'Symbian'], VERSION], [ - /\((series40);/i // Series 40 - ], [NAME], [ - /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS - ], [[NAME, 'Firefox OS'], VERSION], [ - - // Console - /(nintendo|playstation)\s([wids34portablevu]+)/i, // Nintendo/Playstation - - // GNU/Linux based - /(mint)[\/\s\(]?(\w*)/i, // Mint - /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux - /(joli|[kxln]?ubuntu|debian|suse|opensuse|gentoo|(?=\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?(?!chrom)([\w\.-]*)/i, - // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware - // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus - /(hurd|linux)\s?([\w\.]*)/i, // Hurd/Linux - /(gnu)\s?([\w\.]*)/i // GNU - ], [NAME, VERSION], [ - - /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS - ], [[NAME, 'Chromium OS'], VERSION],[ - - // Solaris - /(sunos)\s?([\w\.\d]*)/i // Solaris - ], [[NAME, 'Solaris'], VERSION], [ - - // BSD based - /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]*)/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly - ], [NAME, VERSION],[ - - /(haiku)\s(\w+)/i // Haiku - ], [NAME, VERSION],[ - - /cfnetwork\/.+darwin/i, - /ip[honead]{2,4}(?:.*os\s([\w]+)\slike\smac|;\sopera)/i // iOS - ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ - - /(mac\sos\sx)\s?([\w\s\.]*)/i, - /(macintosh|mac(?=_powerpc)\s)/i // Mac OS - ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ - - // Other - /((?:open)?solaris)[\/\s-]?([\w\.]*)/i, // Solaris - /(aix)\s((\d)(?=\.|\)|\s)[\w\.])*/i, // AIX - /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i, - // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS - /(unix)\s?([\w\.]*)/i // UNIX - ], [NAME, VERSION] - ] - }; - - - ///////////////// - // Constructor - //////////////// - /* - var Browser = function (name, version) { - this[NAME] = name; - this[VERSION] = version; - }; - var CPU = function (arch) { - this[ARCHITECTURE] = arch; - }; - var Device = function (vendor, model, type) { - this[VENDOR] = vendor; - this[MODEL] = model; - this[TYPE] = type; - }; - var Engine = Browser; - var OS = Browser; - */ - var UAParser = function (uastring, extensions) { - - if (typeof uastring === 'object') { - extensions = uastring; - uastring = undefined; - } - - if (!(this instanceof UAParser)) { - return new UAParser(uastring, extensions).getResult(); - } - - var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); - var rgxmap = extensions ? util.extend(regexes, extensions) : regexes; - //var browser = new Browser(); - //var cpu = new CPU(); - //var device = new Device(); - //var engine = new Engine(); - //var os = new OS(); - - this.getBrowser = function () { - var browser = { name: undefined, version: undefined }; - mapper.rgx.call(browser, ua, rgxmap.browser); - browser.major = util.major(browser.version); // deprecated - return browser; - }; - this.getCPU = function () { - var cpu = { architecture: undefined }; - mapper.rgx.call(cpu, ua, rgxmap.cpu); - return cpu; - }; - this.getDevice = function () { - var device = { vendor: undefined, model: undefined, type: undefined }; - mapper.rgx.call(device, ua, rgxmap.device); - return device; - }; - this.getEngine = function () { - var engine = { name: undefined, version: undefined }; - mapper.rgx.call(engine, ua, rgxmap.engine); - return engine; - }; - this.getOS = function () { - var os = { name: undefined, version: undefined }; - mapper.rgx.call(os, ua, rgxmap.os); - return os; - }; - this.getResult = function () { - return { - ua : this.getUA(), - browser : this.getBrowser(), - engine : this.getEngine(), - os : this.getOS(), - device : this.getDevice(), - cpu : this.getCPU() - }; - }; - this.getUA = function () { - return ua; - }; - this.setUA = function (uastring) { - ua = uastring; - //browser = new Browser(); - //cpu = new CPU(); - //device = new Device(); - //engine = new Engine(); - //os = new OS(); - return this; - }; - return this; - }; - - UAParser.VERSION = LIBVERSION; - UAParser.BROWSER = { - NAME : NAME, - MAJOR : MAJOR, // deprecated - VERSION : VERSION - }; - UAParser.CPU = { - ARCHITECTURE : ARCHITECTURE - }; - UAParser.DEVICE = { - MODEL : MODEL, - VENDOR : VENDOR, - TYPE : TYPE, - CONSOLE : CONSOLE, - MOBILE : MOBILE, - SMARTTV : SMARTTV, - TABLET : TABLET, - WEARABLE: WEARABLE, - EMBEDDED: EMBEDDED - }; - UAParser.ENGINE = { - NAME : NAME, - VERSION : VERSION - }; - UAParser.OS = { - NAME : NAME, - VERSION : VERSION - }; - //UAParser.Utils = util; - - /////////// - // Export - ////////// - - - // check js environment - if (typeof(exports) !== UNDEF_TYPE) { - // nodejs env - if (typeof module !== UNDEF_TYPE && module.exports) { - exports = module.exports = UAParser; - } - // TODO: test!!!!!!!! - /* - if (require && require.main === module && process) { - // cli - var jsonize = function (arr) { - var res = []; - for (var i in arr) { - res.push(new UAParser(arr[i]).getResult()); - } - process.stdout.write(JSON.stringify(res, null, 2) + '\n'); - }; - if (process.stdin.isTTY) { - // via args - jsonize(process.argv.slice(2)); - } else { - // via pipe - var str = ''; - process.stdin.on('readable', function() { - var read = process.stdin.read(); - if (read !== null) { - str += read; - } - }); - process.stdin.on('end', function () { - jsonize(str.replace(/\n$/, '').split('\n')); - }); - } - } - */ - exports.UAParser = UAParser; - } else { - // requirejs env (optional) - if (typeof(define) === FUNC_TYPE && define.amd) { - define(function () { - return UAParser; - }); - } else if (window) { - // browser env - window.UAParser = UAParser; - } - } - - // jQuery/Zepto specific (optional) - // Note: - // In AMD env the global scope should be kept clean, but jQuery is an exception. - // jQuery always exports to global scope, unless jQuery.noConflict(true) is used, - // and we should catch that. - var $ = window && (window.jQuery || window.Zepto); - if (typeof $ !== UNDEF_TYPE) { - var parser = new UAParser(); - $.ua = parser.getResult(); - $.ua.get = function () { - return parser.getUA(); - }; - $.ua.set = function (uastring) { - parser.setUA(uastring); - var result = parser.getResult(); - for (var prop in result) { - $.ua[prop] = result[prop]; - } - }; - } - -})(typeof window === 'object' ? window : this); - -},{}],19:[function(require,module,exports){ -var v1 = require('./v1'); -var v4 = require('./v4'); - -var uuid = v4; -uuid.v1 = v1; -uuid.v4 = v4; - -module.exports = uuid; - -},{"./v1":22,"./v4":23}],20:[function(require,module,exports){ -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = []; -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1); -} - -function bytesToUuid(buf, offset) { - var i = offset || 0; - var bth = byteToHex; - return bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]]; -} - -module.exports = bytesToUuid; - -},{}],21:[function(require,module,exports){ -// Unique ID creation requires a high quality random # generator. In the -// browser this is a little complicated due to unknown quality of Math.random() -// and inconsistent support for the `crypto` API. We do the best we can via -// feature-detection - -// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. -var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) || - (typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto)); -if (getRandomValues) { - // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto - var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef - - module.exports = function whatwgRNG() { - getRandomValues(rnds8); - return rnds8; - }; -} else { - // Math.random()-based (RNG) - // - // If all else fails, use Math.random(). It's fast, but is of unspecified - // quality. - var rnds = new Array(16); - - module.exports = function mathRNG() { - for (var i = 0, r; i < 16; i++) { - if ((i & 0x03) === 0) r = Math.random() * 0x100000000; - rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; - } - - return rnds; - }; -} - -},{}],22:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); - -// **`v1()` - Generate time-based UUID** -// -// Inspired by https://github.com/LiosK/UUID.js -// and http://docs.python.org/library/uuid.html - -var _nodeId; -var _clockseq; - -// Previous uuid creation time -var _lastMSecs = 0; -var _lastNSecs = 0; - -// See https://github.com/broofa/node-uuid for API details -function v1(options, buf, offset) { - var i = buf && offset || 0; - var b = buf || []; - - options = options || {}; - var node = options.node || _nodeId; - var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; - - // node and clockseq need to be initialized to random values if they're not - // specified. We do this lazily to minimize issues related to insufficient - // system entropy. See #189 - if (node == null || clockseq == null) { - var seedBytes = rng(); - if (node == null) { - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - node = _nodeId = [ - seedBytes[0] | 0x01, - seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] - ]; - } - if (clockseq == null) { - // Per 4.2.2, randomize (14 bit) clockseq - clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; - } - } - - // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); - - // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; - - // Time since last uuid creation (in msecs) - var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; - - // Per 4.2.1.2, Bump clockseq on clock regression - if (dt < 0 && options.clockseq === undefined) { - clockseq = clockseq + 1 & 0x3fff; - } - - // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { - nsecs = 0; - } - - // Per 4.2.1.2 Throw error if too many uuids are requested - if (nsecs >= 10000) { - throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; - - // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - msecs += 12219292800000; - - // `time_low` - var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; - - // `time_mid` - var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; - - // `time_high_and_version` - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - b[i++] = tmh >>> 16 & 0xff; - - // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - b[i++] = clockseq >>> 8 | 0x80; - - // `clock_seq_low` - b[i++] = clockseq & 0xff; - - // `node` - for (var n = 0; n < 6; ++n) { - b[i + n] = node[n]; - } - - return buf ? buf : bytesToUuid(b); -} - -module.exports = v1; - -},{"./lib/bytesToUuid":20,"./lib/rng":21}],23:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); - -function v4(options, buf, offset) { - var i = buf && offset || 0; - - if (typeof(options) == 'string') { - buf = options === 'binary' ? new Array(16) : null; - options = null; - } - options = options || {}; - - var rnds = options.random || (options.rng || rng)(); - - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = (rnds[6] & 0x0f) | 0x40; - rnds[8] = (rnds[8] & 0x3f) | 0x80; - - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ++ii) { - buf[i + ii] = rnds[ii]; - } - } - - return buf || bytesToUuid(rnds); -} - -module.exports = v4; - -},{"./lib/bytesToUuid":20,"./lib/rng":21}],24:[function(require,module,exports){ -/* -WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based -on @visionmedia's Emitter from UI Kit. - -Why? I wanted it standalone. - -I also wanted support for wildcard emitters like this: - -emitter.on('*', function (eventName, other, event, payloads) { - -}); - -emitter.on('somenamespace*', function (eventName, payloads) { - -}); - -Please note that callbacks triggered by wildcard registered events also get -the event name as the first argument. -*/ - -module.exports = WildEmitter; - -function WildEmitter() { } - -WildEmitter.mixin = function (constructor) { - var prototype = constructor.prototype || constructor; - - prototype.isWildEmitter= true; - - // Listen on the given `event` with `fn`. Store a group name if present. - prototype.on = function (event, groupName, fn) { - this.callbacks = this.callbacks || {}; - var hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - func._groupName = group; - (this.callbacks[event] = this.callbacks[event] || []).push(func); - return this; - }; - - // Adds an `event` listener that will be invoked a single - // time then automatically removed. - prototype.once = function (event, groupName, fn) { - var self = this, - hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - function on() { - self.off(event, on); - func.apply(this, arguments); - } - this.on(event, group, on); - return this; - }; - - // Unbinds an entire group - prototype.releaseGroup = function (groupName) { - this.callbacks = this.callbacks || {}; - var item, i, len, handlers; - for (item in this.callbacks) { - handlers = this.callbacks[item]; - for (i = 0, len = handlers.length; i < len; i++) { - if (handlers[i]._groupName === groupName) { - //console.log('removing'); - // remove it and shorten the array we're looping through - handlers.splice(i, 1); - i--; - len--; - } - } - } - return this; - }; - - // Remove the given callback for `event` or all - // registered callbacks. - prototype.off = function (event, fn) { - this.callbacks = this.callbacks || {}; - var callbacks = this.callbacks[event], - i; - - if (!callbacks) return this; - - // remove all handlers - if (arguments.length === 1) { - delete this.callbacks[event]; - return this; - } - - // remove specific handler - i = callbacks.indexOf(fn); - callbacks.splice(i, 1); - if (callbacks.length === 0) { - delete this.callbacks[event]; - } - return this; - }; - - /// Emit `event` with the given args. - // also calls any `*` handlers - prototype.emit = function (event) { - this.callbacks = this.callbacks || {}; - var args = [].slice.call(arguments, 1), - callbacks = this.callbacks[event], - specialCallbacks = this.getWildcardCallbacks(event), - i, - len, - item, - listeners; - - if (callbacks) { - listeners = callbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, args); - } - } - - if (specialCallbacks) { - len = specialCallbacks.length; - listeners = specialCallbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, [event].concat(args)); - } - } - - return this; - }; - - // Helper for for finding special wildcard event handlers that match the event - prototype.getWildcardCallbacks = function (eventName) { - this.callbacks = this.callbacks || {}; - var item, - split, - result = []; - - for (item in this.callbacks) { - split = item.split('*'); - if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { - result = result.concat(this.callbacks[item]); - } - } - return result; - }; - -}; - -WildEmitter.mixin(WildEmitter); - -},{}],25:[function(require,module,exports){ -/*! - * EventEmitter v5.2.4 - git.io/ee - * Unlicense - http://unlicense.org/ - * Oliver Caldwell - http://oli.me.uk/ - * @preserve - */ - -;(function (exports) { - 'use strict'; - - /** - * Class for managing events. - * Can be extended to provide event functionality in other classes. - * - * @class EventEmitter Manages event registering and emitting. - */ - function EventEmitter() {} - - // Shortcuts to improve speed and size - var proto = EventEmitter.prototype; - var originalGlobalValue = exports.EventEmitter; - - /** - * Finds the index of the listener for the event in its storage array. - * - * @param {Function[]} listeners Array of listeners to search through. - * @param {Function} listener Method to look for. - * @return {Number} Index of the specified listener, -1 if not found - * @api private - */ - function indexOfListener(listeners, listener) { - var i = listeners.length; - while (i--) { - if (listeners[i].listener === listener) { - return i; - } - } - - return -1; - } - - /** - * Alias a method while keeping the context correct, to allow for overwriting of target method. - * - * @param {String} name The name of the target method. - * @return {Function} The aliased method - * @api private - */ - function alias(name) { - return function aliasClosure() { - return this[name].apply(this, arguments); - }; - } - - /** - * Returns the listener array for the specified event. - * Will initialise the event object and listener arrays if required. - * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. - * Each property in the object response is an array of listener functions. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Function[]|Object} All listener functions for the event. - */ - proto.getListeners = function getListeners(evt) { - var events = this._getEvents(); - var response; - var key; - - // Return a concatenated array of all matching events if - // the selector is a regular expression. - if (evt instanceof RegExp) { - response = {}; - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - response[key] = events[key]; - } - } - } - else { - response = events[evt] || (events[evt] = []); - } - - return response; - }; - - /** - * Takes a list of listener objects and flattens it into a list of listener functions. - * - * @param {Object[]} listeners Raw listener objects. - * @return {Function[]} Just the listener functions. - */ - proto.flattenListeners = function flattenListeners(listeners) { - var flatListeners = []; - var i; - - for (i = 0; i < listeners.length; i += 1) { - flatListeners.push(listeners[i].listener); - } - - return flatListeners; - }; - - /** - * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Object} All listener functions for an event in an object. - */ - proto.getListenersAsObject = function getListenersAsObject(evt) { - var listeners = this.getListeners(evt); - var response; - - if (listeners instanceof Array) { - response = {}; - response[evt] = listeners; - } - - return response || listeners; - }; - - function isValidListener (listener) { - if (typeof listener === 'function' || listener instanceof RegExp) { - return true - } else if (listener && typeof listener === 'object') { - return isValidListener(listener.listener) - } else { - return false - } - } - - /** - * Adds a listener function to the specified event. - * The listener will not be added if it is a duplicate. - * If the listener returns true then it will be removed after it is called. - * If you pass a regular expression as the event name then the listener will be added to all events that match it. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListener = function addListener(evt, listener) { - if (!isValidListener(listener)) { - throw new TypeError('listener must be a function'); - } - - var listeners = this.getListenersAsObject(evt); - var listenerIsWrapped = typeof listener === 'object'; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { - listeners[key].push(listenerIsWrapped ? listener : { - listener: listener, - once: false - }); - } - } - - return this; - }; - - /** - * Alias of addListener - */ - proto.on = alias('addListener'); - - /** - * Semi-alias of addListener. It will add a listener that will be - * automatically removed after its first execution. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addOnceListener = function addOnceListener(evt, listener) { - return this.addListener(evt, { - listener: listener, - once: true - }); - }; - - /** - * Alias of addOnceListener. - */ - proto.once = alias('addOnceListener'); - - /** - * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. - * You need to tell it what event names should be matched by a regex. - * - * @param {String} evt Name of the event to create. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvent = function defineEvent(evt) { - this.getListeners(evt); - return this; - }; - - /** - * Uses defineEvent to define multiple events. - * - * @param {String[]} evts An array of event names to define. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvents = function defineEvents(evts) { - for (var i = 0; i < evts.length; i += 1) { - this.defineEvent(evts[i]); - } - return this; - }; - - /** - * Removes a listener function from the specified event. - * When passed a regular expression as the event name, it will remove the listener from all events that match it. - * - * @param {String|RegExp} evt Name of the event to remove the listener from. - * @param {Function} listener Method to remove from the event. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListener = function removeListener(evt, listener) { - var listeners = this.getListenersAsObject(evt); - var index; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key)) { - index = indexOfListener(listeners[key], listener); - - if (index !== -1) { - listeners[key].splice(index, 1); - } - } - } - - return this; - }; - - /** - * Alias of removeListener - */ - proto.off = alias('removeListener'); - - /** - * Adds listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. - * You can also pass it a regular expression to add the array of listeners to all events that match it. - * Yeah, this function does quite a bit. That's probably a bad thing. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListeners = function addListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(false, evt, listeners); - }; - - /** - * Removes listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be removed. - * You can also pass it a regular expression to remove the listeners from all events that match it. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListeners = function removeListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(true, evt, listeners); - }; - - /** - * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. - * The first argument will determine if the listeners are removed (true) or added (false). - * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be added/removed. - * You can also pass it a regular expression to manipulate the listeners of all events that match it. - * - * @param {Boolean} remove True if you want to remove listeners, false if you want to add. - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add/remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { - var i; - var value; - var single = remove ? this.removeListener : this.addListener; - var multiple = remove ? this.removeListeners : this.addListeners; - - // If evt is an object then pass each of its properties to this method - if (typeof evt === 'object' && !(evt instanceof RegExp)) { - for (i in evt) { - if (evt.hasOwnProperty(i) && (value = evt[i])) { - // Pass the single listener straight through to the singular method - if (typeof value === 'function') { - single.call(this, i, value); - } - else { - // Otherwise pass back to the multiple function - multiple.call(this, i, value); - } - } - } - } - else { - // So evt must be a string - // And listeners must be an array of listeners - // Loop over it and pass each one to the multiple method - i = listeners.length; - while (i--) { - single.call(this, evt, listeners[i]); - } - } - - return this; - }; - - /** - * Removes all listeners from a specified event. - * If you do not specify an event then all listeners will be removed. - * That means every event will be emptied. - * You can also pass a regex to remove all events that match it. - * - * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeEvent = function removeEvent(evt) { - var type = typeof evt; - var events = this._getEvents(); - var key; - - // Remove different things depending on the state of evt - if (type === 'string') { - // Remove all listeners for the specified event - delete events[evt]; - } - else if (evt instanceof RegExp) { - // Remove all events matching the regex. - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - delete events[key]; - } - } - } - else { - // Remove all listeners in all events - delete this._events; - } - - return this; - }; - - /** - * Alias of removeEvent. - * - * Added to mirror the node API. - */ - proto.removeAllListeners = alias('removeEvent'); - - /** - * Emits an event of your choice. - * When emitted, every listener attached to that event will be executed. - * If you pass the optional argument array then those arguments will be passed to every listener upon execution. - * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. - * So they will not arrive within the array on the other side, they will be separate. - * You can also pass a regular expression to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {Array} [args] Optional array of arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emitEvent = function emitEvent(evt, args) { - var listenersMap = this.getListenersAsObject(evt); - var listeners; - var listener; - var i; - var key; - var response; - - for (key in listenersMap) { - if (listenersMap.hasOwnProperty(key)) { - listeners = listenersMap[key].slice(0); - - for (i = 0; i < listeners.length; i++) { - // If the listener returns true then it shall be removed from the event - // The function is executed either with a basic call or an apply if there is an args array - listener = listeners[i]; - - if (listener.once === true) { - this.removeListener(evt, listener.listener); - } - - response = listener.listener.apply(this, args || []); - - if (response === this._getOnceReturnValue()) { - this.removeListener(evt, listener.listener); - } - } - } - } - - return this; - }; - - /** - * Alias of emitEvent - */ - proto.trigger = alias('emitEvent'); - - /** - * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. - * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {...*} Optional additional arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emit = function emit(evt) { - var args = Array.prototype.slice.call(arguments, 1); - return this.emitEvent(evt, args); - }; - - /** - * Sets the current value to check against when executing listeners. If a - * listeners return value matches the one set here then it will be removed - * after execution. This value defaults to true. - * - * @param {*} value The new value to check for when executing listeners. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.setOnceReturnValue = function setOnceReturnValue(value) { - this._onceReturnValue = value; - return this; - }; - - /** - * Fetches the current value to check against when executing listeners. If - * the listeners return value matches this one then it should be removed - * automatically. It will return true by default. - * - * @return {*|Boolean} The current value to check for or the default, true. - * @api private - */ - proto._getOnceReturnValue = function _getOnceReturnValue() { - if (this.hasOwnProperty('_onceReturnValue')) { - return this._onceReturnValue; - } - else { - return true; - } - }; - - /** - * Fetches the events object and creates one if required. - * - * @return {Object} The events storage object. - * @api private - */ - proto._getEvents = function _getEvents() { - return this._events || (this._events = {}); - }; - - /** - * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. - * - * @return {Function} Non conflicting EventEmitter class. - */ - EventEmitter.noConflict = function noConflict() { - exports.EventEmitter = originalGlobalValue; - return EventEmitter; - }; - - // Expose the class either via AMD, CommonJS or the global object - if (typeof define === 'function' && define.amd) { - define(function () { - return EventEmitter; - }); - } - else if (typeof module === 'object' && module.exports){ - module.exports = EventEmitter; - } - else { - exports.EventEmitter = EventEmitter; - } -}(this || {})); - -},{}],26:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var OpenVidu_1 = require("./OpenVidu/OpenVidu"); -if (window) { - window['OpenVidu'] = OpenVidu_1.OpenVidu; -} - -},{"./OpenVidu/OpenVidu":29}],27:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Stream_1 = require("./Stream"); -var Connection = (function () { - function Connection(session, opts) { - this.session = session; - this.disposed = false; - var msg = "'Connection' created "; - if (!!opts) { - msg += "(remote) with 'connectionId' [" + opts.id + ']'; - } - else { - msg += '(local)'; - } - console.info(msg); - this.options = opts; - if (!!opts) { - this.connectionId = opts.id; - if (opts.metadata) { - this.data = opts.metadata; - } - if (opts.streams) { - this.initRemoteStreams(opts.streams); - } - } - this.creationTime = new Date().getTime(); - } - Connection.prototype.sendIceCandidate = function (candidate) { - console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate)); - this.session.openvidu.sendRequest('onIceCandidate', { - endpointName: this.connectionId, - candidate: candidate.candidate, - sdpMid: candidate.sdpMid, - sdpMLineIndex: candidate.sdpMLineIndex - }, function (error, response) { - if (error) { - console.error('Error sending ICE candidate: ' - + JSON.stringify(error)); - } - }); - }; - Connection.prototype.initRemoteStreams = function (options) { - var _this = this; - options.forEach(function (opts) { - var streamOptions = { - id: opts.id, - connection: _this, - frameRate: opts.frameRate, - recvAudio: opts.audioActive, - recvVideo: opts.videoActive, - typeOfVideo: opts.typeOfVideo - }; - var stream = new Stream_1.Stream(_this.session, streamOptions); - _this.addStream(stream); - }); - console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); - }; - Connection.prototype.addStream = function (stream) { - stream.connection = this; - this.stream = stream; - }; - Connection.prototype.removeStream = function (streamId) { - delete this.stream; - }; - Connection.prototype.dispose = function () { - if (!!this.stream) { - delete this.stream; - } - this.disposed = true; - }; - return Connection; -}()); -exports.Connection = Connection; - -},{"./Stream":32}],28:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState"); -var LocalRecorder = (function () { - function LocalRecorder(stream) { - this.stream = stream; - this.chunks = []; - this.count = 0; - this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; - this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; - this.state = LocalRecorderState_1.LocalRecorderState.READY; - } - LocalRecorder.prototype.record = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (typeof MediaRecorder === 'undefined') { - console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); - throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); - } - if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) { - throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); - } - console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'"); - if (typeof MediaRecorder.isTypeSupported === 'function') { - var options = void 0; - if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { - options = { mimeType: 'video/webm;codecs=vp9' }; - } - else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { - options = { mimeType: 'video/webm;codecs=h264' }; - } - else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { - options = { mimeType: 'video/webm;codecs=vp8' }; - } - console.log('Using mimeType ' + options.mimeType); - _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options); - } - else { - console.warn('isTypeSupported is not supported, using default codecs for browser'); - _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream()); - } - _this.mediaRecorder.start(10); - } - catch (err) { - reject(err); - } - _this.mediaRecorder.ondataavailable = function (e) { - _this.chunks.push(e.data); - }; - _this.mediaRecorder.onerror = function (e) { - console.error('MediaRecorder error: ', e); - }; - _this.mediaRecorder.onstart = function () { - console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - }; - _this.mediaRecorder.onpause = function () { - console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onresume = function () { - console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onwarning = function (e) { - console.log('MediaRecorder warning: ' + e); - }; - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - resolve(); - }); - }; - LocalRecorder.prototype.stop = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before')); - } - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - resolve(); - }; - _this.mediaRecorder.stop(); - } - catch (e) { - reject(e); - } - }); - }; - LocalRecorder.prototype.pause = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) { - reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before')); - } - _this.mediaRecorder.pause(); - _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED; - } - catch (error) { - reject(error); - } - }); - }; - LocalRecorder.prototype.resume = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) { - throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before')); - } - _this.mediaRecorder.resume(); - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - } - catch (error) { - reject(error); - } - }); - }; - LocalRecorder.prototype.preview = function (parentElement) { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - this.videoPreview = document.createElement('video'); - this.videoPreview.id = this.id; - this.videoPreview.autoplay = true; - if (typeof parentElement === 'string') { - this.htmlParentElementId = parentElement; - var parentElementDom = document.getElementById(parentElement); - if (parentElementDom) { - this.videoPreview = parentElementDom.appendChild(this.videoPreview); - } - } - else { - this.htmlParentElementId = parentElement.id; - this.videoPreview = parentElement.appendChild(this.videoPreview); - } - this.videoPreview.src = this.videoPreviewSrc; - return this.videoPreview; - }; - LocalRecorder.prototype.clean = function () { - var _this = this; - var f = function () { - delete _this.blob; - _this.chunks = []; - _this.count = 0; - delete _this.mediaRecorder; - _this.state = LocalRecorderState_1.LocalRecorderState.READY; - }; - if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) { - this.stop().then(function () { return f(); }).catch(function () { return f(); }); - } - else { - f(); - } - }; - LocalRecorder.prototype.download = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var a = document.createElement('a'); - a.style.display = 'none'; - document.body.appendChild(a); - var url = window.URL.createObjectURL(this.blob); - a.href = url; - a.download = this.id + '.webm'; - a.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(a); - } - }; - LocalRecorder.prototype.getBlob = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); - } - else { - return this.blob; - } - }; - LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_1 = new XMLHttpRequest(); - http_1.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_1.setRequestHeader(key, headers[key]); - } - } - http_1.onreadystatechange = function () { - if (http_1.readyState === 4) { - if (http_1.status.toString().charAt(0) === '2') { - resolve(http_1.responseText); - } - else { - reject(http_1.status); - } - } - }; - http_1.send(_this.blob); - } - }); - }; - LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_2 = new XMLHttpRequest(); - http_2.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_2.setRequestHeader(key, headers[key]); - } - } - var sendable = new FormData(); - sendable.append('file', _this.blob, _this.id + '.webm'); - http_2.onreadystatechange = function () { - if (http_2.readyState === 4) { - if (http_2.status.toString().charAt(0) === '2') { - resolve(http_2.responseText); - } - else { - reject(http_2.status); - } - } - }; - http_2.send(sendable); - } - }); - }; - LocalRecorder.prototype.onStopDefault = function () { - console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')'); - this.blob = new Blob(this.chunks, { type: 'video/webm' }); - this.chunks = []; - this.videoPreviewSrc = window.URL.createObjectURL(this.blob); - this.state = LocalRecorderState_1.LocalRecorderState.FINISHED; - }; - return LocalRecorder; -}()); -exports.LocalRecorder = LocalRecorder; - -},{"../OpenViduInternal/Enums/LocalRecorderState":35}],29:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorder_1 = require("./LocalRecorder"); -var Publisher_1 = require("./Publisher"); -var Session_1 = require("./Session"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); -var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); -var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); -var platform = require("platform"); -var OpenVidu = (function () { - function OpenVidu() { - this.secret = ''; - this.recorder = false; - this.advancedConfiguration = {}; - console.info("'OpenVidu' initialized"); - } - OpenVidu.prototype.initSession = function () { - this.session = new Session_1.Session(this); - return this.session; - }; - OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) { - var properties; - if (!!param2 && (typeof param2 !== 'function')) { - properties = param2; - properties = { - audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, - frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), - insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, - publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, - publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, - resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), - videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: true, - publishAudio: true, - publishVideo: true, - resolution: '640x480' - }; - } - var publisher = new Publisher_1.Publisher(targetElement, properties, this); - var completionHandler; - if (!!param2 && (typeof param2 === 'function')) { - completionHandler = param2; - } - else if (!!param3) { - completionHandler = param3; - } - publisher.initialize() - .then(function () { - if (completionHandler !== undefined) { - completionHandler(undefined); - } - publisher.emitEvent('accessAllowed', []); - }).catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - publisher.emitEvent('accessDenied', []); - }); - return publisher; - }; - OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - var publisher; - var callback = function (error) { - if (!!error) { - reject(error); - } - else { - resolve(publisher); - } - }; - if (!!properties) { - publisher = _this.initPublisher(targetElement, properties, callback); - } - else { - publisher = _this.initPublisher(targetElement, callback); - } - }); - }; - OpenVidu.prototype.initLocalRecorder = function (stream) { - return new LocalRecorder_1.LocalRecorder(stream); - }; - OpenVidu.prototype.checkSystemRequirements = function () { - var browser = platform.name; - var version = platform.version; - if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') && - (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') && - (browser !== 'Opera') && (browser !== 'Opera Mobile') && - (browser !== 'Safari')) { - return 0; - } - else { - return 1; - } - }; - OpenVidu.prototype.getDevices = function () { - return new Promise(function (resolve, reject) { - navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { - var devices = []; - deviceInfos.forEach(function (deviceInfo) { - if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { - devices.push({ - kind: deviceInfo.kind, - deviceId: deviceInfo.deviceId, - label: deviceInfo.label - }); - } - }); - resolve(devices); - }).catch(function (error) { - console.error('Error getting devices', error); - reject(error); - }); - }); - }; - OpenVidu.prototype.getUserMedia = function (options) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.generateMediaConstraints(options) - .then(function (constraints) { - navigator.mediaDevices.getUserMedia(constraints) - .then(function (mediaStream) { - resolve(mediaStream); - }) - .catch(function (error) { - var errorName; - var errorMessage = error.toString(); - if (!(options.videoSource === 'screen')) { - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; - } - reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - }) - .catch(function (error) { - reject(error); - }); - }); - }; - OpenVidu.prototype.enableProdMode = function () { - console.log = function () { }; - console.debug = function () { }; - console.info = function () { }; - console.warn = function () { }; - }; - OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { - this.advancedConfiguration = configuration; - }; - OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { - var _this = this; - return new Promise(function (resolve, reject) { - var audio, video; - if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) { - audio = false; - } - else if (publisherProperties.audioSource === undefined) { - audio = true; - } - else { - audio = publisherProperties.audioSource; - } - if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) { - video = false; - } - else { - video = { - height: { - ideal: 480 - }, - width: { - ideal: 640 - } - }; - } - var mediaConstraints = { - audio: audio, - video: video - }; - if (typeof mediaConstraints.audio === 'string') { - mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } }; - } - if (mediaConstraints.video) { - if (!!publisherProperties.resolution) { - var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); - var width = Number(widthAndHeight[0]); - var height = Number(widthAndHeight[1]); - mediaConstraints.video.width.ideal = width; - mediaConstraints.video.height.ideal = height; - } - if (!!publisherProperties.frameRate) { - mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate }; - } - if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') { - if (publisherProperties.videoSource === 'screen') { - if (platform.name !== 'Chrome' && platform.name !== 'Firefox') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); - console.error(error); - reject(error); - } - else { - if (!!_this.advancedConfiguration.screenShareChromeExtension) { - var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); - screenSharing.getChromeExtensionStatus(extensionId, function (status) { - if (status === 'installed-enabled') { - screenSharing.getScreenConstraints(function (error, screenConstraints) { - if (!!error && error === 'permission-denied') { - var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - console.error(error_1); - reject(error_1); - } - else { - mediaConstraints.video = screenConstraints; - resolve(mediaConstraints); - } - }); - } - if (status === 'installed-disabled') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - console.error(error); - reject(error); - } - if (status === 'not-installed') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); - console.error(error); - reject(error); - } - }); - } - else { - screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { - if (!!error) { - if (error === 'not-installed') { - var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); - console.error(error_2); - reject(error_2); - } - else if (error === 'installed-disabled') { - var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - console.error(error_3); - reject(error_3); - } - else if (error === 'permission-denied') { - var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - console.error(error_4); - reject(error_4); - } - } - else { - mediaConstraints.video = screenConstraints.video; - resolve(mediaConstraints); - } - }); - } - publisherProperties.videoSource = 'screen'; - } - } - else { - mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource }; - resolve(mediaConstraints); - } - } - else { - resolve(mediaConstraints); - } - } - else { - resolve(mediaConstraints); - } - }); - }; - OpenVidu.prototype.startWs = function (onConnectSucces) { - var config = { - heartbeat: 5000, - sendCloseMessage: false, - ws: { - uri: this.wsUri, - useSockJS: false, - onconnected: onConnectSucces, - ondisconnect: this.disconnectCallback.bind(this), - onreconnecting: this.reconnectingCallback.bind(this), - onreconnected: this.reconnectedCallback.bind(this) - }, - rpc: { - requestTimeout: 15000, - participantJoined: this.session.onParticipantJoined.bind(this.session), - participantPublished: this.session.onParticipantPublished.bind(this.session), - participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), - participantLeft: this.session.onParticipantLeft.bind(this.session), - participantEvicted: this.session.onParticipantEvicted.bind(this.session), - recordingStarted: this.session.onRecordingStarted.bind(this.session), - recordingStopped: this.session.onRecordingStopped.bind(this.session), - sendMessage: this.session.onNewMessage.bind(this.session), - iceCandidate: this.session.recvIceCandidate.bind(this.session), - mediaError: this.session.onMediaError.bind(this.session) - } - }; - this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); - }; - OpenVidu.prototype.closeWs = function () { - this.jsonRpcClient.close(); - }; - OpenVidu.prototype.sendRequest = function (method, params, callback) { - if (params && params instanceof Function) { - callback = params; - params = {}; - } - console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); - this.jsonRpcClient.send(method, params, callback); - }; - OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) { - var is = (!!mediaSource && - mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' && - mediaSource.id !== undefined && typeof mediaSource.id === 'string' && - mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' && - mediaSource.label !== undefined && typeof mediaSource.label === 'string' && - mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' && - mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string'); - return is; - }; - OpenVidu.prototype.getWsUri = function () { - return this.wsUri; - }; - OpenVidu.prototype.getSecret = function () { - return this.secret; - }; - OpenVidu.prototype.getRecorder = function () { - return this.recorder; - }; - OpenVidu.prototype.disconnectCallback = function () { - console.warn('Websocket connection lost'); - if (this.isRoomAvailable()) { - this.session.onLostConnection(); - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.reconnectingCallback = function () { - console.warn('Websocket connection lost (reconnecting)'); - if (this.isRoomAvailable()) { - this.session.onLostConnection(); - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.reconnectedCallback = function () { - console.warn('Websocket reconnected'); - }; - OpenVidu.prototype.isRoomAvailable = function () { - if (this.session !== undefined && this.session instanceof Session_1.Session) { - return true; - } - else { - console.warn('Session instance not found'); - return false; - } - }; - return OpenVidu; -}()); -exports.OpenVidu = OpenVidu; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":52,"../OpenViduInternal/ScreenSharing/Screen-Capturing":59,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":58,"./LocalRecorder":28,"./Publisher":30,"./Session":31,"platform":9}],30:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Session_1 = require("./Session"); -var Stream_1 = require("./Stream"); -var StreamManager_1 = require("./StreamManager"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var Publisher = (function (_super) { - __extends(Publisher, _super); - function Publisher(targEl, properties, openvidu) { - var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this; - _this.openvidu = openvidu; - _this.accessAllowed = false; - _this.isSubscribedToRemote = false; - _this.accessDenied = false; - _this.properties = properties; - _this.stream.ee.on('local-stream-destroyed-by-disconnect', function (reason) { - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - }); - return _this; - } - Publisher.prototype.publishAudio = function (value) { - this.stream.getWebRtcPeer().audioEnabled = value; - console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream'); - }; - Publisher.prototype.publishVideo = function (value) { - this.stream.getWebRtcPeer().videoEnabled = value; - console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream'); - }; - Publisher.prototype.subscribeToRemote = function (value) { - value = (value !== undefined) ? value : true; - this.isSubscribedToRemote = value; - this.stream.subscribeToMyRemote(value); - }; - Publisher.prototype.on = function (type, handler) { - var _this = this; - _super.prototype.on.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.on('stream-created-by-publisher', function () { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'remoteVideoPlaying') { - if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.ee.emitEvent('accessAllowed'); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.ee.emitEvent('accessDenied'); - } - } - return this; - }; - Publisher.prototype.once = function (type, handler) { - var _this = this; - _super.prototype.once.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.once('stream-created-by-publisher', function () { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'remoteVideoPlaying') { - if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.ee.emitEvent('accessAllowed'); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.ee.emitEvent('accessDenied'); - } - } - return this; - }; - Publisher.prototype.initialize = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var errorCallback = function (openViduError) { - _this.accessDenied = true; - _this.accessAllowed = false; - reject(openViduError); - }; - var successCallback = function (mediaStream) { - _this.accessAllowed = true; - _this.accessDenied = false; - if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) { - mediaStream.removeTrack(mediaStream.getAudioTracks()[0]); - mediaStream.addTrack(_this.properties.audioSource); - } - if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) { - mediaStream.removeTrack(mediaStream.getVideoTracks()[0]); - mediaStream.addTrack(_this.properties.videoSource); - } - if (!!mediaStream.getAudioTracks()[0]) { - mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; - } - if (!!mediaStream.getVideoTracks()[0]) { - mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; - } - _this.stream.setMediaStream(mediaStream); - if (!_this.stream.displayMyRemote()) { - _this.stream.updateMediaStreamInVideos(); - } - _this.stream.isLocalStreamReadyToPublish = true; - _this.stream.ee.emitEvent('stream-ready-to-publish', []); - if (!!_this.firstVideoElement) { - _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode); - } - delete _this.firstVideoElement; - resolve(); - }; - _this.openvidu.generateMediaConstraints(_this.properties) - .then(function (constraints) { - var outboundStreamOptions = { - mediaConstraints: constraints, - publisherProperties: _this.properties - }; - _this.stream.setOutboundStreamOptions(outboundStreamOptions); - var constraintsAux = {}; - var timeForDialogEvent = 1250; - if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) { - var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio); - constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1; - constraintsAux.video = constraints.video; - var startTime_1 = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (mediaStream) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) { - constraintsAux.audio = definedAudioConstraint_1; - constraintsAux.video = false; - startTime_1 = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (audioOnlyStream) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); - successCallback(mediaStream); - }) - .catch(function (error) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'notallowederror': - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'overconstrainederror': - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - } - }); - } - else { - successCallback(mediaStream); - } - }) - .catch(function (error) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - case 'notallowederror': - errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'overconstrainederror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - } - }); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'")); - } - }) - .catch(function (error) { - errorCallback(error); - }); - }); - }; - Publisher.prototype.updateSession = function (session) { - this.session = session; - this.stream.session = session; - }; - Publisher.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - Publisher.prototype.reestablishStreamPlayingEvent = function () { - if (this.ee.getListeners('streamPlaying').length > 0) { - this.addPlayEventToFirstVideo(); - } - }; - Publisher.prototype.setPermissionDialogTimer = function (waitTime) { - var _this = this; - this.permissionDialogTimeout = setTimeout(function () { - _this.ee.emitEvent('accessDialogOpened', []); - }, waitTime); - }; - Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) { - clearTimeout(this.permissionDialogTimeout); - if ((Date.now() - startTime) > waitTime) { - this.ee.emitEvent('accessDialogClosed', []); - } - }; - return Publisher; -}(StreamManager_1.StreamManager)); -exports.Publisher = Publisher; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Events/StreamEvent":44,"../OpenViduInternal/Events/VideoElementEvent":46,"./Session":31,"./Stream":32,"./StreamManager":33}],31:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Connection_1 = require("./Connection"); -var Subscriber_1 = require("./Subscriber"); -var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent"); -var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent"); -var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); -var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var platform = require("platform"); -var EventEmitter = require("wolfy87-eventemitter"); -var Session = (function () { - function Session(openvidu) { - this.streamManagers = []; - this.remoteStreamsCreated = {}; - this.remoteConnections = {}; - this.speakingEventsEnabled = false; - this.ee = new EventEmitter(); - this.openvidu = openvidu; - } - Session.prototype.connect = function (token, metadata) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.processToken(token); - if (_this.openvidu.checkSystemRequirements()) { - _this.options = { - sessionId: _this.sessionId, - participantId: token, - metadata: !!metadata ? _this.stringClientMetadata(metadata) : '' - }; - _this.connectAux(token).then(function () { - resolve(); - }).catch(function (error) { - reject(error); - }); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu')); - } - }); - }; - Session.prototype.disconnect = function () { - this.leave(false, 'disconnect'); - }; - Session.prototype.subscribe = function (stream, targetElement, param3, param4) { - var properties = {}; - if (!!param3 && typeof param3 !== 'function') { - properties = { - insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, - subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: true, - subscribeToVideo: true - }; - } - var completionHandler; - if (!!param3 && (typeof param3 === 'function')) { - completionHandler = param3; - } - else if (!!param4) { - completionHandler = param4; - } - console.info('Subscribing to ' + stream.connection.connectionId); - stream.subscribe() - .then(function () { - console.info('Subscribed correctly to ' + stream.connection.connectionId); - if (completionHandler !== undefined) { - completionHandler(undefined); - } - }) - .catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - }); - var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties); - if (!!subscriber.targetElement) { - stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode); - } - return subscriber; - }; - Session.prototype.subscribeAsync = function (stream, targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - var subscriber; - var callback = function (error) { - if (!!error) { - reject(error); - } - else { - resolve(subscriber); - } - }; - if (!!properties) { - subscriber = _this.subscribe(stream, targetElement, properties, callback); - } - else { - subscriber = _this.subscribe(stream, targetElement, callback); - } - }); - }; - Session.prototype.unsubscribe = function (subscriber) { - var connectionId = subscriber.stream.connection.connectionId; - console.info('Unsubscribing from ' + connectionId); - this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { - if (error) { - console.error('Error unsubscribing from ' + connectionId, error); - } - else { - console.info('Unsubscribed correctly from ' + connectionId); - } - subscriber.stream.disposeWebRtcPeer(); - subscriber.stream.disposeMediaStream(); - }); - subscriber.stream.streamManager.removeAllVideos(); - }; - Session.prototype.publish = function (publisher) { - var _this = this; - return new Promise(function (resolve, reject) { - publisher.session = _this; - publisher.stream.session = _this; - if (!publisher.stream.isLocalStreamPublished) { - _this.connection.addStream(publisher.stream); - publisher.stream.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - } - else { - publisher.initialize() - .then(function () { - _this.connection.addStream(publisher.stream); - publisher.reestablishStreamPlayingEvent(); - publisher.stream.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }).catch(function (error) { - reject(error); - }); - } - }); - }; - Session.prototype.unpublish = function (publisher) { - var stream = publisher.stream; - if (!stream.connection) { - console.error('The associated Connection object of this Publisher is null', stream); - return; - } - else if (stream.connection !== this.connection) { - console.error('The associated Connection object of this Publisher is not your local Connection.' + - "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); - return; - } - else { - console.info('Unpublishing local media (' + stream.connection.connectionId + ')'); - this.openvidu.sendRequest('unpublishVideo', function (error, response) { - if (error) { - console.error(error); - } - else { - console.info('Media unpublished correctly'); - } - }); - stream.disposeWebRtcPeer(); - delete stream.connection.stream; - var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish'); - publisher.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - } - }; - Session.prototype.signal = function (signal) { - var _this = this; - return new Promise(function (resolve, reject) { - var signalMessage = {}; - if (signal.to && signal.to.length > 0) { - var connectionIds_1 = []; - signal.to.forEach(function (connection) { - connectionIds_1.push(connection.connectionId); - }); - signalMessage['to'] = connectionIds_1; - } - else { - signalMessage['to'] = []; - } - signalMessage['data'] = signal.data ? signal.data : ''; - signalMessage['type'] = signal.type ? signal.type : ''; - _this.openvidu.sendRequest('sendMessage', { - message: JSON.stringify(signalMessage) - }, function (error, response) { - if (!!error) { - reject(error); - } - else { - resolve(); - } - }); - }); - }; - Session.prototype.on = function (type, handler) { - this.ee.on(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered by 'Session'", event); - } - else { - console.info("Event '" + type + "' triggered by 'Session'"); - } - handler(event); - }); - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = true; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !str.speechEvent && str.hasAudio) { - str.enableSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.once = function (type, handler) { - this.ee.once(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered by 'Session'", event); - } - else { - console.info("Event '" + type + "' triggered by 'Session'"); - } - handler(event); - }); - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = true; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !str.speechEvent && str.hasAudio) { - str.enableOnceSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.off = function (type, handler) { - if (!handler) { - this.ee.removeAllListeners(type); - } - else { - this.ee.off(type, handler); - } - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = false; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !!str.speechEvent) { - str.disableSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.onParticipantJoined = function (response) { - var _this = this; - this.getConnection(response.id, '') - .then(function (connection) { - console.warn('Connection ' + response.id + ' already exists in connections list'); - }) - .catch(function (openViduError) { - var connection = new Connection_1.Connection(_this, response); - _this.remoteConnections[response.id] = connection; - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - }; - Session.prototype.onParticipantLeft = function (msg) { - var _this = this; - this.getRemoteConnection(msg.name, 'Remote connection ' + msg.name + " unknown when 'onParticipantLeft'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (connection) { - if (!!connection.stream) { - var stream = connection.stream; - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - delete _this.remoteStreamsCreated[stream.streamId]; - } - delete _this.remoteConnections[connection.connectionId]; - _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onParticipantPublished = function (response) { - var _this = this; - var afterConnectionFound = function (connection) { - _this.remoteConnections[connection.connectionId] = connection; - if (!_this.remoteStreamsCreated[connection.stream.streamId]) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]); - } - _this.remoteStreamsCreated[connection.stream.streamId] = true; - }; - var connection; - this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (con) { - connection = con; - response.metadata = con.data; - connection.options = response; - connection.initRemoteStreams(response.streams); - afterConnectionFound(connection); - }) - .catch(function (openViduError) { - connection = new Connection_1.Connection(_this, response); - afterConnectionFound(connection); - }); - }; - Session.prototype.onParticipantUnpublished = function (msg) { - var _this = this; - this.getRemoteConnection(msg.name, "Remote connection '" + msg.name + "' unknown when 'onParticipantUnpublished'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (connection) { - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - var streamId = connection.stream.streamId; - delete _this.remoteStreamsCreated[streamId]; - connection.removeStream(streamId); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onParticipantEvicted = function (msg) { - }; - Session.prototype.onNewMessage = function (msg) { - var _this = this; - console.info('New signal: ' + JSON.stringify(msg)); - this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: " - + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId) - .then(function (connection) { - _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); - _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.recvIceCandidate = function (msg) { - var candidate = { - candidate: msg.candidate, - sdpMid: msg.sdpMid, - sdpMLineIndex: msg.sdpMLineIndex - }; - this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) - .then(function (connection) { - var stream = connection.stream; - stream.getWebRtcPeer().addIceCandidate(candidate, function (error) { - if (error) { - console.error('Error adding candidate for ' + stream.streamId - + ' stream of endpoint ' + msg.endpointName + ': ' + error); - } - }); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onSessionClosed = function (msg) { - console.info('Session closed: ' + JSON.stringify(msg)); - var s = msg.room; - if (s !== undefined) { - this.ee.emitEvent('session-closed', [{ - session: s - }]); - } - else { - console.warn('Session undefined on session closed', msg); - } - }; - Session.prototype.onLostConnection = function () { - if (!this.connection) { - console.warn('Not connected to session: if you are not debugging, this is probably a certificate error'); - var url = 'https://' + this.openvidu.getWsUri().split('wss://')[1].split('/openvidu')[0]; - if (window.confirm('If you are not debugging, this is probably a certificate error at \"' + url + '\"\n\nClick OK to navigate and accept it')) { - location.assign(url + '/accept-certificate'); - } - return; - } - console.warn('Lost connection in Session ' + this.sessionId); - if (!!this.sessionId && !this.connection.disposed) { - this.leave(true, 'networkDisconnect'); - } - }; - Session.prototype.onMediaError = function (params) { - console.error('Media error: ' + JSON.stringify(params)); - var err = params.error; - if (err) { - this.ee.emitEvent('error-media', [{ - error: err - }]); - } - else { - console.warn('Received undefined media error. Params:', params); - } - }; - Session.prototype.onRecordingStarted = function (response) { - this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]); - }; - Session.prototype.onRecordingStopped = function (response) { - this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]); - }; - Session.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - Session.prototype.leave = function (forced, reason) { - var _this = this; - forced = !!forced; - console.info('Leaving Session (forced=' + forced + ')'); - if (!!this.connection) { - if (!this.connection.disposed && !forced) { - this.openvidu.sendRequest('leaveRoom', function (error, response) { - if (error) { - console.error(error); - } - _this.openvidu.closeWs(); - }); - } - else { - this.openvidu.closeWs(); - } - if (!!this.connection.stream) { - this.connection.stream.disposeWebRtcPeer(); - if (this.connection.stream.isLocalStreamPublished) { - this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); - } - } - if (!this.connection.disposed) { - var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason); - this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); - sessionDisconnectEvent.callDefaultBehaviour(); - } - } - else { - console.warn('You were not connected to the session ' + this.sessionId); - } - }; - Session.prototype.connectAux = function (token) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.openvidu.startWs(function (error) { - if (!!error) { - reject(error); - } - else { - var joinParams = { - token: (!!token) ? token : '', - session: _this.sessionId, - metadata: !!_this.options.metadata ? _this.options.metadata : '', - secret: _this.openvidu.getSecret(), - recorder: _this.openvidu.getRecorder(), - }; - _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { - if (!!error) { - reject(error); - } - else { - _this.connection = new Connection_1.Connection(_this); - _this.connection.connectionId = response.id; - _this.connection.data = response.metadata; - var events_1 = { - connections: new Array(), - streams: new Array() - }; - var existingParticipants = response.value; - existingParticipants.forEach(function (participant) { - var connection = new Connection_1.Connection(_this, participant); - _this.remoteConnections[connection.connectionId] = connection; - events_1.connections.push(connection); - if (!!connection.stream) { - _this.remoteStreamsCreated[connection.stream.streamId] = true; - events_1.streams.push(connection.stream); - } - }); - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]); - events_1.connections.forEach(function (connection) { - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - events_1.streams.forEach(function (stream) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]); - }); - resolve(); - } - }); - } - }); - }); - }; - Session.prototype.stringClientMetadata = function (metadata) { - if (typeof metadata !== 'string') { - return JSON.stringify(metadata); - } - else { - return metadata; - } - }; - Session.prototype.getConnection = function (connectionId, errorMessage) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections[connectionId]; - if (!!connection) { - resolve(connection); - } - else { - if (_this.connection.connectionId === connectionId) { - resolve(_this.connection); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - } - }); - }; - Session.prototype.getRemoteConnection = function (connectionId, errorMessage) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections[connectionId]; - if (!!connection) { - resolve(connection); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - }); - }; - Session.prototype.processToken = function (token) { - var url = new URL(token); - this.sessionId = url.searchParams.get('sessionId'); - var secret = url.searchParams.get('secret'); - var recorder = url.searchParams.get('recorder'); - if (!!secret) { - this.openvidu.secret = secret; - } - if (!!recorder) { - this.openvidu.recorder = true; - } - this.openvidu.wsUri = 'wss://' + url.host + '/openvidu'; - }; - return Session; -}()); -exports.Session = Session; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/Events/ConnectionEvent":38,"../OpenViduInternal/Events/RecordingEvent":41,"../OpenViduInternal/Events/SessionDisconnectedEvent":42,"../OpenViduInternal/Events/SignalEvent":43,"../OpenViduInternal/Events/StreamEvent":44,"./Connection":27,"./Subscriber":34,"platform":9,"wolfy87-eventemitter":25}],32:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats"); -var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent"); -var EventEmitter = require("wolfy87-eventemitter"); -var kurentoUtils = require("../OpenViduInternal/KurentoUtils/kurento-utils-js"); -var Stream = (function () { - function Stream(session, options) { - var _this = this; - this.ee = new EventEmitter(); - this.isSubscribeToRemote = false; - this.isLocalStreamReadyToPublish = false; - this.isLocalStreamPublished = false; - this.session = session; - if (options.hasOwnProperty('id')) { - this.inboundStreamOpts = options; - this.streamId = this.inboundStreamOpts.id; - this.hasAudio = this.inboundStreamOpts.recvAudio; - this.hasVideo = this.inboundStreamOpts.recvVideo; - this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo; - this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; - } - else { - this.outboundStreamOpts = options; - if (this.isSendVideo()) { - if (this.isSendScreen()) { - this.streamId = 'SCREEN'; - this.typeOfVideo = 'SCREEN'; - } - else { - this.streamId = 'CAMERA'; - this.typeOfVideo = 'CAMERA'; - } - this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; - } - else { - this.streamId = 'MICRO'; - delete this.typeOfVideo; - } - this.hasAudio = this.isSendAudio(); - this.hasVideo = this.isSendVideo(); - } - this.ee.on('mediastream-updated', function () { - _this.streamManager.updateMediaStream(_this.mediaStream); - console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']'); - }); - } - Stream.prototype.getMediaStream = function () { - return this.mediaStream; - }; - Stream.prototype.setMediaStream = function (mediaStream) { - this.mediaStream = mediaStream; - }; - Stream.prototype.updateMediaStreamInVideos = function () { - this.ee.emitEvent('mediastream-updated'); - }; - Stream.prototype.getWebRtcPeer = function () { - return this.webRtcPeer; - }; - Stream.prototype.getRTCPeerConnection = function () { - return this.webRtcPeer.peerConnection; - }; - Stream.prototype.subscribeToMyRemote = function (value) { - this.isSubscribeToRemote = value; - }; - Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { - this.outboundStreamOpts = outboundStreamOpts; - }; - Stream.prototype.subscribe = function () { - var _this = this; - return new Promise(function (resolve, reject) { - _this.initWebRtcPeerReceive() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }); - }; - Stream.prototype.publish = function () { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.isLocalStreamReadyToPublish) { - _this.initWebRtcPeerSend() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - } - else { - _this.ee.once('stream-ready-to-publish', function () { - _this.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }); - } - }); - }; - Stream.prototype.disposeWebRtcPeer = function () { - if (this.webRtcPeer) { - this.webRtcPeer.dispose(); - } - if (this.speechEvent) { - this.speechEvent.stop(); - } - this.stopWebRtcStats(); - console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed'); - }; - Stream.prototype.disposeMediaStream = function () { - if (this.mediaStream) { - this.mediaStream.getAudioTracks().forEach(function (track) { - track.stop(); - }); - this.mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - delete this.mediaStream; - } - console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed'); - }; - Stream.prototype.displayMyRemote = function () { - return this.isSubscribeToRemote; - }; - Stream.prototype.isSendAudio = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.audioSource !== null && - this.outboundStreamOpts.publisherProperties.audioSource !== false); - }; - Stream.prototype.isSendVideo = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.videoSource !== null && - this.outboundStreamOpts.publisherProperties.videoSource !== false); - }; - Stream.prototype.isSendScreen = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.videoSource === 'screen'); - }; - Stream.prototype.setSpeechEventIfNotExists = function () { - if (!this.speechEvent) { - var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}; - harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50; - harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50; - this.speechEvent = kurentoUtils.WebRtcPeer.hark(this.mediaStream, harkOptions); - } - }; - Stream.prototype.enableSpeakingEvents = function () { - var _this = this; - this.setSpeechEventIfNotExists(); - this.speechEvent.on('speaking', function () { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - }); - this.speechEvent.on('stopped_speaking', function () { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - }); - }; - Stream.prototype.enableOnceSpeakingEvents = function () { - var _this = this; - this.setSpeechEventIfNotExists(); - this.speechEvent.on('speaking', function () { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - _this.disableSpeakingEvents(); - }); - this.speechEvent.on('stopped_speaking', function () { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - _this.disableSpeakingEvents(); - }); - }; - Stream.prototype.disableSpeakingEvents = function () { - this.speechEvent.stop(); - this.speechEvent = undefined; - }; - Stream.prototype.initWebRtcPeerSend = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var userMediaConstraints = { - audio: _this.isSendAudio(), - video: _this.isSendVideo() - }; - var options = { - videoStream: _this.mediaStream, - mediaConstraints: userMediaConstraints, - onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), - iceServers: _this.session.openvidu.advancedConfiguration.iceServers - }; - var successCallback = function (error, sdpOfferParam, wp) { - if (error) { - reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error))); - } - console.debug('Sending SDP offer to publish as ' - + _this.streamId, sdpOfferParam); - _this.session.openvidu.sendRequest('publishVideo', { - sdpOffer: sdpOfferParam, - doLoopback: _this.displayMyRemote() || false, - audioActive: _this.isSendAudio(), - videoActive: _this.isSendVideo(), - typeOfVideo: ((_this.isSendVideo()) ? (_this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''), - frameRate: !!_this.frameRate ? _this.frameRate : -1 - }, function (error, response) { - if (error) { - reject('Error on publishVideo: ' + JSON.stringify(error)); - } - else { - _this.processSdpAnswer(response.sdpAnswer) - .then(function () { - _this.isLocalStreamPublished = true; - if (_this.displayMyRemote()) { - _this.updateMediaStreamInVideos(); - } - _this.ee.emitEvent('stream-created-by-publisher'); - resolve(); - }) - .catch(function (error) { - reject(error); - }); - console.info("'Publisher' successfully published to session"); - } - }); - }; - if (_this.displayMyRemote()) { - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function (err) { - if (err) { - reject(err); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - } - else { - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options, function (error) { - if (error) { - reject(error); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - } - }); - }; - Stream.prototype.initWebRtcPeerReceive = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var offerConstraints = { - audio: _this.inboundStreamOpts.recvAudio, - video: _this.inboundStreamOpts.recvVideo - }; - console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); - var options = { - onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), - mediaConstraints: offerConstraints - }; - var successCallback = function (error, sdpOfferParam, wp) { - if (error) { - reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error))); - } - console.debug('Sending SDP offer to subscribe to ' - + _this.streamId, sdpOfferParam); - _this.session.openvidu.sendRequest('receiveVideoFrom', { - sender: _this.streamId, - sdpOffer: sdpOfferParam - }, function (error, response) { - if (error) { - reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error))); - } - else { - _this.processSdpAnswer(response.sdpAnswer).then(function () { - resolve(); - }).catch(function (error) { - reject(error); - }); - } - }); - }; - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function (error) { - if (error) { - reject(error); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - }); - }; - Stream.prototype.processSdpAnswer = function (sdpAnswer) { - var _this = this; - return new Promise(function (resolve, reject) { - var answer = new RTCSessionDescription({ - type: 'answer', - sdp: sdpAnswer, - }); - console.debug(_this.streamId + ': set peer connection with recvd SDP answer', sdpAnswer); - var streamId = _this.streamId; - var peerConnection = _this.webRtcPeer.peerConnection; - peerConnection.setRemoteDescription(answer, function () { - if (!_this.isLocal() || _this.displayMyRemote()) { - _this.mediaStream = peerConnection.getRemoteStreams()[0]; - console.debug('Peer remote stream', _this.mediaStream); - if (!!_this.mediaStream) { - _this.ee.emitEvent('mediastream-updated'); - if (!!_this.mediaStream.getAudioTracks()[0] && _this.session.speakingEventsEnabled) { - _this.enableSpeakingEvents(); - } - } - } - _this.initWebRtcStats(); - resolve(); - }, function (error) { - reject(new Error(_this.streamId + ': Error setting SDP to the peer connection: ' + JSON.stringify(error))); - }); - }); - }; - Stream.prototype.initWebRtcStats = function () { - this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); - this.webRtcStats.initWebRtcStats(); - }; - Stream.prototype.stopWebRtcStats = function () { - if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { - this.webRtcStats.stopWebRtcStats(); - } - }; - Stream.prototype.isLocal = function () { - return (!this.inboundStreamOpts && !!this.outboundStreamOpts); - }; - return Stream; -}()); -exports.Stream = Stream; - -},{"../OpenViduInternal/Events/PublisherSpeakingEvent":40,"../OpenViduInternal/KurentoUtils/kurento-utils-js":57,"../OpenViduInternal/WebRtcStats/WebRtcStats":60,"wolfy87-eventemitter":25}],33:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); -var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var EventEmitter = require("wolfy87-eventemitter"); -var StreamManager = (function () { - function StreamManager(stream, targetElement) { - var _this = this; - this.videos = []; - this.lazyLaunchVideoElementCreatedEvent = false; - this.ee = new EventEmitter(); - this.stream = stream; - this.stream.streamManager = this; - this.remote = !this.stream.isLocal(); - if (!!targetElement) { - var targEl = void 0; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targetElement); - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - if (!!targEl) { - this.firstVideoElement = { - targetElement: targEl, - video: document.createElement('video'), - id: '' - }; - this.targetElement = targEl; - this.element = targEl; - } - } - this.canPlayListener = function () { - if (_this.stream.isLocal()) { - if (!_this.stream.displayMyRemote()) { - console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); - } - else { - console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]); - } - } - else { - console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); - } - _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]); - }; - } - StreamManager.prototype.on = function (type, handler) { - this.ee.on(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered", event); - } - else { - console.info("Event '" + type + "' triggered"); - } - handler(event); - }); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = false; - } - } - if (type === 'streamPlaying' || type === 'videoPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); - this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); - } - } - return this; - }; - StreamManager.prototype.once = function (type, handler) { - this.ee.once(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered once", event); - } - else { - console.info("Event '" + type + "' triggered once"); - } - handler(event); - }); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - } - } - if (type === 'streamPlaying' || type === 'videoPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); - this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); - } - } - return this; - }; - StreamManager.prototype.off = function (type, handler) { - if (!handler) { - this.ee.removeAllListeners(type); - } - else { - this.ee.off(type, handler); - } - return this; - }; - StreamManager.prototype.addVideoElement = function (video) { - this.initializeVideoProperties(video); - for (var _i = 0, _a = this.videos; _i < _a.length; _i++) { - var v = _a[_i]; - if (v.video === video) { - return 0; - } - } - var returnNumber = 1; - this.initializeVideoProperties(video); - for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) { - var streamManager = _c[_b]; - if (streamManager.disassociateVideo(video)) { - returnNumber = -1; - break; - } - } - this.stream.session.streamManagers.forEach(function (streamManager) { - streamManager.disassociateVideo(video); - }); - this.pushNewStreamManagerVideo({ - video: video, - id: video.id - }); - console.info('New video element associated to ', this); - return returnNumber; - }; - StreamManager.prototype.createVideoElement = function (targetElement, insertMode) { - var targEl; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targEl); - if (!targEl) { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - else { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - var video = document.createElement('video'); - this.initializeVideoProperties(video); - var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; - switch (insMode) { - case VideoInsertMode_1.VideoInsertMode.AFTER: - targEl.parentNode.insertBefore(video, targEl.nextSibling); - break; - case VideoInsertMode_1.VideoInsertMode.APPEND: - targEl.appendChild(video); - break; - case VideoInsertMode_1.VideoInsertMode.BEFORE: - targEl.parentNode.insertBefore(video, targEl); - break; - case VideoInsertMode_1.VideoInsertMode.PREPEND: - targEl.insertBefore(video, targEl.childNodes[0]); - break; - case VideoInsertMode_1.VideoInsertMode.REPLACE: - targEl.parentNode.replaceChild(video, targEl); - break; - default: - insMode = VideoInsertMode_1.VideoInsertMode.APPEND; - targEl.appendChild(video); - break; - } - var v = { - targetElement: targEl, - video: video, - insertMode: insMode, - id: video.id - }; - this.pushNewStreamManagerVideo(v); - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement; - return video; - }; - StreamManager.prototype.initializeVideoProperties = function (video) { - video.srcObject = this.stream.getMediaStream(); - video.autoplay = true; - video.controls = false; - if (!video.id) { - video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId; - if (!this.id && !!this.targetElement) { - this.id = video.id; - } - } - if (!this.remote && !this.stream.displayMyRemote()) { - video.muted = true; - if (this.stream.outboundStreamOpts.publisherProperties.mirror) { - this.mirrorVideo(video); - } - } - }; - StreamManager.prototype.removeAllVideos = function () { - var _this = this; - for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) { - if (this.stream.session.streamManagers[i] === this) { - this.stream.session.streamManagers.splice(i, 1); - } - } - this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) { - streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener); - if (!!streamManagerVideo.targetElement) { - streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video); - _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]); - _this.videos.splice(videos.length - 1 - index, 1); - } - else { - streamManagerVideo.video.srcObject = null; - } - }); - }; - StreamManager.prototype.disassociateVideo = function (video) { - var disassociated = false; - for (var i = 0; i < this.videos.length; i++) { - if (this.videos[i].video === video) { - this.videos.splice(i, 1); - disassociated = true; - console.info('Video element disassociated from ', this); - break; - } - } - return disassociated; - }; - StreamManager.prototype.addPlayEventToFirstVideo = function () { - if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) { - this.videos[0].video.addEventListener('canplay', this.canPlayListener); - } - }; - StreamManager.prototype.updateMediaStream = function (mediaStream) { - this.videos.forEach(function (streamManagerVideo) { - streamManagerVideo.video.srcObject = mediaStream; - }); - }; - StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) { - this.videos.push(streamManagerVideo); - this.addPlayEventToFirstVideo(); - if (this.stream.session.streamManagers.indexOf(this) === -1) { - this.stream.session.streamManagers.push(this); - } - }; - StreamManager.prototype.mirrorVideo = function (video) { - video.style.transform = 'rotateY(180deg)'; - video.style.webkitTransform = 'rotateY(180deg)'; - }; - return StreamManager; -}()); -exports.StreamManager = StreamManager; - -},{"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/Events/StreamManagerEvent":45,"../OpenViduInternal/Events/VideoElementEvent":46,"wolfy87-eventemitter":25}],34:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var StreamManager_1 = require("./StreamManager"); -var Subscriber = (function (_super) { - __extends(Subscriber, _super); - function Subscriber(stream, targEl, properties) { - var _this = _super.call(this, stream, targEl) || this; - _this.element = _this.targetElement; - _this.stream = stream; - _this.properties = properties; - return _this; - } - Subscriber.prototype.subscribeToAudio = function (value) { - this.stream.getMediaStream().getAudioTracks().forEach(function (track) { - track.enabled = value; - }); - console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream'); - return this; - }; - Subscriber.prototype.subscribeToVideo = function (value) { - this.stream.getMediaStream().getVideoTracks().forEach(function (track) { - track.enabled = value; - }); - console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream'); - return this; - }; - return Subscriber; -}(StreamManager_1.StreamManager)); -exports.Subscriber = Subscriber; - -},{"./StreamManager":33}],35:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorderState; -(function (LocalRecorderState) { - LocalRecorderState["READY"] = "READY"; - LocalRecorderState["RECORDING"] = "RECORDING"; - LocalRecorderState["PAUSED"] = "PAUSED"; - LocalRecorderState["FINISHED"] = "FINISHED"; -})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {})); - -},{}],36:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var OpenViduErrorName; -(function (OpenViduErrorName) { - OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; - OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED"; - OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; - OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; - OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; - OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED"; - OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; - OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; - OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; - OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; - OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; - OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED"; - OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; -})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); -var OpenViduError = (function () { - function OpenViduError(name, message) { - this.name = name; - this.message = message; - } - return OpenViduError; -}()); -exports.OpenViduError = OpenViduError; - -},{}],37:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var VideoInsertMode; -(function (VideoInsertMode) { - VideoInsertMode["AFTER"] = "AFTER"; - VideoInsertMode["APPEND"] = "APPEND"; - VideoInsertMode["BEFORE"] = "BEFORE"; - VideoInsertMode["PREPEND"] = "PREPEND"; - VideoInsertMode["REPLACE"] = "REPLACE"; -})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); - -},{}],38:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var ConnectionEvent = (function (_super) { - __extends(ConnectionEvent, _super); - function ConnectionEvent(cancelable, target, type, connection, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.connection = connection; - _this.reason = reason; - return _this; - } - ConnectionEvent.prototype.callDefaultBehaviour = function () { }; - return ConnectionEvent; -}(Event_1.Event)); -exports.ConnectionEvent = ConnectionEvent; - -},{"./Event":39}],39:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Event = (function () { - function Event(cancelable, target, type) { - this.hasBeenPrevented = false; - this.cancelable = cancelable; - this.target = target; - this.type = type; - } - Event.prototype.isDefaultPrevented = function () { - return this.hasBeenPrevented; - }; - Event.prototype.preventDefault = function () { - this.callDefaultBehaviour = function () { }; - this.hasBeenPrevented = true; - }; - return Event; -}()); -exports.Event = Event; - -},{}],40:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var PublisherSpeakingEvent = (function (_super) { - __extends(PublisherSpeakingEvent, _super); - function PublisherSpeakingEvent(target, type, connection, streamId) { - var _this = _super.call(this, false, target, type) || this; - _this.type = type; - _this.connection = connection; - _this.streamId = streamId; - return _this; - } - PublisherSpeakingEvent.prototype.callDefaultBehaviour = function () { }; - return PublisherSpeakingEvent; -}(Event_1.Event)); -exports.PublisherSpeakingEvent = PublisherSpeakingEvent; - -},{"./Event":39}],41:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var RecordingEvent = (function (_super) { - __extends(RecordingEvent, _super); - function RecordingEvent(target, type, id, name) { - var _this = _super.call(this, false, target, type) || this; - _this.id = id; - if (name !== id) { - _this.name = name; - } - return _this; - } - RecordingEvent.prototype.callDefaultBehaviour = function () { }; - return RecordingEvent; -}(Event_1.Event)); -exports.RecordingEvent = RecordingEvent; - -},{"./Event":39}],42:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var SessionDisconnectedEvent = (function (_super) { - __extends(SessionDisconnectedEvent, _super); - function SessionDisconnectedEvent(target, reason) { - var _this = _super.call(this, true, target, 'sessionDisconnected') || this; - _this.reason = reason; - return _this; - } - SessionDisconnectedEvent.prototype.callDefaultBehaviour = function () { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); - var session = this.target; - for (var connectionId in session.remoteConnections) { - if (!!session.remoteConnections[connectionId].stream) { - session.remoteConnections[connectionId].stream.disposeWebRtcPeer(); - session.remoteConnections[connectionId].stream.disposeMediaStream(); - if (session.remoteConnections[connectionId].stream.streamManager) { - session.remoteConnections[connectionId].stream.streamManager.removeAllVideos(); - } - delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId]; - session.remoteConnections[connectionId].dispose(); - } - delete session.remoteConnections[connectionId]; - } - }; - return SessionDisconnectedEvent; -}(Event_1.Event)); -exports.SessionDisconnectedEvent = SessionDisconnectedEvent; - -},{"./Event":39}],43:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var SignalEvent = (function (_super) { - __extends(SignalEvent, _super); - function SignalEvent(target, type, data, from) { - var _this = _super.call(this, false, target, type) || this; - _this.type = type; - _this.data = data; - _this.from = from; - return _this; - } - SignalEvent.prototype.callDefaultBehaviour = function () { }; - return SignalEvent; -}(Event_1.Event)); -exports.SignalEvent = SignalEvent; - -},{"./Event":39}],44:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var Publisher_1 = require("../../OpenVidu/Publisher"); -var Session_1 = require("../../OpenVidu/Session"); -var StreamEvent = (function (_super) { - __extends(StreamEvent, _super); - function StreamEvent(cancelable, target, type, stream, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.stream = stream; - _this.reason = reason; - return _this; - } - StreamEvent.prototype.callDefaultBehaviour = function () { - if (this.type === 'streamDestroyed') { - if (this.target instanceof Session_1.Session) { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); - this.stream.disposeWebRtcPeer(); - } - else if (this.target instanceof Publisher_1.Publisher) { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Publisher'"); - this.stream.isLocalStreamReadyToPublish = false; - } - this.stream.disposeMediaStream(); - if (this.stream.streamManager) - this.stream.streamManager.removeAllVideos(); - delete this.stream.session.remoteStreamsCreated[this.stream.streamId]; - var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId]; - if (!!remoteConnection && !!remoteConnection.options) { - var streamOptionsServer = remoteConnection.options.streams; - for (var i = streamOptionsServer.length - 1; i >= 0; --i) { - if (streamOptionsServer[i].id === this.stream.streamId) { - streamOptionsServer.splice(i, 1); - } - } - } - } - }; - return StreamEvent; -}(Event_1.Event)); -exports.StreamEvent = StreamEvent; - -},{"../../OpenVidu/Publisher":30,"../../OpenVidu/Session":31,"./Event":39}],45:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var StreamManagerEvent = (function (_super) { - __extends(StreamManagerEvent, _super); - function StreamManagerEvent(target) { - return _super.call(this, false, target, 'streamPlaying') || this; - } - StreamManagerEvent.prototype.callDefaultBehaviour = function () { }; - return StreamManagerEvent; -}(Event_1.Event)); -exports.StreamManagerEvent = StreamManagerEvent; - -},{"./Event":39}],46:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var VideoElementEvent = (function (_super) { - __extends(VideoElementEvent, _super); - function VideoElementEvent(element, target, type) { - var _this = _super.call(this, false, target, type) || this; - _this.element = element; - return _this; - } - VideoElementEvent.prototype.callDefaultBehaviour = function () { }; - return VideoElementEvent; -}(Event_1.Event)); -exports.VideoElementEvent = VideoElementEvent; - -},{"./Event":39}],47:[function(require,module,exports){ -function Mapper() { - var sources = {}; - this.forEach = function (callback) { - for (var key in sources) { - var source = sources[key]; - for (var key2 in source) - callback(source[key2]); - } - ; - }; - this.get = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return undefined; - return ids[id]; - }; - this.remove = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return; - delete ids[id]; - for (var i in ids) { - return false; - } - delete sources[source]; - }; - this.set = function (value, id, source) { - if (value == undefined) - return this.remove(id, source); - var ids = sources[source]; - if (ids == undefined) - sources[source] = ids = {}; - ids[id] = value; - }; -} -; -Mapper.prototype.pop = function (id, source) { - var value = this.get(id, source); - if (value == undefined) - return undefined; - this.remove(id, source); - return value; -}; -module.exports = Mapper; - -},{}],48:[function(require,module,exports){ -var JsonRpcClient = require('./jsonrpcclient'); -exports.JsonRpcClient = JsonRpcClient; - -},{"./jsonrpcclient":49}],49:[function(require,module,exports){ -var RpcBuilder = require('../'); -var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); -Date.now = Date.now || function () { - return +new Date; -}; -var PING_INTERVAL = 5000; -var RECONNECTING = 'RECONNECTING'; -var CONNECTED = 'CONNECTED'; -var DISCONNECTED = 'DISCONNECTED'; -var Logger = console; -function JsonRpcClient(configuration) { - var self = this; - var wsConfig = configuration.ws; - var notReconnectIfNumLessThan = -1; - var pingNextNum = 0; - var enabledPings = true; - var pingPongStarted = false; - var pingInterval; - var status = DISCONNECTED; - var onreconnecting = wsConfig.onreconnecting; - var onreconnected = wsConfig.onreconnected; - var onconnected = wsConfig.onconnected; - var onerror = wsConfig.onerror; - configuration.rpc.pull = function (params, request) { - request.reply(null, "push"); - }; - wsConfig.onreconnecting = function () { - Logger.debug("--------- ONRECONNECTING -----------"); - if (status === RECONNECTING) { - Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it"); - return; - } - status = RECONNECTING; - if (onreconnecting) { - onreconnecting(); - } - }; - wsConfig.onreconnected = function () { - Logger.debug("--------- ONRECONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - enabledPings = true; - updateNotReconnectIfLessThan(); - usePing(); - if (onreconnected) { - onreconnected(); - } - }; - wsConfig.onconnected = function () { - Logger.debug("--------- ONCONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - enabledPings = true; - usePing(); - if (onconnected) { - onconnected(); - } - }; - wsConfig.onerror = function (error) { - Logger.debug("--------- ONERROR -----------"); - status = DISCONNECTED; - if (onerror) { - onerror(error); - } - }; - var ws = new WebSocketWithReconnection(wsConfig); - Logger.debug('Connecting websocket to URI: ' + wsConfig.uri); - var rpcBuilderOptions = { - request_timeout: configuration.rpc.requestTimeout, - ping_request_timeout: configuration.rpc.heartbeatRequestTimeout - }; - var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) { - Logger.debug('Received request: ' + JSON.stringify(request)); - try { - var func = configuration.rpc[request.method]; - if (func === undefined) { - Logger.error("Method " + request.method + " not registered in client"); - } - else { - func(request.params, request); - } - } - catch (err) { - Logger.error('Exception processing request: ' + JSON.stringify(request)); - Logger.error(err); - } - }); - this.send = function (method, params, callback) { - if (method !== 'ping') { - Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); - } - var requestTime = Date.now(); - rpc.encode(method, params, function (error, result) { - if (error) { - try { - Logger.error("ERROR:" + error.message + " in Request: method:" + - method + " params:" + JSON.stringify(params) + " request:" + - error.request); - if (error.data) { - Logger.error("ERROR DATA:" + JSON.stringify(error.data)); - } - } - catch (e) { } - error.requestTime = requestTime; - } - if (callback) { - if (result != undefined && result.value !== 'pong') { - Logger.debug('Response: ' + JSON.stringify(result)); - } - callback(error, result); - } - }); - }; - function updateNotReconnectIfLessThan() { - Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' + - notReconnectIfNumLessThan + ')'); - notReconnectIfNumLessThan = pingNextNum; - } - function sendPing() { - if (enabledPings) { - var params = null; - if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) { - params = { - interval: configuration.heartbeat || PING_INTERVAL - }; - } - pingNextNum++; - self.send('ping', params, (function (pingNum) { - return function (error, result) { - if (error) { - Logger.debug("Error in ping request #" + pingNum + " (" + - error.message + ")"); - if (pingNum > notReconnectIfNumLessThan) { - enabledPings = false; - updateNotReconnectIfLessThan(); - Logger.debug("Server did not respond to ping message #" + - pingNum + ". Reconnecting... "); - ws.reconnectWs(); - } - } - }; - })(pingNextNum)); - } - else { - Logger.debug("Trying to send ping, but ping is not enabled"); - } - } - function usePing() { - if (!pingPongStarted) { - Logger.debug("Starting ping (if configured)"); - pingPongStarted = true; - if (configuration.heartbeat != undefined) { - pingInterval = setInterval(sendPing, configuration.heartbeat); - sendPing(); - } - } - } - this.close = function () { - Logger.debug("Closing jsonRpcClient explicitly by client"); - if (pingInterval != undefined) { - Logger.debug("Clearing ping interval"); - clearInterval(pingInterval); - } - pingPongStarted = false; - enabledPings = false; - if (configuration.sendCloseMessage) { - Logger.debug("Sending close message"); - this.send('closeSession', null, function (error, result) { - if (error) { - Logger.error("Error sending close message: " + JSON.stringify(error)); - } - ws.close(); - }); - } - else { - ws.close(); - } - }; - this.forceClose = function (millis) { - ws.forceClose(millis); - }; - this.reconnect = function () { - ws.reconnectWs(); - }; -} -module.exports = JsonRpcClient; - -},{"../":52,"./transports/webSocketWithReconnection":51}],50:[function(require,module,exports){ -var WebSocketWithReconnection = require('./webSocketWithReconnection'); -exports.WebSocketWithReconnection = WebSocketWithReconnection; - -},{"./webSocketWithReconnection":51}],51:[function(require,module,exports){ -(function (global){ -"use strict"; -var BrowserWebSocket = global.WebSocket || global.MozWebSocket; -var Logger = console; -var MAX_RETRIES = 2000; -var RETRY_TIME_MS = 3000; -var CONNECTING = 0; -var OPEN = 1; -var CLOSING = 2; -var CLOSED = 3; -function WebSocketWithReconnection(config) { - var closing = false; - var registerMessageHandler; - var wsUri = config.uri; - var useSockJS = config.useSockJS; - var reconnecting = false; - var forcingDisconnection = false; - var ws; - if (useSockJS) { - ws = new SockJS(wsUri); - } - else { - ws = new WebSocket(wsUri); - } - ws.onopen = function () { - logConnected(ws, wsUri); - if (config.onconnected) { - config.onconnected(); - } - }; - ws.onerror = function (error) { - Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error); - if (config.onerror) { - config.onerror(error); - } - }; - function logConnected(ws, wsUri) { - try { - Logger.debug("WebSocket connected to " + wsUri); - } - catch (e) { - Logger.error(e); - } - } - var reconnectionOnClose = function () { - if (ws.readyState === CLOSED) { - if (closing) { - Logger.debug("Connection closed by user"); - } - else { - Logger.debug("Connection closed unexpectecly. Reconnecting..."); - reconnectToSameUri(MAX_RETRIES, 1); - } - } - else { - Logger.debug("Close callback from previous websocket. Ignoring it"); - } - }; - ws.onclose = reconnectionOnClose; - function reconnectToSameUri(maxRetries, numRetries) { - Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); - if (numRetries === 1) { - if (reconnecting) { - Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); - return; - } - else { - reconnecting = true; - } - if (config.onreconnecting) { - config.onreconnecting(); - } - } - if (forcingDisconnection) { - reconnectToNewUri(maxRetries, numRetries, wsUri); - } - else { - if (config.newWsUriOnReconnection) { - config.newWsUriOnReconnection(function (error, newWsUri) { - if (error) { - Logger.debug(error); - setTimeout(function () { - reconnectToSameUri(maxRetries, numRetries + 1); - }, RETRY_TIME_MS); - } - else { - reconnectToNewUri(maxRetries, numRetries, newWsUri); - } - }); - } - else { - reconnectToNewUri(maxRetries, numRetries, wsUri); - } - } - } - function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { - Logger.debug("Reconnection attempt #" + numRetries); - ws.close(); - wsUri = reconnectWsUri || wsUri; - var newWs; - if (useSockJS) { - newWs = new SockJS(wsUri); - } - else { - newWs = new WebSocket(wsUri); - } - newWs.onopen = function () { - Logger.debug("Reconnected after " + numRetries + " attempts..."); - logConnected(newWs, wsUri); - reconnecting = false; - registerMessageHandler(); - if (config.onreconnected()) { - config.onreconnected(); - } - newWs.onclose = reconnectionOnClose; - }; - var onErrorOrClose = function (error) { - Logger.warn("Reconnection error: ", error); - if (numRetries === maxRetries) { - if (config.ondisconnect) { - config.ondisconnect(); - } - } - else { - setTimeout(function () { - reconnectToSameUri(maxRetries, numRetries + 1); - }, RETRY_TIME_MS); - } - }; - newWs.onerror = onErrorOrClose; - ws = newWs; - } - this.close = function () { - closing = true; - ws.close(); - }; - this.forceClose = function (millis) { - Logger.debug("Testing: Force WebSocket close"); - if (millis) { - Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); - var goodWsUri = wsUri; - wsUri = "wss://21.234.12.34.4:443/"; - forcingDisconnection = true; - setTimeout(function () { - Logger.debug("Testing: Recover good wsUri " + goodWsUri); - wsUri = goodWsUri; - forcingDisconnection = false; - }, millis); - } - ws.close(); - }; - this.reconnectWs = function () { - Logger.debug("reconnectWs"); - reconnectToSameUri(MAX_RETRIES, 1, wsUri); - }; - this.send = function (message) { - ws.send(message); - }; - this.addEventListener = function (type, callback) { - registerMessageHandler = function () { - ws.addEventListener(type, callback); - }; - registerMessageHandler(); - }; -} -module.exports = WebSocketWithReconnection; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],52:[function(require,module,exports){ -var defineProperty_IE8 = false; -if (Object.defineProperty) { - try { - Object.defineProperty({}, "x", {}); - } - catch (e) { - defineProperty_IE8 = true; - } -} -if (!Function.prototype.bind) { - Function.prototype.bind = function (oThis) { - if (typeof this !== 'function') { - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { - return fToBind.apply(this instanceof fNOP && oThis - ? this - : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); - }; - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - return fBound; - }; -} -var EventEmitter = require('events').EventEmitter; -var inherits = require('inherits'); -var packers = require('./packers'); -var Mapper = require('./Mapper'); -var BASE_TIMEOUT = 5000; -function unifyResponseMethods(responseMethods) { - if (!responseMethods) - return {}; - for (var key in responseMethods) { - var value = responseMethods[key]; - if (typeof value == 'string') - responseMethods[key] = - { - response: value - }; - } - ; - return responseMethods; -} -; -function unifyTransport(transport) { - if (!transport) - return; - if (transport instanceof Function) - return { send: transport }; - if (transport.send instanceof Function) - return transport; - if (transport.postMessage instanceof Function) { - transport.send = transport.postMessage; - return transport; - } - if (transport.write instanceof Function) { - transport.send = transport.write; - return transport; - } - if (transport.onmessage !== undefined) - return; - if (transport.pause instanceof Function) - return; - throw new SyntaxError("Transport is not a function nor a valid object"); -} -; -function RpcNotification(method, params) { - if (defineProperty_IE8) { - this.method = method; - this.params = params; - } - else { - Object.defineProperty(this, 'method', { value: method, enumerable: true }); - Object.defineProperty(this, 'params', { value: params, enumerable: true }); - } -} -; -function RpcBuilder(packer, options, transport, onRequest) { - var self = this; - if (!packer) - throw new SyntaxError('Packer is not defined'); - if (!packer.pack || !packer.unpack) - throw new SyntaxError('Packer is invalid'); - var responseMethods = unifyResponseMethods(packer.responseMethods); - if (options instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = options; - transport = undefined; - options = undefined; - } - ; - if (options && options.send instanceof Function) { - if (transport && !(transport instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - onRequest = transport; - transport = options; - options = undefined; - } - ; - if (transport instanceof Function) { - if (onRequest != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = transport; - transport = undefined; - } - ; - if (transport && transport.send instanceof Function) - if (onRequest && !(onRequest instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - options = options || {}; - EventEmitter.call(this); - if (onRequest) - this.on('request', onRequest); - if (defineProperty_IE8) - this.peerID = options.peerID; - else - Object.defineProperty(this, 'peerID', { value: options.peerID }); - var max_retries = options.max_retries || 0; - function transportMessage(event) { - self.decode(event.data || event); - } - ; - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - if (transport) { - if (transport.removeEventListener) - transport.removeEventListener('message', transportMessage); - else if (transport.removeListener) - transport.removeListener('data', transportMessage); - } - ; - if (value) { - if (value.addEventListener) - value.addEventListener('message', transportMessage); - else if (value.addListener) - value.addListener('data', transportMessage); - } - ; - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - this.setTransport(transport); - var request_timeout = options.request_timeout || BASE_TIMEOUT; - var ping_request_timeout = options.ping_request_timeout || request_timeout; - var response_timeout = options.response_timeout || BASE_TIMEOUT; - var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT; - var requestID = 0; - var requests = new Mapper(); - var responses = new Mapper(); - var processedResponses = new Mapper(); - var message2Key = {}; - function storeResponse(message, id, dest) { - var response = { - message: message, - timeout: setTimeout(function () { - responses.remove(id, dest); - }, response_timeout) - }; - responses.set(response, id, dest); - } - ; - function storeProcessedResponse(ack, from) { - var timeout = setTimeout(function () { - processedResponses.remove(ack, from); - }, duplicates_timeout); - processedResponses.set(timeout, ack, from); - } - ; - function RpcRequest(method, params, id, from, transport) { - RpcNotification.call(this, method, params); - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - var response = responses.get(id, from); - if (!(transport || self.getTransport())) { - if (defineProperty_IE8) - this.duplicated = Boolean(response); - else - Object.defineProperty(this, 'duplicated', { - value: Boolean(response) - }); - } - var responseMethod = responseMethods[method]; - this.pack = packer.pack.bind(packer, this, id); - this.reply = function (error, result, transport) { - if (error instanceof Function || error && error.send instanceof Function) { - if (result != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = error; - result = null; - error = undefined; - } - else if (result instanceof Function - || result && result.send instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = result; - result = null; - } - ; - transport = unifyTransport(transport); - if (response) - clearTimeout(response.timeout); - if (from != undefined) { - if (error) - error.dest = from; - if (result) - result.dest = from; - } - ; - var message; - if (error || result != undefined) { - if (self.peerID != undefined) { - if (error) - error.from = self.peerID; - else - result.from = self.peerID; - } - if (responseMethod) { - if (responseMethod.error == undefined && error) - message = - { - error: error - }; - else { - var method = error - ? responseMethod.error - : responseMethod.response; - message = - { - method: method, - params: error || result - }; - } - } - else - message = - { - error: error, - result: result - }; - message = packer.pack(message, id); - } - else if (response) - message = response.message; - else - message = packer.pack({ result: null }, id); - storeResponse(message, id, from); - transport = transport || this.getTransport() || self.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - } - ; - inherits(RpcRequest, RpcNotification); - function cancel(message) { - var key = message2Key[message]; - if (!key) - return; - delete message2Key[message]; - var request = requests.pop(key.id, key.dest); - if (!request) - return; - clearTimeout(request.timeout); - storeProcessedResponse(key.id, key.dest); - } - ; - this.cancel = function (message) { - if (message) - return cancel(message); - for (var message in message2Key) - cancel(message); - }; - this.close = function () { - var transport = this.getTransport(); - if (transport && transport.close) - transport.close(); - this.cancel(); - processedResponses.forEach(clearTimeout); - responses.forEach(function (response) { - clearTimeout(response.timeout); - }); - }; - this.encode = function (method, params, dest, transport, callback) { - if (params instanceof Function) { - if (dest != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = params; - transport = undefined; - dest = undefined; - params = undefined; - } - else if (dest instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = dest; - transport = undefined; - dest = undefined; - } - else if (transport instanceof Function) { - if (callback != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = transport; - transport = undefined; - } - ; - if (self.peerID != undefined) { - params = params || {}; - params.from = self.peerID; - } - ; - if (dest != undefined) { - params = params || {}; - params.dest = dest; - } - ; - var message = { - method: method, - params: params - }; - if (callback) { - var id = requestID++; - var retried = 0; - message = packer.pack(message, id); - function dispatchCallback(error, result) { - self.cancel(message); - callback(error, result); - } - ; - var request = { - message: message, - callback: dispatchCallback, - responseMethods: responseMethods[method] || {} - }; - var encode_transport = unifyTransport(transport); - function sendRequest(transport) { - var rt = (method === 'ping' ? ping_request_timeout : request_timeout); - request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++)); - message2Key[message] = { id: id, dest: dest }; - requests.set(request, id, dest); - transport = transport || encode_transport || self.getTransport(); - if (transport) - return transport.send(message); - return message; - } - ; - function retry(transport) { - transport = unifyTransport(transport); - console.warn(retried + ' retry for request message:', message); - var timeout = processedResponses.pop(id, dest); - clearTimeout(timeout); - return sendRequest(transport); - } - ; - function timeout() { - if (retried < max_retries) - return retry(transport); - var error = new Error('Request has timed out'); - error.request = message; - error.retry = retry; - dispatchCallback(error); - } - ; - return sendRequest(transport); - } - ; - message = packer.pack(message); - transport = transport || this.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - this.decode = function (message, transport) { - if (!message) - throw new TypeError("Message is not defined"); - try { - message = packer.unpack(message); - } - catch (e) { - return console.debug(e, message); - } - ; - var id = message.id; - var ack = message.ack; - var method = message.method; - var params = message.params || {}; - var from = params.from; - var dest = params.dest; - if (self.peerID != undefined && from == self.peerID) - return; - if (id == undefined && ack == undefined) { - var notification = new RpcNotification(method, params); - if (self.emit('request', notification)) - return; - return notification; - } - ; - function processRequest() { - transport = unifyTransport(transport) || self.getTransport(); - if (transport) { - var response = responses.get(id, from); - if (response) - return transport.send(response.message); - } - ; - var idAck = (id != undefined) ? id : ack; - var request = new RpcRequest(method, params, idAck, from, transport); - if (self.emit('request', request)) - return; - return request; - } - ; - function processResponse(request, error, result) { - request.callback(error, result); - } - ; - function duplicatedResponse(timeout) { - console.warn("Response already processed", message); - clearTimeout(timeout); - storeProcessedResponse(ack, from); - } - ; - if (method) { - if (dest == undefined || dest == self.peerID) { - var request = requests.get(ack, from); - if (request) { - var responseMethods = request.responseMethods; - if (method == responseMethods.error) - return processResponse(request, params); - if (method == responseMethods.response) - return processResponse(request, null, params); - return processRequest(); - } - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - } - return processRequest(); - } - ; - var error = message.error; - var result = message.result; - if (error && error.dest && error.dest != self.peerID) - return; - if (result && result.dest && result.dest != self.peerID) - return; - var request = requests.get(ack, from); - if (!request) { - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - return console.warn("No callback was defined for this message", message); - } - ; - processResponse(request, error, result); - }; -} -; -inherits(RpcBuilder, EventEmitter); -RpcBuilder.RpcNotification = RpcNotification; -module.exports = RpcBuilder; -var clients = require('./clients'); -var transports = require('./clients/transports'); -RpcBuilder.clients = clients; -RpcBuilder.clients.transports = transports; -RpcBuilder.packers = packers; - -},{"./Mapper":47,"./clients":48,"./clients/transports":50,"./packers":55,"events":1,"inherits":6}],53:[function(require,module,exports){ -function pack(message, id) { - var result = { - jsonrpc: "2.0" - }; - if (message.method) { - result.method = message.method; - if (message.params) - result.params = message.params; - if (id != undefined) - result.id = id; - } - else if (id != undefined) { - if (message.error) { - if (message.result !== undefined) - throw new TypeError("Both result and error are defined"); - result.error = message.error; - } - else if (message.result !== undefined) - result.result = message.result; - else - throw new TypeError("No result or error is defined"); - result.id = id; - } - ; - return JSON.stringify(result); -} -; -function unpack(message) { - var result = message; - if (typeof message === 'string' || message instanceof String) { - result = JSON.parse(message); - } - var version = result.jsonrpc; - if (version !== '2.0') - throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); - if (result.method == undefined) { - if (result.id == undefined) - throw new TypeError("Invalid message: " + message); - var result_defined = result.result !== undefined; - var error_defined = result.error !== undefined; - if (result_defined && error_defined) - throw new TypeError("Both result and error are defined: " + message); - if (!result_defined && !error_defined) - throw new TypeError("No result or error is defined: " + message); - result.ack = result.id; - delete result.id; - } - return result; -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],54:[function(require,module,exports){ -function pack(message) { - throw new TypeError("Not yet implemented"); -} -; -function unpack(message) { - throw new TypeError("Not yet implemented"); -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],55:[function(require,module,exports){ -var JsonRPC = require('./JsonRPC'); -var XmlRPC = require('./XmlRPC'); -exports.JsonRPC = JsonRPC; -exports.XmlRPC = XmlRPC; - -},{"./JsonRPC":53,"./XmlRPC":54}],56:[function(require,module,exports){ -var freeice = require('freeice'); -var inherits = require('inherits'); -var UAParser = require('ua-parser-js'); -var uuid = require('uuid'); -var hark = require('hark'); -var EventEmitter = require('events').EventEmitter; -var recursive = require('merge').recursive.bind(undefined, true); -var sdpTranslator = require('sdp-translator'); -var logger = window.Logger || console; -var MEDIA_CONSTRAINTS = { - audio: true, - video: { - width: 640, - framerate: 15 - } -}; -var ua = (window && window.navigator) ? window.navigator.userAgent : ''; -var parser = new UAParser(ua); -var browser = parser.getBrowser(); -var usePlanB = false; -if (browser.name === 'Chrome' || browser.name === 'Chromium') { - logger.debug(browser.name + ": using SDP PlanB"); - usePlanB = true; -} -function noop(error) { - if (error) - logger.error(error); -} -function trackStop(track) { - track.stop && track.stop(); -} -function streamStop(stream) { - stream.getTracks().forEach(trackStop); -} -var dumpSDP = function (description) { - if (typeof description === 'undefined' || description === null) { - return ''; - } - return 'type: ' + description.type + '\r\n' + description.sdp; -}; -function bufferizeCandidates(pc, onerror) { - var candidatesQueue = []; - pc.addEventListener('signalingstatechange', function () { - if (this.signalingState === 'stable') { - while (candidatesQueue.length) { - var entry = candidatesQueue.shift(); - pc.addIceCandidate(entry.candidate, entry.callback, entry.callback); - } - } - }); - return function (candidate, callback) { - callback = callback || onerror; - switch (pc.signalingState) { - case 'closed': - callback(new Error('PeerConnection object is closed')); - break; - case 'stable': - if (pc.remoteDescription) { - pc.addIceCandidate(candidate, callback, callback); - } - break; - default: - candidatesQueue.push({ - candidate: candidate, - callback: callback - }); - } - }; -} -function removeFIDFromOffer(sdp) { - var n = sdp.indexOf("a=ssrc-group:FID"); - if (n > 0) { - return sdp.slice(0, n); - } - else { - return sdp; - } -} -function getSimulcastInfo(videoStream) { - var videoTracks = videoStream.getVideoTracks(); - if (!videoTracks.length) { - logger.warn('No video tracks available in the video stream'); - return ''; - } - var lines = [ - 'a=x-google-flag:conference', - 'a=ssrc-group:SIM 1 2 3', - 'a=ssrc:1 cname:localVideo', - 'a=ssrc:1 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:1 mslabel:' + videoStream.id, - 'a=ssrc:1 label:' + videoTracks[0].id, - 'a=ssrc:2 cname:localVideo', - 'a=ssrc:2 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:2 mslabel:' + videoStream.id, - 'a=ssrc:2 label:' + videoTracks[0].id, - 'a=ssrc:3 cname:localVideo', - 'a=ssrc:3 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:3 mslabel:' + videoStream.id, - 'a=ssrc:3 label:' + videoTracks[0].id - ]; - lines.push(''); - return lines.join('\n'); -} -function WebRtcPeer(mode, options, callback) { - if (!(this instanceof WebRtcPeer)) { - return new WebRtcPeer(mode, options, callback); - } - WebRtcPeer.super_.call(this); - if (options instanceof Function) { - callback = options; - options = undefined; - } - options = options || {}; - callback = (callback || noop).bind(this); - var self = this; - var localVideo = options.localVideo; - var remoteVideo = options.remoteVideo; - var videoStream = options.videoStream; - var audioStream = options.audioStream; - var mediaConstraints = options.mediaConstraints; - var connectionConstraints = options.connectionConstraints; - var pc = options.peerConnection; - var sendSource = options.sendSource || 'webcam'; - var guid = uuid.v4(); - var configuration = recursive({ - iceServers: (!!options.iceServers && options.iceServers.length > 0) ? options.iceServers : freeice() - }, options.configuration); - var onicecandidate = options.onicecandidate; - if (onicecandidate) - this.on('icecandidate', onicecandidate); - var oncandidategatheringdone = options.oncandidategatheringdone; - if (oncandidategatheringdone) { - this.on('candidategatheringdone', oncandidategatheringdone); - } - var simulcast = options.simulcast; - var multistream = options.multistream; - var interop = new sdpTranslator.Interop(); - var candidatesQueueOut = []; - var candidategatheringdone = false; - Object.defineProperties(this, { - 'peerConnection': { - get: function () { - return pc; - } - }, - 'id': { - value: options.id || guid, - writable: false - }, - 'remoteVideo': { - get: function () { - return remoteVideo; - } - }, - 'localVideo': { - get: function () { - return localVideo; - } - }, - 'currentFrame': { - get: function () { - if (!remoteVideo) - return; - if (remoteVideo.readyState < remoteVideo.HAVE_CURRENT_DATA) - throw new Error('No video stream data available'); - var canvas = document.createElement('canvas'); - canvas.width = remoteVideo.videoWidth; - canvas.height = remoteVideo.videoHeight; - canvas.getContext('2d').drawImage(remoteVideo, 0, 0); - return canvas; - } - } - }); - if (!pc) { - pc = new RTCPeerConnection(configuration); - } - pc.addEventListener('icecandidate', function (event) { - var candidate = event.candidate; - if (EventEmitter.listenerCount(self, 'icecandidate') || - EventEmitter.listenerCount(self, 'candidategatheringdone')) { - if (candidate) { - var cand; - if (multistream && usePlanB) { - cand = interop.candidateToUnifiedPlan(candidate); - } - else { - cand = candidate; - } - self.emit('icecandidate', cand); - candidategatheringdone = false; - } - else if (!candidategatheringdone) { - self.emit('candidategatheringdone'); - candidategatheringdone = true; - } - } - else if (!candidategatheringdone) { - candidatesQueueOut.push(candidate); - if (!candidate) - candidategatheringdone = true; - } - }); - pc.onaddstream = options.onaddstream; - pc.onnegotiationneeded = options.onnegotiationneeded; - this.on('newListener', function (event, listener) { - if (event === 'icecandidate' || event === 'candidategatheringdone') { - while (candidatesQueueOut.length) { - var candidate = candidatesQueueOut.shift(); - if (!candidate === (event === 'candidategatheringdone')) { - listener(candidate); - } - } - } - }); - var addIceCandidate = bufferizeCandidates(pc); - this.addIceCandidate = function (iceCandidate, callback) { - var candidate; - if (multistream && usePlanB) { - candidate = interop.candidateToPlanB(iceCandidate); - } - else { - candidate = new RTCIceCandidate(iceCandidate); - } - logger.debug('Remote ICE candidate received', iceCandidate); - callback = (callback || noop).bind(this); - addIceCandidate(candidate, callback); - }; - this.generateOffer = function (callback) { - callback = callback.bind(this); - var offerAudio = true; - var offerVideo = true; - if (mediaConstraints) { - offerAudio = (typeof mediaConstraints.audio === 'boolean') ? - mediaConstraints.audio : true; - offerVideo = (typeof mediaConstraints.video === 'boolean') ? - mediaConstraints.video : true; - } - var browserDependantConstraints = { - offerToReceiveAudio: (mode !== 'sendonly' && offerAudio), - offerToReceiveVideo: (mode !== 'sendonly' && offerVideo) - }; - var constraints = browserDependantConstraints; - logger.debug('constraints: ' + JSON.stringify(constraints)); - pc.createOffer(constraints).then(function (offer) { - logger.debug('Created SDP offer'); - offer = mangleSdpToAddSimulcast(offer); - return pc.setLocalDescription(offer); - }).then(function () { - var localDescription = pc.localDescription; - logger.debug('Local description set', localDescription.sdp); - if (multistream && usePlanB) { - localDescription = interop.toUnifiedPlan(localDescription); - logger.debug('offer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); - } - callback(null, localDescription.sdp, self.processAnswer.bind(self)); - }).catch(callback); - }; - this.getLocalSessionDescriptor = function () { - return pc.localDescription; - }; - this.getRemoteSessionDescriptor = function () { - return pc.remoteDescription; - }; - function setRemoteVideo() { - if (remoteVideo) { - remoteVideo.pause(); - var stream = pc.getRemoteStreams()[0]; - remoteVideo.srcObject = stream; - logger.debug('Remote stream:', stream); - remoteVideo.load(); - } - } - this.showLocalVideo = function () { - localVideo.srcObject = videoStream; - localVideo.muted = true; - }; - this.processAnswer = function (sdpAnswer, callback) { - callback = (callback || noop).bind(this); - var answer = new RTCSessionDescription({ - type: 'answer', - sdp: sdpAnswer - }); - if (multistream && usePlanB) { - var planBAnswer = interop.toPlanB(answer); - logger.debug('asnwer::planB', dumpSDP(planBAnswer)); - answer = planBAnswer; - } - logger.debug('SDP answer received, setting remote description'); - if (pc.signalingState === 'closed') { - return callback('PeerConnection is closed'); - } - pc.setRemoteDescription(answer, function () { - setRemoteVideo(); - callback(); - }, callback); - }; - this.processOffer = function (sdpOffer, callback) { - callback = callback.bind(this); - var offer = new RTCSessionDescription({ - type: 'offer', - sdp: sdpOffer - }); - if (multistream && usePlanB) { - var planBOffer = interop.toPlanB(offer); - logger.debug('offer::planB', dumpSDP(planBOffer)); - offer = planBOffer; - } - logger.debug('SDP offer received, setting remote description'); - if (pc.signalingState === 'closed') { - return callback('PeerConnection is closed'); - } - pc.setRemoteDescription(offer).then(function () { - return setRemoteVideo(); - }).then(function () { - return pc.createAnswer(); - }).then(function (answer) { - answer = mangleSdpToAddSimulcast(answer); - logger.debug('Created SDP answer'); - return pc.setLocalDescription(answer); - }).then(function () { - var localDescription = pc.localDescription; - if (multistream && usePlanB) { - localDescription = interop.toUnifiedPlan(localDescription); - logger.debug('answer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); - } - logger.debug('Local description set', localDescription.sdp); - callback(null, localDescription.sdp); - }).catch(callback); - }; - function mangleSdpToAddSimulcast(answer) { - if (simulcast) { - if (browser.name === 'Chrome' || browser.name === 'Chromium') { - logger.debug('Adding multicast info'); - answer = new RTCSessionDescription({ - 'type': answer.type, - 'sdp': removeFIDFromOffer(answer.sdp) + getSimulcastInfo(videoStream) - }); - } - else { - logger.warn('Simulcast is only available in Chrome browser.'); - } - } - return answer; - } - function start() { - if (pc.signalingState === 'closed') { - callback('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); - } - if (videoStream && localVideo) { - self.showLocalVideo(); - } - if (videoStream) { - pc.addStream(videoStream); - } - if (audioStream) { - pc.addStream(audioStream); - } - var browser = parser.getBrowser(); - if (mode === 'sendonly' && - (browser.name === 'Chrome' || browser.name === 'Chromium') && - browser.major === 39) { - mode = 'sendrecv'; - } - callback(); - } - if (mode !== 'recvonly' && !videoStream && !audioStream) { - function getMedia(constraints) { - if (constraints === undefined) { - constraints = MEDIA_CONSTRAINTS; - } - navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - videoStream = stream; - start(); - }).catch(callback); - } - if (sendSource === 'webcam') { - getMedia(mediaConstraints); - } - else { - getScreenConstraints(sendSource, function (error, constraints_) { - if (error) - return callback(error); - constraints = [mediaConstraints]; - constraints.unshift(constraints_); - getMedia(recursive.apply(undefined, constraints)); - }, guid); - } - } - else { - setTimeout(start, 0); - } - this.on('_dispose', function () { - if (localVideo) { - localVideo.pause(); - localVideo.srcObject = null; - localVideo.load(); - localVideo.muted = false; - } - if (remoteVideo) { - remoteVideo.pause(); - remoteVideo.srcObject = null; - remoteVideo.load(); - } - self.removeAllListeners(); - if (window.cancelChooseDesktopMedia !== undefined) { - window.cancelChooseDesktopMedia(guid); - } - }); -} -inherits(WebRtcPeer, EventEmitter); -function createEnableDescriptor(type) { - var method = 'get' + type + 'Tracks'; - return { - enumerable: true, - get: function () { - if (!this.peerConnection) - return; - var streams = this.peerConnection.getLocalStreams(); - if (!streams.length) - return; - for (var i = 0, stream; stream = streams[i]; i++) { - var tracks = stream[method](); - for (var j = 0, track; track = tracks[j]; j++) - if (!track.enabled) - return false; - } - return true; - }, - set: function (value) { - function trackSetEnable(track) { - track.enabled = value; - } - this.peerConnection.getLocalStreams().forEach(function (stream) { - stream[method]().forEach(trackSetEnable); - }); - } - }; -} -Object.defineProperties(WebRtcPeer.prototype, { - 'enabled': { - enumerable: true, - get: function () { - return this.audioEnabled && this.videoEnabled; - }, - set: function (value) { - this.audioEnabled = this.videoEnabled = value; - } - }, - 'audioEnabled': createEnableDescriptor('Audio'), - 'videoEnabled': createEnableDescriptor('Video') -}); -WebRtcPeer.prototype.getLocalStream = function (index) { - if (this.peerConnection) { - return this.peerConnection.getLocalStreams()[index || 0]; - } -}; -WebRtcPeer.prototype.getRemoteStream = function (index) { - if (this.peerConnection) { - return this.peerConnection.getRemoteStreams()[index || 0]; - } -}; -WebRtcPeer.prototype.dispose = function () { - logger.debug('Disposing WebRtcPeer'); - var pc = this.peerConnection; - try { - if (pc) { - if (pc.signalingState === 'closed') - return; - pc.getLocalStreams().forEach(streamStop); - pc.close(); - } - } - catch (err) { - logger.warn('Exception disposing webrtc peer ' + err); - } - this.emit('_dispose'); -}; -function WebRtcPeerRecvonly(options, callback) { - if (!(this instanceof WebRtcPeerRecvonly)) { - return new WebRtcPeerRecvonly(options, callback); - } - WebRtcPeerRecvonly.super_.call(this, 'recvonly', options, callback); -} -inherits(WebRtcPeerRecvonly, WebRtcPeer); -function WebRtcPeerSendonly(options, callback) { - if (!(this instanceof WebRtcPeerSendonly)) { - return new WebRtcPeerSendonly(options, callback); - } - WebRtcPeerSendonly.super_.call(this, 'sendonly', options, callback); -} -inherits(WebRtcPeerSendonly, WebRtcPeer); -function WebRtcPeerSendrecv(options, callback) { - if (!(this instanceof WebRtcPeerSendrecv)) { - return new WebRtcPeerSendrecv(options, callback); - } - WebRtcPeerSendrecv.super_.call(this, 'sendrecv', options, callback); -} -inherits(WebRtcPeerSendrecv, WebRtcPeer); -function harkUtils(stream, options) { - return hark(stream, options); -} -exports.bufferizeCandidates = bufferizeCandidates; -exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; -exports.WebRtcPeerSendonly = WebRtcPeerSendonly; -exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; -exports.hark = harkUtils; - -},{"events":1,"freeice":2,"hark":5,"inherits":6,"merge":7,"sdp-translator":15,"ua-parser-js":18,"uuid":19}],57:[function(require,module,exports){ -var WebRtcPeer = require('./WebRtcPeer'); -exports.WebRtcPeer = WebRtcPeer; - -},{"./WebRtcPeer":56}],58:[function(require,module,exports){ -window.getScreenId = function (callback) { - if (!!navigator.mozGetUserMedia) { - callback(null, 'firefox', { - video: { - mozMediaSource: 'window', - mediaSource: 'window' - } - }); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeMediaSourceId) { - if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { - callback('permission-denied'); - } - else { - callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId)); - } - window.removeEventListener('message', onIFrameCallback); - } - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); - window.removeEventListener('message', onIFrameCallback); - } - } - setTimeout(postGetSourceIdMessage, 100); -}; -function getScreenConstraints(error, sourceId) { - var screen_constraints = { - audio: false, - video: { - mandatory: { - chromeMediaSource: error ? 'screen' : 'desktop', - maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, - maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 - }, - optional: [] - } - }; - if (sourceId) { - screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; - } - return screen_constraints; -} -var iframe; -function postGetSourceIdMessage() { - if (!iframe) { - loadIFrame(postGetSourceIdMessage); - return; - } - if (!iframe.isLoaded) { - setTimeout(postGetSourceIdMessage, 100); - return; - } - iframe.contentWindow.postMessage({ - captureSourceId: true - }, '*'); -} -function loadIFrame(loadCallback) { - if (iframe) { - loadCallback(); - return; - } - iframe = document.createElement('iframe'); - iframe.onload = function () { - iframe.isLoaded = true; - loadCallback(); - }; - iframe.src = 'https://www.webrtc-experiment.com/getSourceId/'; - iframe.style.display = 'none'; - (document.body || document.documentElement).appendChild(iframe); -} -window.getChromeExtensionStatus = function (callback) { - if (!!navigator.mozGetUserMedia) { - callback('installed-enabled'); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus); - } - window.removeEventListener('message', onIFrameCallback); - } - setTimeout(postGetChromeExtensionStatusMessage, 100); -}; -function postGetChromeExtensionStatusMessage() { - if (!iframe) { - loadIFrame(postGetChromeExtensionStatusMessage); - return; - } - if (!iframe.isLoaded) { - setTimeout(postGetChromeExtensionStatusMessage, 100); - return; - } - iframe.contentWindow.postMessage({ - getChromeExtensionStatus: true - }, '*'); -} -exports.getScreenId = getScreenId; - -},{}],59:[function(require,module,exports){ -var chromeMediaSource = 'screen'; -var screenCallback; -var isFirefox = typeof window.InstallTrigger !== 'undefined'; -var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; -var isChrome = !!window.chrome && !isOpera; -window.addEventListener('message', function (event) { - if (event.origin != window.location.origin) { - return; - } - onMessageCallback(event.data); -}); -function onMessageCallback(data) { - if (data == 'PermissionDeniedError') { - chromeMediaSource = 'PermissionDeniedError'; - if (screenCallback) - return screenCallback('PermissionDeniedError'); - else - throw new Error('PermissionDeniedError'); - } - if (data == 'rtcmulticonnection-extension-loaded') { - chromeMediaSource = 'desktop'; - } - if (data.sourceId && screenCallback) { - screenCallback(sourceId = data.sourceId); - } -} -function isChromeExtensionAvailable(callback) { - if (isFirefox) - return callback(false); - if (chromeMediaSource == 'desktop') - return callback('isFirefox'); - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback('unavailable'); - } - else - callback('available'); - }, 2000); -} -function getSourceId(callback) { - if (!callback) - throw '"callback" parameter is mandatory.'; - if (sourceId) - return callback(sourceId); - screenCallback = callback; - window.postMessage('get-sourceId', '*'); -} -function getChromeExtensionStatus(extensionid, callback) { - if (isFirefox) - return callback('not-chrome'); - if (arguments.length != 2) { - callback = extensionid; - extensionid = 'ajhifddimkapgcifgcodmmfdlknahffk'; - } - var image = document.createElement('img'); - image.src = 'chrome-extension://' + extensionid + '/icon.png'; - image.onload = function () { - chromeMediaSource = 'screen'; - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback(extensionid == extensionid ? 'installed-enabled' : 'installed-disabled'); - } - else - callback('installed-enabled'); - }, 2000); - }; - image.onerror = function () { - callback('not-installed'); - }; -} -function getScreenConstraints(callback) { - sourceId = ''; - var firefoxScreenConstraints = { - mozMediaSource: 'window', - mediaSource: 'window' - }; - if (isFirefox) - return callback(null, firefoxScreenConstraints); - var screen_constraints = { - mandatory: { - chromeMediaSource: chromeMediaSource, - maxWidth: screen.width > 1920 ? screen.width : 1920, - maxHeight: screen.height > 1080 ? screen.height : 1080 - }, - optional: [] - }; - if (chromeMediaSource == 'desktop' && !sourceId) { - getSourceId(function () { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); - }); - return; - } - if (chromeMediaSource == 'desktop') { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - } - callback(null, screen_constraints); -} -exports.getScreenConstraints = getScreenConstraints; -exports.isChromeExtensionAvailable = isChromeExtensionAvailable; -exports.getChromeExtensionStatus = getChromeExtensionStatus; -exports.getSourceId = getSourceId; - -},{}],60:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var platform = require("platform"); -var WebRtcStats = (function () { - function WebRtcStats(stream) { - this.stream = stream; - this.webRtcStatsEnabled = false; - this.statsInterval = 1; - this.stats = { - inbound: { - audio: { - bytesReceived: 0, - packetsReceived: 0, - packetsLost: 0 - }, - video: { - bytesReceived: 0, - packetsReceived: 0, - packetsLost: 0, - framesDecoded: 0, - nackCount: 0 - } - }, - outbound: { - audio: { - bytesSent: 0, - packetsSent: 0, - }, - video: { - bytesSent: 0, - packetsSent: 0, - framesEncoded: 0, - nackCount: 0 - } - } - }; - } - WebRtcStats.prototype.isEnabled = function () { - return this.webRtcStatsEnabled; - }; - WebRtcStats.prototype.initWebRtcStats = function () { - var _this = this; - var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); - if (elastestInstrumentation) { - console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - this.webRtcStatsEnabled = true; - var instrumentation_1 = JSON.parse(elastestInstrumentation); - this.statsInterval = instrumentation_1.webrtc.interval; - console.warn('localStorage item: ' + JSON.stringify(instrumentation_1)); - this.webRtcStatsIntervalId = setInterval(function () { - _this.sendStatsToHttpEndpoint(instrumentation_1); - }, this.statsInterval * 1000); - return; - } - console.debug('WebRtc stats not enabled'); - }; - WebRtcStats.prototype.stopWebRtcStats = function () { - if (this.webRtcStatsEnabled) { - clearInterval(this.webRtcStatsIntervalId); - console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - } - }; - WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { - var _this = this; - var sendPost = function (json) { - var http = new XMLHttpRequest(); - var url = instrumentation.webrtc.httpEndpoint; - http.open('POST', url, true); - http.setRequestHeader('Content-type', 'application/json'); - http.onreadystatechange = function () { - if (http.readyState === 4 && http.status === 200) { - console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId); - } - }; - http.send(json); - }; - var f = function (stats) { - if (platform.name.indexOf('Firefox') !== -1) { - stats.forEach(function (stat) { - var json = {}; - if ((stat.type === 'inbound-rtp') && - (stat.nackCount !== null && - stat.isRemote === false && - stat.id.startsWith('inbound') && - stat.remoteId.startsWith('inbound'))) { - var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; - var jit = stat.jitter * 1000; - var metrics = { - bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, - jitter: jit, - packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, - packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval - }; - var units = { - bytesReceived: 'bytes', - jitter: 'ms', - packetsReceived: 'packets', - packetsLost: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; - metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; - units['framesDecoded'] = 'frames'; - units['nackCount'] = 'packets'; - _this.stats.inbound.video.framesDecoded = stat.framesDecoded; - _this.stats.inbound.video.nackCount = stat.nackCount; - } - _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; - _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; - _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - else if ((stat.type === 'outbound-rtp') && - (stat.isRemote === false && - stat.id.toLowerCase().includes('outbound'))) { - var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, - packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval - }; - var units = { - bytesSent: 'bytes', - packetsSent: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; - units['framesEncoded'] = 'frames'; - _this.stats.outbound.video.framesEncoded = stat.framesEncoded; - } - _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; - _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - }); - } - else if (platform.name.indexOf('Chrome') !== -1) { - for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { - var key = _a[_i]; - var stat = stats[key]; - if (stat.type === 'ssrc') { - var json = {}; - if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || - (stat.mediaType === 'video' && 'qpSum' in stat))) { - var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, - jitter: stat.googJitterBufferMs, - packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, - packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval - }; - var units = { - bytesReceived: 'bytes', - jitter: 'ms', - packetsReceived: 'packets', - packetsLost: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; - metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; - units['framesDecoded'] = 'frames'; - units['nackCount'] = 'packets'; - _this.stats.inbound.video.framesDecoded = stat.framesDecoded; - _this.stats.inbound.video.nackCount = stat.googNacksSent; - } - _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; - _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; - _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - else if ('bytesSent' in stat) { - var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, - packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval - }; - var units = { - bytesSent: 'bytes', - packetsSent: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; - units['framesEncoded'] = 'frames'; - _this.stats.outbound.video.framesEncoded = stat.framesEncoded; - } - _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; - _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - } - } - } - }; - this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); }); - }; - WebRtcStats.prototype.standardizeReport = function (response) { - if (platform.name.indexOf('Firefox') !== -1) { - return response; - } - var standardReport = {}; - response.result().forEach(function (report) { - var standardStats = { - id: report.id, - timestamp: report.timestamp, - type: report.type - }; - report.names().forEach(function (name) { - standardStats[name] = report.stat(name); - }); - standardReport[standardStats.id] = standardStats; - }); - return standardReport; - }; - WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) { - var _this = this; - if (platform.name.indexOf('Firefox') !== -1) { - return pc.getStats(null, function (response) { - var report = _this.standardizeReport(response); - successCb(report); - }, failureCb); - } - else if (platform.name.indexOf('Chrome') !== -1) { - return pc.getStats(function (response) { - var report = _this.standardizeReport(response); - successCb(report); - }, null, failureCb); - } - }; - return WebRtcStats; -}()); -exports.WebRtcStats = WebRtcStats; - -},{"platform":9}]},{},[26]) -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL21lcmdlL21lcmdlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi9ncmFtbWFyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL3BhcnNlci5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi93cml0ZXIuanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2FycmF5LWVxdWFscy5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNsYXRvci9saWIvaW5kZXguanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2ludGVyb3AuanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL3RyYW5zZm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91YS1wYXJzZXItanMvc3JjL3VhLXBhcnNlci5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9NYXBwZXIuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvSnNvblJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL1htbFJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcy9XZWJSdGNQZWVyLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8uanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2prQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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IjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qIVxyXG4gKiBAbmFtZSBKYXZhU2NyaXB0L05vZGVKUyBNZXJnZSB2MS4yLjBcclxuICogQGF1dGhvciB5ZWlrb3NcclxuICogQHJlcG9zaXRvcnkgaHR0cHM6Ly9naXRodWIuY29tL3llaWtvcy9qcy5tZXJnZVxyXG5cclxuICogQ29weXJpZ2h0IDIwMTQgeWVpa29zIC0gTUlUIGxpY2Vuc2VcclxuICogaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS95ZWlrb3MvanMubWVyZ2UvbWFzdGVyL0xJQ0VOU0VcclxuICovXHJcblxyXG47KGZ1bmN0aW9uKGlzTm9kZSkge1xyXG5cclxuXHQvKipcclxuXHQgKiBNZXJnZSBvbmUgb3IgbW9yZSBvYmplY3RzIFxyXG5cdCAqIEBwYXJhbSBib29sPyBjbG9uZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCwuLi4gYXJndW1lbnRzXHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0dmFyIFB1YmxpYyA9IGZ1bmN0aW9uKGNsb25lKSB7XHJcblxyXG5cdFx0cmV0dXJuIG1lcmdlKGNsb25lID09PSB0cnVlLCBmYWxzZSwgYXJndW1lbnRzKTtcclxuXHJcblx0fSwgcHVibGljTmFtZSA9ICdtZXJnZSc7XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvciBtb3JlIG9iamVjdHMgcmVjdXJzaXZlbHkgXHJcblx0ICogQHBhcmFtIGJvb2w/IGNsb25lXHJcblx0ICogQHBhcmFtIG1peGVkLC4uLiBhcmd1bWVudHNcclxuXHQgKiBAcmV0dXJuIG9iamVjdFxyXG5cdCAqL1xyXG5cclxuXHRQdWJsaWMucmVjdXJzaXZlID0gZnVuY3Rpb24oY2xvbmUpIHtcclxuXHJcblx0XHRyZXR1cm4gbWVyZ2UoY2xvbmUgPT09IHRydWUsIHRydWUsIGFyZ3VtZW50cyk7XHJcblxyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIENsb25lIHRoZSBpbnB1dCByZW1vdmluZyBhbnkgcmVmZXJlbmNlXHJcblx0ICogQHBhcmFtIG1peGVkIGlucHV0XHJcblx0ICogQHJldHVybiBtaXhlZFxyXG5cdCAqL1xyXG5cclxuXHRQdWJsaWMuY2xvbmUgPSBmdW5jdGlvbihpbnB1dCkge1xyXG5cclxuXHRcdHZhciBvdXRwdXQgPSBpbnB1dCxcclxuXHRcdFx0dHlwZSA9IHR5cGVPZihpbnB1dCksXHJcblx0XHRcdGluZGV4LCBzaXplO1xyXG5cclxuXHRcdGlmICh0eXBlID09PSAnYXJyYXknKSB7XHJcblxyXG5cdFx0XHRvdXRwdXQgPSBbXTtcclxuXHRcdFx0c2l6ZSA9IGlucHV0Lmxlbmd0aDtcclxuXHJcblx0XHRcdGZvciAoaW5kZXg9MDtpbmRleDxzaXplOysraW5kZXgpXHJcblxyXG5cdFx0XHRcdG91dHB1dFtpbmRleF0gPSBQdWJsaWMuY2xvbmUoaW5wdXRbaW5kZXhdKTtcclxuXHJcblx0XHR9IGVsc2UgaWYgKHR5cGUgPT09ICdvYmplY3QnKSB7XHJcblxyXG5cdFx0XHRvdXRwdXQgPSB7fTtcclxuXHJcblx0XHRcdGZvciAoaW5kZXggaW4gaW5wdXQpXHJcblxyXG5cdFx0XHRcdG91dHB1dFtpbmRleF0gPSBQdWJsaWMuY2xvbmUoaW5wdXRbaW5kZXhdKTtcclxuXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIG91dHB1dDtcclxuXHJcblx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogTWVyZ2UgdHdvIG9iamVjdHMgcmVjdXJzaXZlbHlcclxuXHQgKiBAcGFyYW0gbWl4ZWQgaW5wdXRcclxuXHQgKiBAcGFyYW0gbWl4ZWQgZXh0ZW5kXHJcblx0ICogQHJldHVybiBtaXhlZFxyXG5cdCAqL1xyXG5cclxuXHRmdW5jdGlvbiBtZXJnZV9yZWN1cnNpdmUoYmFzZSwgZXh0ZW5kKSB7XHJcblxyXG5cdFx0aWYgKHR5cGVPZihiYXNlKSAhPT0gJ29iamVjdCcpXHJcblxyXG5cdFx0XHRyZXR1cm4gZXh0ZW5kO1xyXG5cclxuXHRcdGZvciAodmFyIGtleSBpbiBleHRlbmQpIHtcclxuXHJcblx0XHRcdGlmICh0eXBlT2YoYmFzZVtrZXldKSA9PT0gJ29iamVjdCcgJiYgdHlwZU9mKGV4dGVuZFtrZXldKSA9PT0gJ29iamVjdCcpIHtcclxuXHJcblx0XHRcdFx0YmFzZVtrZXldID0gbWVyZ2VfcmVjdXJzaXZlKGJhc2Vba2V5XSwgZXh0ZW5kW2tleV0pO1xyXG5cclxuXHRcdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdFx0YmFzZVtrZXldID0gZXh0ZW5kW2tleV07XHJcblxyXG5cdFx0XHR9XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBiYXNlO1xyXG5cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvciBtb3JlIG9iamVjdHNcclxuXHQgKiBAcGFyYW0gYm9vbCBjbG9uZVxyXG5cdCAqIEBwYXJhbSBib29sIHJlY3Vyc2l2ZVxyXG5cdCAqIEBwYXJhbSBhcnJheSBhcmd2XHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0ZnVuY3Rpb24gbWVyZ2UoY2xvbmUsIHJlY3Vyc2l2ZSwgYXJndikge1xyXG5cclxuXHRcdHZhciByZXN1bHQgPSBhcmd2WzBdLFxyXG5cdFx0XHRzaXplID0gYXJndi5sZW5ndGg7XHJcblxyXG5cdFx0aWYgKGNsb25lIHx8IHR5cGVPZihyZXN1bHQpICE9PSAnb2JqZWN0JylcclxuXHJcblx0XHRcdHJlc3VsdCA9IHt9O1xyXG5cclxuXHRcdGZvciAodmFyIGluZGV4PTA7aW5kZXg8c2l6ZTsrK2luZGV4KSB7XHJcblxyXG5cdFx0XHR2YXIgaXRlbSA9IGFyZ3ZbaW5kZXhdLFxyXG5cclxuXHRcdFx0XHR0eXBlID0gdHlwZU9mKGl0ZW0pO1xyXG5cclxuXHRcdFx0aWYgKHR5cGUgIT09ICdvYmplY3QnKSBjb250aW51ZTtcclxuXHJcblx0XHRcdGZvciAodmFyIGtleSBpbiBpdGVtKSB7XHJcblxyXG5cdFx0XHRcdHZhciBzaXRlbSA9IGNsb25lID8gUHVibGljLmNsb25lKGl0ZW1ba2V5XSkgOiBpdGVtW2tleV07XHJcblxyXG5cdFx0XHRcdGlmIChyZWN1cnNpdmUpIHtcclxuXHJcblx0XHRcdFx0XHRyZXN1bHRba2V5XSA9IG1lcmdlX3JlY3Vyc2l2ZShyZXN1bHRba2V5XSwgc2l0ZW0pO1xyXG5cclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cclxuXHRcdFx0XHRcdHJlc3VsdFtrZXldID0gc2l0ZW07XHJcblxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdH1cclxuXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHJlc3VsdDtcclxuXHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgdHlwZSBvZiB2YXJpYWJsZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCBpbnB1dFxyXG5cdCAqIEByZXR1cm4gc3RyaW5nXHJcblx0ICpcclxuXHQgKiBAc2VlIGh0dHA6Ly9qc3BlcmYuY29tL3R5cGVvZnZhclxyXG5cdCAqL1xyXG5cclxuXHRmdW5jdGlvbiB0eXBlT2YoaW5wdXQpIHtcclxuXHJcblx0XHRyZXR1cm4gKHt9KS50b1N0cmluZy5jYWxsKGlucHV0KS5zbGljZSg4LCAtMSkudG9Mb3dlckNhc2UoKTtcclxuXHJcblx0fVxyXG5cclxuXHRpZiAoaXNOb2RlKSB7XHJcblxyXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBQdWJsaWM7XHJcblxyXG5cdH0gZWxzZSB7XHJcblxyXG5cdFx0d2luZG93W3B1YmxpY05hbWVdID0gUHVibGljO1xyXG5cclxuXHR9XHJcblxyXG59KSh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyk7IiwiLyoqXG4gICMgbm9ybWFsaWNlXG5cbiAgTm9ybWFsaXplIGFuIGljZSBzZXJ2ZXIgY29uZmlndXJhdGlvbiBvYmplY3QgKG9yIHBsYWluIG9sZCBzdHJpbmcpIGludG8gYSBmb3JtYXRcbiAgdGhhdCBpcyB1c2FibGUgaW4gYWxsIGJyb3dzZXJzIHN1cHBvcnRpbmcgV2ViUlRDLiAgUHJpbWFyaWx5IHRoaXMgbW9kdWxlIGlzIGRlc2lnbmVkXG4gIHRvIGhlbHAgd2l0aCB0aGUgdHJhbnNpdGlvbiBvZiB0aGUgYHVybGAgYXR0cmlidXRlIG9mIHRoZSBjb25maWd1cmF0aW9uIG9iamVjdCB0b1xuICB0aGUgYHVybHNgIGF0dHJpYnV0ZS5cblxuICAjIyBFeGFtcGxlIFVzYWdlXG5cbiAgPDw8IGV4YW1wbGVzL3NpbXBsZS5qc1xuXG4qKi9cblxudmFyIHByb3RvY29scyA9IFtcbiAgJ3N0dW46JyxcbiAgJ3R1cm46J1xuXTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpbnB1dCkge1xuICB2YXIgdXJsID0gKGlucHV0IHx8IHt9KS51cmwgfHwgaW5wdXQ7XG4gIHZhciBwcm90b2NvbDtcbiAgdmFyIHBhcnRzO1xuICB2YXIgb3V0cHV0ID0ge307XG5cbiAgLy8gaWYgd2UgZG9uJ3QgaGF2ZSBhIHN0cmluZyB1cmwsIHRoZW4gYWxsb3cgdGhlIGlucHV0IHRvIHBhc3N0aHJvdWdoXG4gIGlmICh0eXBlb2YgdXJsICE9ICdzdHJpbmcnICYmICghICh1cmwgaW5zdGFuY2VvZiBTdHJpbmcpKSkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIC8vIHRyaW0gdGhlIHVybCBzdHJpbmcsIGFuZCBjb252ZXJ0IHRvIGFuIGFycmF5XG4gIHVybCA9IHVybC50cmltKCk7XG5cbiAgLy8gaWYgdGhlIHByb3RvY29sIGlzIG5vdCBrbm93biwgdGhlbiBwYXNzdGhyb3VnaFxuICBwcm90b2NvbCA9IHByb3RvY29sc1twcm90b2NvbHMuaW5kZXhPZih1cmwuc2xpY2UoMCwgNSkpXTtcbiAgaWYgKCEgcHJvdG9jb2wpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyBub3cgbGV0J3MgYXR0YWNrIHRoZSByZW1haW5pbmcgdXJsIHBhcnRzXG4gIHVybCA9IHVybC5zbGljZSg1KTtcbiAgcGFydHMgPSB1cmwuc3BsaXQoJ0AnKTtcblxuICBvdXRwdXQudXNlcm5hbWUgPSBpbnB1dC51c2VybmFtZTtcbiAgb3V0cHV0LmNyZWRlbnRpYWwgPSBpbnB1dC5jcmVkZW50aWFsO1xuICAvLyBpZiB3ZSBoYXZlIGFuIGF1dGhlbnRpY2F0aW9uIHBhcnQsIHRoZW4gc2V0IHRoZSBjcmVkZW50aWFsc1xuICBpZiAocGFydHMubGVuZ3RoID4gMSkge1xuICAgIHVybCA9IHBhcnRzWzFdO1xuICAgIHBhcnRzID0gcGFydHNbMF0uc3BsaXQoJzonKTtcblxuICAgIC8vIGFkZCB0aGUgb3V0cHV0IGNyZWRlbnRpYWwgYW5kIHVzZXJuYW1lXG4gICAgb3V0cHV0LnVzZXJuYW1lID0gcGFydHNbMF07XG4gICAgb3V0cHV0LmNyZWRlbnRpYWwgPSAoaW5wdXQgfHwge30pLmNyZWRlbnRpYWwgfHwgcGFydHNbMV0gfHwgJyc7XG4gIH1cblxuICBvdXRwdXQudXJsID0gcHJvdG9jb2wgKyB1cmw7XG4gIG91dHB1dC51cmxzID0gWyBvdXRwdXQudXJsIF07XG5cbiAgcmV0dXJuIG91dHB1dDtcbn07XG4iLCIvKiFcbiAqIFBsYXRmb3JtLmpzIDxodHRwczovL210aHMuYmUvcGxhdGZvcm0+XG4gKiBDb3B5cmlnaHQgMjAxNC0yMDE4IEJlbmphbWluIFRhbiA8aHR0cHM6Ly9ibmptbnQ0bi5ub3cuc2gvPlxuICogQ29weXJpZ2h0IDIwMTEtMjAxMyBKb2huLURhdmlkIERhbHRvbiA8aHR0cDovL2FsbHlvdWNhbmxlZXQuY29tLz5cbiAqIEF2YWlsYWJsZSB1bmRlciBNSVQgbGljZW5zZSA8aHR0cHM6Ly9tdGhzLmJlL21pdD5cbiAqL1xuOyhmdW5jdGlvbigpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVybWluZSBpZiB2YWx1ZXMgYXJlIG9mIHRoZSBsYW5ndWFnZSB0eXBlIGBPYmplY3RgLiAqL1xuICB2YXIgb2JqZWN0VHlwZXMgPSB7XG4gICAgJ2Z1bmN0aW9uJzogdHJ1ZSxcbiAgICAnb2JqZWN0JzogdHJ1ZVxuICB9O1xuXG4gIC8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgcm9vdCA9IChvYmplY3RUeXBlc1t0eXBlb2Ygd2luZG93XSAmJiB3aW5kb3cpIHx8IHRoaXM7XG5cbiAgLyoqIEJhY2t1cCBwb3NzaWJsZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgb2xkUm9vdCA9IHJvb3Q7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBleHBvcnRzYC4gKi9cbiAgdmFyIGZyZWVFeHBvcnRzID0gb2JqZWN0VHlwZXNbdHlwZW9mIGV4cG9ydHNdICYmIGV4cG9ydHM7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBtb2R1bGVgLiAqL1xuICB2YXIgZnJlZU1vZHVsZSA9IG9iamVjdFR5cGVzW3R5cGVvZiBtb2R1bGVdICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzIG9yIEJyb3dzZXJpZmllZCBjb2RlIGFuZCB1c2UgaXQgYXMgYHJvb3RgLiAqL1xuICB2YXIgZnJlZUdsb2JhbCA9IGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUgJiYgdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWw7XG4gIGlmIChmcmVlR2xvYmFsICYmIChmcmVlR2xvYmFsLmdsb2JhbCA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLndpbmRvdyA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLnNlbGYgPT09IGZyZWVHbG9iYWwpKSB7XG4gICAgcm9vdCA9IGZyZWVHbG9iYWw7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBhcyB0aGUgbWF4aW11bSBsZW5ndGggb2YgYW4gYXJyYXktbGlrZSBvYmplY3QuXG4gICAqIFNlZSB0aGUgW0VTNiBzcGVjXShodHRwOi8vcGVvcGxlLm1vemlsbGEub3JnL35qb3JlbmRvcmZmL2VzNi1kcmFmdC5odG1sI3NlYy10b2xlbmd0aClcbiAgICogZm9yIG1vcmUgZGV0YWlscy5cbiAgICovXG4gIHZhciBtYXhTYWZlSW50ZWdlciA9IE1hdGgucG93KDIsIDUzKSAtIDE7XG5cbiAgLyoqIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBkZXRlY3QgT3BlcmEuICovXG4gIHZhciByZU9wZXJhID0gL1xcYk9wZXJhLztcblxuICAvKiogUG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHRoaXNCaW5kaW5nID0gdGhpcztcblxuICAvKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xuICB2YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4gIC8qKiBVc2VkIHRvIGNoZWNrIGZvciBvd24gcHJvcGVydGllcyBvZiBhbiBvYmplY3QuICovXG4gIHZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4gIC8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIHZhbHVlcy4gKi9cbiAgdmFyIHRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENhcGl0YWxpemVzIGEgc3RyaW5nIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGNhcGl0YWxpemVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gU3RyaW5nKHN0cmluZyk7XG4gICAgcmV0dXJuIHN0cmluZy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0cmluZy5zbGljZSgxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHV0aWxpdHkgZnVuY3Rpb24gdG8gY2xlYW4gdXAgdGhlIE9TIG5hbWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcyBUaGUgT1MgbmFtZSB0byBjbGVhbiB1cC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwYXR0ZXJuXSBBIGBSZWdFeHBgIHBhdHRlcm4gbWF0Y2hpbmcgdGhlIE9TIG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbGFiZWxdIEEgbGFiZWwgZm9yIHRoZSBPUy5cbiAgICovXG4gIGZ1bmN0aW9uIGNsZWFudXBPUyhvcywgcGF0dGVybiwgbGFiZWwpIHtcbiAgICAvLyBQbGF0Zm9ybSB0b2tlbnMgYXJlIGRlZmluZWQgYXQ6XG4gICAgLy8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgLy8gaHR0cDovL3dlYi5hcmNoaXZlLm9yZy93ZWIvMjAwODExMjIwNTM5NTAvaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgdmFyIGRhdGEgPSB7XG4gICAgICAnMTAuMCc6ICcxMCcsXG4gICAgICAnNi40JzogICcxMCBUZWNobmljYWwgUHJldmlldycsXG4gICAgICAnNi4zJzogICc4LjEnLFxuICAgICAgJzYuMic6ICAnOCcsXG4gICAgICAnNi4xJzogICdTZXJ2ZXIgMjAwOCBSMiAvIDcnLFxuICAgICAgJzYuMCc6ICAnU2VydmVyIDIwMDggLyBWaXN0YScsXG4gICAgICAnNS4yJzogICdTZXJ2ZXIgMjAwMyAvIFhQIDY0LWJpdCcsXG4gICAgICAnNS4xJzogICdYUCcsXG4gICAgICAnNS4wMSc6ICcyMDAwIFNQMScsXG4gICAgICAnNS4wJzogICcyMDAwJyxcbiAgICAgICc0LjAnOiAgJ05UJyxcbiAgICAgICc0LjkwJzogJ01FJ1xuICAgIH07XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgdmVyc2lvbiBmcm9tIHBsYXRmb3JtIHRva2Vucy5cbiAgICBpZiAocGF0dGVybiAmJiBsYWJlbCAmJiAvXldpbi9pLnRlc3Qob3MpICYmICEvXldpbmRvd3MgUGhvbmUgL2kudGVzdChvcykgJiZcbiAgICAgICAgKGRhdGEgPSBkYXRhWy9bXFxkLl0rJC8uZXhlYyhvcyldKSkge1xuICAgICAgb3MgPSAnV2luZG93cyAnICsgZGF0YTtcbiAgICB9XG4gICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgb3MgPSBTdHJpbmcob3MpO1xuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwpIHtcbiAgICAgIG9zID0gb3MucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgbGFiZWwpO1xuICAgIH1cblxuICAgIG9zID0gZm9ybWF0KFxuICAgICAgb3MucmVwbGFjZSgvIGNlJC9pLCAnIENFJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYmhwdy9pLCAnd2ViJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hY2ludG9zaFxcYi8sICdNYWMgT1MnKVxuICAgICAgICAucmVwbGFjZSgvX1Bvd2VyUENcXGIvaSwgJyBPUycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoT1MgWCkgW14gXFxkXSsvaSwgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hYyAoT1MgWClcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFwvKFxcZCkvLCAnICQxJylcbiAgICAgICAgLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICAucmVwbGFjZSgvKD86IEJlUEN8WyAuXSpmY1sgXFxkLl0rKSQvaSwgJycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJ4ODZcXC42NFxcYi9naSwgJ3g4Nl82NCcpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoV2luZG93cyBQaG9uZSkgT1NcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKENocm9tZSBPUyBcXHcrKSBbXFxkLl0rXFxiLywgJyQxJylcbiAgICAgICAgLnNwbGl0KCcgb24gJylbMF1cbiAgICApO1xuXG4gICAgcmV0dXJuIG9zO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGl0ZXJhdGlvbiB1dGlsaXR5IGZvciBhcnJheXMgYW5kIG9iamVjdHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIGVhY2gob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBvYmplY3QgPyBvYmplY3QubGVuZ3RoIDogMDtcblxuICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInICYmIGxlbmd0aCA+IC0xICYmIGxlbmd0aCA8PSBtYXhTYWZlSW50ZWdlcikge1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2luZGV4XSwgaW5kZXgsIG9iamVjdCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvck93bihvYmplY3QsIGNhbGxiYWNrKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJpbSBhbmQgY29uZGl0aW9uYWxseSBjYXBpdGFsaXplIHN0cmluZyB2YWx1ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBmb3JtYXQuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBmb3JtYXR0ZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gZm9ybWF0KHN0cmluZykge1xuICAgIHN0cmluZyA9IHRyaW0oc3RyaW5nKTtcbiAgICByZXR1cm4gL14oPzp3ZWJPU3xpKD86T1N8UCkpLy50ZXN0KHN0cmluZylcbiAgICAgID8gc3RyaW5nXG4gICAgICA6IGNhcGl0YWxpemUoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJdGVyYXRlcyBvdmVyIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzLCBleGVjdXRpbmcgdGhlIGBjYWxsYmFja2AgZm9yIGVhY2guXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBleGVjdXRlZCBwZXIgb3duIHByb3BlcnR5LlxuICAgKi9cbiAgZnVuY3Rpb24gZm9yT3duKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2tleV0sIGtleSwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgaW50ZXJuYWwgYFtbQ2xhc3NdXWAgb2YgYSB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBgW1tDbGFzc11dYC5cbiAgICovXG4gIGZ1bmN0aW9uIGdldENsYXNzT2YodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPT0gbnVsbFxuICAgICAgPyBjYXBpdGFsaXplKHZhbHVlKVxuICAgICAgOiB0b1N0cmluZy5jYWxsKHZhbHVlKS5zbGljZSg4LCAtMSk7XG4gIH1cblxuICAvKipcbiAgICogSG9zdCBvYmplY3RzIGNhbiByZXR1cm4gdHlwZSB2YWx1ZXMgdGhhdCBhcmUgZGlmZmVyZW50IGZyb20gdGhlaXIgYWN0dWFsXG4gICAqIGRhdGEgdHlwZS4gVGhlIG9iamVjdHMgd2UgYXJlIGNvbmNlcm5lZCB3aXRoIHVzdWFsbHkgcmV0dXJuIG5vbi1wcmltaXRpdmVcbiAgICogdHlwZXMgb2YgXCJvYmplY3RcIiwgXCJmdW5jdGlvblwiLCBvciBcInVua25vd25cIi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSBvYmplY3QgVGhlIG93bmVyIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3BlcnR5IFRoZSBwcm9wZXJ0eSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyBhIG5vbi1wcmltaXRpdmUsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGlzSG9zdFR5cGUob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgIHZhciB0eXBlID0gb2JqZWN0ICE9IG51bGwgPyB0eXBlb2Ygb2JqZWN0W3Byb3BlcnR5XSA6ICdudW1iZXInO1xuICAgIHJldHVybiAhL14oPzpib29sZWFufG51bWJlcnxzdHJpbmd8dW5kZWZpbmVkKSQvLnRlc3QodHlwZSkgJiZcbiAgICAgICh0eXBlID09ICdvYmplY3QnID8gISFvYmplY3RbcHJvcGVydHldIDogdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUHJlcGFyZXMgYSBzdHJpbmcgZm9yIHVzZSBpbiBhIGBSZWdFeHBgIGJ5IG1ha2luZyBoeXBoZW5zIGFuZCBzcGFjZXMgb3B0aW9uYWwuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBxdWFsaWZ5LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgcXVhbGlmaWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIHF1YWxpZnkoc3RyaW5nKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoLyhbIC1dKSg/ISQpL2csICckMT8nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGJhcmUtYm9uZXMgYEFycmF5I3JlZHVjZWAgbGlrZSB1dGlsaXR5IGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHsqfSBUaGUgYWNjdW11bGF0ZWQgcmVzdWx0LlxuICAgKi9cbiAgZnVuY3Rpb24gcmVkdWNlKGFycmF5LCBjYWxsYmFjaykge1xuICAgIHZhciBhY2N1bXVsYXRvciA9IG51bGw7XG4gICAgZWFjaChhcnJheSwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICBhY2N1bXVsYXRvciA9IGNhbGxiYWNrKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGFycmF5KTtcbiAgICB9KTtcbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIGZyb20gYSBzdHJpbmcuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byB0cmltLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgdHJpbW1lZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiB0cmltKHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC9eICt8ICskL2csICcnKTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IHBsYXRmb3JtIG9iamVjdC5cbiAgICpcbiAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAqIEBwYXJhbSB7T2JqZWN0fHN0cmluZ30gW3VhPW5hdmlnYXRvci51c2VyQWdlbnRdIFRoZSB1c2VyIGFnZW50IHN0cmluZyBvclxuICAgKiAgY29udGV4dCBvYmplY3QuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IEEgcGxhdGZvcm0gb2JqZWN0LlxuICAgKi9cbiAgZnVuY3Rpb24gcGFyc2UodWEpIHtcblxuICAgIC8qKiBUaGUgZW52aXJvbm1lbnQgY29udGV4dCBvYmplY3QuICovXG4gICAgdmFyIGNvbnRleHQgPSByb290O1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGEgY3VzdG9tIGNvbnRleHQgaXMgcHJvdmlkZWQuICovXG4gICAgdmFyIGlzQ3VzdG9tQ29udGV4dCA9IHVhICYmIHR5cGVvZiB1YSA9PSAnb2JqZWN0JyAmJiBnZXRDbGFzc09mKHVhKSAhPSAnU3RyaW5nJztcblxuICAgIC8vIEp1Z2dsZSBhcmd1bWVudHMuXG4gICAgaWYgKGlzQ3VzdG9tQ29udGV4dCkge1xuICAgICAgY29udGV4dCA9IHVhO1xuICAgICAgdWEgPSBudWxsO1xuICAgIH1cblxuICAgIC8qKiBCcm93c2VyIG5hdmlnYXRvciBvYmplY3QuICovXG4gICAgdmFyIG5hdiA9IGNvbnRleHQubmF2aWdhdG9yIHx8IHt9O1xuXG4gICAgLyoqIEJyb3dzZXIgdXNlciBhZ2VudCBzdHJpbmcuICovXG4gICAgdmFyIHVzZXJBZ2VudCA9IG5hdi51c2VyQWdlbnQgfHwgJyc7XG5cbiAgICB1YSB8fCAodWEgPSB1c2VyQWdlbnQpO1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGB0aGlzQmluZGluZ2AgaXMgdGhlIFtNb2R1bGVTY29wZV0uICovXG4gICAgdmFyIGlzTW9kdWxlU2NvcGUgPSBpc0N1c3RvbUNvbnRleHQgfHwgdGhpc0JpbmRpbmcgPT0gb2xkUm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGRldGVjdCBpZiBicm93c2VyIGlzIGxpa2UgQ2hyb21lLiAqL1xuICAgIHZhciBsaWtlQ2hyb21lID0gaXNDdXN0b21Db250ZXh0XG4gICAgICA/ICEhbmF2Lmxpa2VDaHJvbWVcbiAgICAgIDogL1xcYkNocm9tZVxcYi8udGVzdCh1YSkgJiYgIS9pbnRlcm5hbHxcXG4vaS50ZXN0KHRvU3RyaW5nLnRvU3RyaW5nKCkpO1xuXG4gICAgLyoqIEludGVybmFsIGBbW0NsYXNzXV1gIHZhbHVlIHNob3J0Y3V0cy4gKi9cbiAgICB2YXIgb2JqZWN0Q2xhc3MgPSAnT2JqZWN0JyxcbiAgICAgICAgYWlyUnVudGltZUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnU2NyaXB0QnJpZGdpbmdQcm94eU9iamVjdCcsXG4gICAgICAgIGVudmlyb0NsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnRW52aXJvbm1lbnQnLFxuICAgICAgICBqYXZhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIGNvbnRleHQuamF2YSkgPyAnSmF2YVBhY2thZ2UnIDogZ2V0Q2xhc3NPZihjb250ZXh0LmphdmEpLFxuICAgICAgICBwaGFudG9tQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdSdW50aW1lT2JqZWN0JztcblxuICAgIC8qKiBEZXRlY3QgSmF2YSBlbnZpcm9ubWVudHMuICovXG4gICAgdmFyIGphdmEgPSAvXFxiSmF2YS8udGVzdChqYXZhQ2xhc3MpICYmIGNvbnRleHQuamF2YTtcblxuICAgIC8qKiBEZXRlY3QgUmhpbm8uICovXG4gICAgdmFyIHJoaW5vID0gamF2YSAmJiBnZXRDbGFzc09mKGNvbnRleHQuZW52aXJvbm1lbnQpID09IGVudmlyb0NsYXNzO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBhbHBoYS4gKi9cbiAgICB2YXIgYWxwaGEgPSBqYXZhID8gJ2EnIDogJ1xcdTAzYjEnO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBiZXRhLiAqL1xuICAgIHZhciBiZXRhID0gamF2YSA/ICdiJyA6ICdcXHUwM2IyJztcblxuICAgIC8qKiBCcm93c2VyIGRvY3VtZW50IG9iamVjdC4gKi9cbiAgICB2YXIgZG9jID0gY29udGV4dC5kb2N1bWVudCB8fCB7fTtcblxuICAgIC8qKlxuICAgICAqIERldGVjdCBPcGVyYSBicm93c2VyIChQcmVzdG8tYmFzZWQpLlxuICAgICAqIGh0dHA6Ly93d3cuaG93dG9jcmVhdGUuY28udWsvb3BlcmFTdHVmZi9vcGVyYU9iamVjdC5odG1sXG4gICAgICogaHR0cDovL2Rldi5vcGVyYS5jb20vYXJ0aWNsZXMvdmlldy9vcGVyYS1taW5pLXdlYi1jb250ZW50LWF1dGhvcmluZy1ndWlkZWxpbmVzLyNvcGVyYW1pbmlcbiAgICAgKi9cbiAgICB2YXIgb3BlcmEgPSBjb250ZXh0Lm9wZXJhbWluaSB8fCBjb250ZXh0Lm9wZXJhO1xuXG4gICAgLyoqIE9wZXJhIGBbW0NsYXNzXV1gLiAqL1xuICAgIHZhciBvcGVyYUNsYXNzID0gcmVPcGVyYS50ZXN0KG9wZXJhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIG9wZXJhKSA/IG9wZXJhWydbW0NsYXNzXV0nXSA6IGdldENsYXNzT2Yob3BlcmEpKVxuICAgICAgPyBvcGVyYUNsYXNzXG4gICAgICA6IChvcGVyYSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqIFRlbXBvcmFyeSB2YXJpYWJsZSB1c2VkIG92ZXIgdGhlIHNjcmlwdCdzIGxpZmV0aW1lLiAqL1xuICAgIHZhciBkYXRhO1xuXG4gICAgLyoqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlLiAqL1xuICAgIHZhciBhcmNoID0gdWE7XG5cbiAgICAvKiogUGxhdGZvcm0gZGVzY3JpcHRpb24gYXJyYXkuICovXG4gICAgdmFyIGRlc2NyaXB0aW9uID0gW107XG5cbiAgICAvKiogUGxhdGZvcm0gYWxwaGEvYmV0YSBpbmRpY2F0b3IuICovXG4gICAgdmFyIHByZXJlbGVhc2UgPSBudWxsO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSB0aGF0IGVudmlyb25tZW50IGZlYXR1cmVzIHNob3VsZCBiZSB1c2VkIHRvIHJlc29sdmUgdGhlIHBsYXRmb3JtLiAqL1xuICAgIHZhciB1c2VGZWF0dXJlcyA9IHVhID09IHVzZXJBZ2VudDtcblxuICAgIC8qKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLiAqL1xuICAgIHZhciB2ZXJzaW9uID0gdXNlRmVhdHVyZXMgJiYgb3BlcmEgJiYgdHlwZW9mIG9wZXJhLnZlcnNpb24gPT0gJ2Z1bmN0aW9uJyAmJiBvcGVyYS52ZXJzaW9uKCk7XG5cbiAgICAvKiogQSBmbGFnIHRvIGluZGljYXRlIGlmIHRoZSBPUyBlbmRzIHdpdGggXCIvIFZlcnNpb25cIiAqL1xuICAgIHZhciBpc1NwZWNpYWxDYXNlZE9TO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBsYXlvdXQgZW5naW5lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbGF5b3V0ID0gZ2V0TGF5b3V0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0VkZ2VIVE1MJywgJ3BhdHRlcm4nOiAnRWRnZScgfSxcbiAgICAgICdUcmlkZW50JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1dlYktpdCcsICdwYXR0ZXJuJzogJ0FwcGxlV2ViS2l0JyB9LFxuICAgICAgJ2lDYWInLFxuICAgICAgJ1ByZXN0bycsXG4gICAgICAnTmV0RnJvbnQnLFxuICAgICAgJ1Rhc21hbicsXG4gICAgICAnS0hUTUwnLFxuICAgICAgJ0dlY2tvJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBicm93c2VyIG5hbWVzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBuYW1lID0gZ2V0TmFtZShbXG4gICAgICAnQWRvYmUgQUlSJyxcbiAgICAgICdBcm9yYScsXG4gICAgICAnQXZhbnQgQnJvd3NlcicsXG4gICAgICAnQnJlYWNoJyxcbiAgICAgICdDYW1pbm8nLFxuICAgICAgJ0VsZWN0cm9uJyxcbiAgICAgICdFcGlwaGFueScsXG4gICAgICAnRmVubmVjJyxcbiAgICAgICdGbG9jaycsXG4gICAgICAnR2FsZW9uJyxcbiAgICAgICdHcmVlbkJyb3dzZXInLFxuICAgICAgJ2lDYWInLFxuICAgICAgJ0ljZXdlYXNlbCcsXG4gICAgICAnSy1NZWxlb24nLFxuICAgICAgJ0tvbnF1ZXJvcicsXG4gICAgICAnTHVuYXNjYXBlJyxcbiAgICAgICdNYXh0aG9uJyxcbiAgICAgIHsgJ2xhYmVsJzogJ01pY3Jvc29mdCBFZGdlJywgJ3BhdHRlcm4nOiAnRWRnZScgfSxcbiAgICAgICdNaWRvcmknLFxuICAgICAgJ05vb2sgQnJvd3NlcicsXG4gICAgICAnUGFsZU1vb24nLFxuICAgICAgJ1BoYW50b21KUycsXG4gICAgICAnUmF2ZW4nLFxuICAgICAgJ1Jla29ucScsXG4gICAgICAnUm9ja01lbHQnLFxuICAgICAgeyAnbGFiZWwnOiAnU2Ftc3VuZyBJbnRlcm5ldCcsICdwYXR0ZXJuJzogJ1NhbXN1bmdCcm93c2VyJyB9LFxuICAgICAgJ1NlYU1vbmtleScsXG4gICAgICB7ICdsYWJlbCc6ICdTaWxrJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ1NsZWlwbmlyJyxcbiAgICAgICdTbGltQnJvd3NlcicsXG4gICAgICB7ICdsYWJlbCc6ICdTUldhcmUgSXJvbicsICdwYXR0ZXJuJzogJ0lyb24nIH0sXG4gICAgICAnU3VucmlzZScsXG4gICAgICAnU3dpZnRmb3gnLFxuICAgICAgJ1dhdGVyZm94JyxcbiAgICAgICdXZWJQb3NpdGl2ZScsXG4gICAgICAnT3BlcmEgTWluaScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYSBNaW5pJywgJ3BhdHRlcm4nOiAnT1BpT1MnIH0sXG4gICAgICAnT3BlcmEnLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEnLCAncGF0dGVybic6ICdPUFInIH0sXG4gICAgICAnQ2hyb21lJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBNb2JpbGUnLCAncGF0dGVybic6ICcoPzpDcmlPU3xDck1vKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0ZpcmVmb3gnLCAncGF0dGVybic6ICcoPzpGaXJlZm94fE1pbmVmaWVsZCknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94IGZvciBpT1MnLCAncGF0dGVybic6ICdGeGlPUycgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0lFJywgJ3BhdHRlcm4nOiAnSUVNb2JpbGUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ01TSUUnIH0sXG4gICAgICAnU2FmYXJpJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBwcm9kdWN0cyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgcHJvZHVjdCA9IGdldFByb2R1Y3QoW1xuICAgICAgeyAnbGFiZWwnOiAnQmxhY2tCZXJyeScsICdwYXR0ZXJuJzogJ0JCMTAnIH0sXG4gICAgICAnQmxhY2tCZXJyeScsXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUycsICdwYXR0ZXJuJzogJ0dULUk5MDAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMyJywgJ3BhdHRlcm4nOiAnR1QtSTkxMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzMnLCAncGF0dGVybic6ICdHVC1JOTMwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNCcsICdwYXR0ZXJuJzogJ0dULUk5NTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM1JywgJ3BhdHRlcm4nOiAnU00tRzkwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNicsICdwYXR0ZXJuJzogJ1NNLUc5MjAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYgRWRnZScsICdwYXR0ZXJuJzogJ1NNLUc5MjUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzcnLCAncGF0dGVybic6ICdTTS1HOTMwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTM1JyB9LFxuICAgICAgJ0dvb2dsZSBUVicsXG4gICAgICAnTHVtaWEnLFxuICAgICAgJ2lQYWQnLFxuICAgICAgJ2lQb2QnLFxuICAgICAgJ2lQaG9uZScsXG4gICAgICAnS2luZGxlJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0tpbmRsZSBGaXJlJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ05leHVzJyxcbiAgICAgICdOb29rJyxcbiAgICAgICdQbGF5Qm9vaycsXG4gICAgICAnUGxheVN0YXRpb24gVml0YScsXG4gICAgICAnUGxheVN0YXRpb24nLFxuICAgICAgJ1RvdWNoUGFkJyxcbiAgICAgICdUcmFuc2Zvcm1lcicsXG4gICAgICB7ICdsYWJlbCc6ICdXaWkgVScsICdwYXR0ZXJuJzogJ1dpaVUnIH0sXG4gICAgICAnV2lpJyxcbiAgICAgICdYYm94IE9uZScsXG4gICAgICB7ICdsYWJlbCc6ICdYYm94IDM2MCcsICdwYXR0ZXJuJzogJ1hib3gnIH0sXG4gICAgICAnWG9vbSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgbWFudWZhY3R1cmVycy4gKi9cbiAgICB2YXIgbWFudWZhY3R1cmVyID0gZ2V0TWFudWZhY3R1cmVyKHtcbiAgICAgICdBcHBsZSc6IHsgJ2lQYWQnOiAxLCAnaVBob25lJzogMSwgJ2lQb2QnOiAxIH0sXG4gICAgICAnQXJjaG9zJzoge30sXG4gICAgICAnQW1hem9uJzogeyAnS2luZGxlJzogMSwgJ0tpbmRsZSBGaXJlJzogMSB9LFxuICAgICAgJ0FzdXMnOiB7ICdUcmFuc2Zvcm1lcic6IDEgfSxcbiAgICAgICdCYXJuZXMgJiBOb2JsZSc6IHsgJ05vb2snOiAxIH0sXG4gICAgICAnQmxhY2tCZXJyeSc6IHsgJ1BsYXlCb29rJzogMSB9LFxuICAgICAgJ0dvb2dsZSc6IHsgJ0dvb2dsZSBUVic6IDEsICdOZXh1cyc6IDEgfSxcbiAgICAgICdIUCc6IHsgJ1RvdWNoUGFkJzogMSB9LFxuICAgICAgJ0hUQyc6IHt9LFxuICAgICAgJ0xHJzoge30sXG4gICAgICAnTWljcm9zb2Z0JzogeyAnWGJveCc6IDEsICdYYm94IE9uZSc6IDEgfSxcbiAgICAgICdNb3Rvcm9sYSc6IHsgJ1hvb20nOiAxIH0sXG4gICAgICAnTmludGVuZG8nOiB7ICdXaWkgVSc6IDEsICAnV2lpJzogMSB9LFxuICAgICAgJ05va2lhJzogeyAnTHVtaWEnOiAxIH0sXG4gICAgICAnU2Ftc3VuZyc6IHsgJ0dhbGF4eSBTJzogMSwgJ0dhbGF4eSBTMic6IDEsICdHYWxheHkgUzMnOiAxLCAnR2FsYXh5IFM0JzogMSB9LFxuICAgICAgJ1NvbnknOiB7ICdQbGF5U3RhdGlvbic6IDEsICdQbGF5U3RhdGlvbiBWaXRhJzogMSB9XG4gICAgfSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG9wZXJhdGluZyBzeXN0ZW1zIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBvcyA9IGdldE9TKFtcbiAgICAgICdXaW5kb3dzIFBob25lJyxcbiAgICAgICdBbmRyb2lkJyxcbiAgICAgICdDZW50T1MnLFxuICAgICAgeyAnbGFiZWwnOiAnQ2hyb21lIE9TJywgJ3BhdHRlcm4nOiAnQ3JPUycgfSxcbiAgICAgICdEZWJpYW4nLFxuICAgICAgJ0ZlZG9yYScsXG4gICAgICAnRnJlZUJTRCcsXG4gICAgICAnR2VudG9vJyxcbiAgICAgICdIYWlrdScsXG4gICAgICAnS3VidW50dScsXG4gICAgICAnTGludXggTWludCcsXG4gICAgICAnT3BlbkJTRCcsXG4gICAgICAnUmVkIEhhdCcsXG4gICAgICAnU3VTRScsXG4gICAgICAnVWJ1bnR1JyxcbiAgICAgICdYdWJ1bnR1JyxcbiAgICAgICdDeWd3aW4nLFxuICAgICAgJ1N5bWJpYW4gT1MnLFxuICAgICAgJ2hwd09TJyxcbiAgICAgICd3ZWJPUyAnLFxuICAgICAgJ3dlYk9TJyxcbiAgICAgICdUYWJsZXQgT1MnLFxuICAgICAgJ1RpemVuJyxcbiAgICAgICdMaW51eCcsXG4gICAgICAnTWFjIE9TIFgnLFxuICAgICAgJ01hY2ludG9zaCcsXG4gICAgICAnTWFjJyxcbiAgICAgICdXaW5kb3dzIDk4OycsXG4gICAgICAnV2luZG93cyAnXG4gICAgXSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgbGF5b3V0IGVuZ2luZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBsYXlvdXQgZW5naW5lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldExheW91dChndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCBSZWdFeHAoJ1xcXFxiJyArIChcbiAgICAgICAgICBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpXG4gICAgICAgICkgKyAnXFxcXGInLCAnaScpLmV4ZWModWEpICYmIChndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgbWFudWZhY3R1cmVyIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBvYmplY3Qgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBtYW51ZmFjdHVyZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TWFudWZhY3R1cmVyKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICAgIC8vIExvb2t1cCB0aGUgbWFudWZhY3R1cmVyIGJ5IHByb2R1Y3Qgb3Igc2NhbiB0aGUgVUEgZm9yIHRoZSBtYW51ZmFjdHVyZXIuXG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgKFxuICAgICAgICAgIHZhbHVlW3Byb2R1Y3RdIHx8XG4gICAgICAgICAgdmFsdWVbL15bYS16XSsoPzogK1thLXpdK1xcYikqL2kuZXhlYyhwcm9kdWN0KV0gfHxcbiAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHF1YWxpZnkoa2V5KSArICcoPzpcXFxcYnxcXFxcdypcXFxcZCknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICkgJiYga2V5O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGJyb3dzZXIgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBicm93c2VyIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TmFtZShndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCBSZWdFeHAoJ1xcXFxiJyArIChcbiAgICAgICAgICBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpXG4gICAgICAgICkgKyAnXFxcXGInLCAnaScpLmV4ZWModWEpICYmIChndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgT1MgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBPUyBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE9TKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnKD86L1tcXFxcZC5dK3xbIFxcXFx3Ll0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICByZXN1bHQgPSBjbGVhbnVwT1MocmVzdWx0LCBwYXR0ZXJuLCBndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBwcm9kdWN0IG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgcHJvZHVjdCBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFByb2R1Y3QoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKTtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgKHJlc3VsdCA9XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcgKlxcXFxkK1suXFxcXHdfXSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcgKlxcXFx3Ky1bXFxcXHddKicsICdpJykuZXhlYyh1YSkgfHxcbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/OjsgKig/OlthLXpdK1tfLV0pP1thLXpdK1xcXFxkK3xbXiAoKTstXSopJywgJ2knKS5leGVjKHVhKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIC8vIFNwbGl0IGJ5IGZvcndhcmQgc2xhc2ggYW5kIGFwcGVuZCBwcm9kdWN0IHZlcnNpb24gaWYgbmVlZGVkLlxuICAgICAgICAgIGlmICgocmVzdWx0ID0gU3RyaW5nKChndWVzcy5sYWJlbCAmJiAhUmVnRXhwKHBhdHRlcm4sICdpJykudGVzdChndWVzcy5sYWJlbCkpID8gZ3Vlc3MubGFiZWwgOiByZXN1bHQpLnNwbGl0KCcvJykpWzFdICYmICEvW1xcZC5dKy8udGVzdChyZXN1bHRbMF0pKSB7XG4gICAgICAgICAgICByZXN1bHRbMF0gKz0gJyAnICsgcmVzdWx0WzFdO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBDb3JyZWN0IGNoYXJhY3RlciBjYXNlIGFuZCBjbGVhbnVwIHN0cmluZy5cbiAgICAgICAgICBndWVzcyA9IGd1ZXNzLmxhYmVsIHx8IGd1ZXNzO1xuICAgICAgICAgIHJlc3VsdCA9IGZvcm1hdChyZXN1bHRbMF1cbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cChwYXR0ZXJuLCAnaScpLCBndWVzcylcbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cCgnOyAqKD86JyArIGd1ZXNzICsgJ1tfLV0pPycsICdpJyksICcgJylcbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cCgnKCcgKyBndWVzcyArICcpWy1fLl0/KFxcXFx3KScsICdpJyksICckMSAkMicpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzb2x2ZXMgdGhlIHZlcnNpb24gdXNpbmcgYW4gYXJyYXkgb2YgVUEgcGF0dGVybnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhdHRlcm5zIEFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHZlcnNpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0VmVyc2lvbihwYXR0ZXJucykge1xuICAgICAgcmV0dXJuIHJlZHVjZShwYXR0ZXJucywgZnVuY3Rpb24ocmVzdWx0LCBwYXR0ZXJuKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgKFJlZ0V4cChwYXR0ZXJuICtcbiAgICAgICAgICAnKD86LVtcXFxcZC5dKy98KD86IGZvciBbXFxcXHctXSspP1sgLy1dKShbXFxcXGQuXStbXiAoKTsvXy1dKiknLCAnaScpLmV4ZWModWEpIHx8IDApWzFdIHx8IG51bGw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgd2hlbiB0aGUgcGxhdGZvcm0gb2JqZWN0IGlzIGNvZXJjZWQgdG8gYSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbmFtZSB0b1N0cmluZ1xuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgYHBsYXRmb3JtLmRlc2NyaXB0aW9uYCBpZiBhdmFpbGFibGUsIGVsc2UgYW4gZW1wdHkgc3RyaW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvU3RyaW5nUGxhdGZvcm0oKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXNjcmlwdGlvbiB8fCAnJztcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBDb252ZXJ0IGxheW91dCB0byBhbiBhcnJheSBzbyB3ZSBjYW4gYWRkIGV4dHJhIGRldGFpbHMuXG4gICAgbGF5b3V0ICYmIChsYXlvdXQgPSBbbGF5b3V0XSk7XG5cbiAgICAvLyBEZXRlY3QgcHJvZHVjdCBuYW1lcyB0aGF0IGNvbnRhaW4gdGhlaXIgbWFudWZhY3R1cmVyJ3MgbmFtZS5cbiAgICBpZiAobWFudWZhY3R1cmVyICYmICFwcm9kdWN0KSB7XG4gICAgICBwcm9kdWN0ID0gZ2V0UHJvZHVjdChbbWFudWZhY3R1cmVyXSk7XG4gICAgfVxuICAgIC8vIENsZWFuIHVwIEdvb2dsZSBUVi5cbiAgICBpZiAoKGRhdGEgPSAvXFxiR29vZ2xlIFRWXFxiLy5leGVjKHByb2R1Y3QpKSkge1xuICAgICAgcHJvZHVjdCA9IGRhdGFbMF07XG4gICAgfVxuICAgIC8vIERldGVjdCBzaW11bGF0b3JzLlxuICAgIGlmICgvXFxiU2ltdWxhdG9yXFxiL2kudGVzdCh1YSkpIHtcbiAgICAgIHByb2R1Y3QgPSAocHJvZHVjdCA/IHByb2R1Y3QgKyAnICcgOiAnJykgKyAnU2ltdWxhdG9yJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIE1pbmkgOCsgcnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZSBvbiBpT1MuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhIE1pbmknICYmIC9cXGJPUGlPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ3J1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIE1vYmlsZSAxMS5cbiAgICBpZiAobmFtZSA9PSAnSUUnICYmIC9cXGJsaWtlIGlQaG9uZSBPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRhdGEgPSBwYXJzZSh1YS5yZXBsYWNlKC9saWtlIGlQaG9uZSBPUy8sICcnKSk7XG4gICAgICBtYW51ZmFjdHVyZXIgPSBkYXRhLm1hbnVmYWN0dXJlcjtcbiAgICAgIHByb2R1Y3QgPSBkYXRhLnByb2R1Y3Q7XG4gICAgfVxuICAgIC8vIERldGVjdCBpT1MuXG4gICAgZWxzZSBpZiAoL15pUC8udGVzdChwcm9kdWN0KSkge1xuICAgICAgbmFtZSB8fCAobmFtZSA9ICdTYWZhcmknKTtcbiAgICAgIG9zID0gJ2lPUycgKyAoKGRhdGEgPSAvIE9TIChbXFxkX10rKS9pLmV4ZWModWEpKVxuICAgICAgICA/ICcgJyArIGRhdGFbMV0ucmVwbGFjZSgvXy9nLCAnLicpXG4gICAgICAgIDogJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgS3VidW50dS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdLb25xdWVyb3InICYmICEvYnVudHUvaS50ZXN0KG9zKSkge1xuICAgICAgb3MgPSAnS3VidW50dSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBBbmRyb2lkIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKChtYW51ZmFjdHVyZXIgJiYgbWFudWZhY3R1cmVyICE9ICdHb29nbGUnICYmXG4gICAgICAgICgoL0Nocm9tZS8udGVzdChuYW1lKSAmJiAhL1xcYk1vYmlsZSBTYWZhcmlcXGIvaS50ZXN0KHVhKSkgfHwgL1xcYlZpdGFcXGIvLnRlc3QocHJvZHVjdCkpKSB8fFxuICAgICAgICAoL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpICYmIC9eQ2hyb21lLy50ZXN0KG5hbWUpICYmIC9cXGJWZXJzaW9uXFwvL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lID0gJ0FuZHJvaWQgQnJvd3Nlcic7XG4gICAgICBvcyA9IC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogJ0FuZHJvaWQnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgU2lsayBkZXNrdG9wL2FjY2VsZXJhdGVkIG1vZGVzLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1NpbGsnKSB7XG4gICAgICBpZiAoIS9cXGJNb2JpL2kudGVzdCh1YSkpIHtcbiAgICAgICAgb3MgPSAnQW5kcm9pZCc7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgfVxuICAgICAgaWYgKC9BY2NlbGVyYXRlZCAqPSAqdHJ1ZS9pLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2FjY2VsZXJhdGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBQYWxlTW9vbiBpZGVudGlmeWluZyBhcyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1BhbGVNb29uJyAmJiAoZGF0YSA9IC9cXGJGaXJlZm94XFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzIEZpcmVmb3ggJyArIGRhdGFbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBPUyBhbmQgcHJvZHVjdHMgcnVubmluZyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIChkYXRhID0gL1xcYihNb2JpbGV8VGFibGV0fFRWKVxcYi9pLmV4ZWModWEpKSkge1xuICAgICAgb3MgfHwgKG9zID0gJ0ZpcmVmb3ggT1MnKTtcbiAgICAgIHByb2R1Y3QgfHwgKHByb2R1Y3QgPSBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGZhbHNlIHBvc2l0aXZlcyBmb3IgRmlyZWZveC9TYWZhcmkuXG4gICAgZWxzZSBpZiAoIW5hbWUgfHwgKGRhdGEgPSAhL1xcYk1pbmVmaWVsZFxcYi9pLnRlc3QodWEpICYmIC9cXGIoPzpGaXJlZm94fFNhZmFyaSlcXGIvLmV4ZWMobmFtZSkpKSB7XG4gICAgICAvLyBFc2NhcGUgdGhlIGAvYCBmb3IgRmlyZWZveCAxLlxuICAgICAgaWYgKG5hbWUgJiYgIXByb2R1Y3QgJiYgL1tcXC8sXXxeW14oXSs/XFwpLy50ZXN0KHVhLnNsaWNlKHVhLmluZGV4T2YoZGF0YSArICcvJykgKyA4KSkpIHtcbiAgICAgICAgLy8gQ2xlYXIgbmFtZSBvZiBmYWxzZSBwb3NpdGl2ZXMuXG4gICAgICAgIG5hbWUgPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gUmVhc3NpZ24gYSBnZW5lcmljIG5hbWUuXG4gICAgICBpZiAoKGRhdGEgPSBwcm9kdWN0IHx8IG1hbnVmYWN0dXJlciB8fCBvcykgJiZcbiAgICAgICAgICAocHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgL1xcYig/OkFuZHJvaWR8U3ltYmlhbiBPU3xUYWJsZXQgT1N8d2ViT1MpXFxiLy50ZXN0KG9zKSkpIHtcbiAgICAgICAgbmFtZSA9IC9bYS16XSsoPzogSGF0KT8vaS5leGVjKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogZGF0YSkgKyAnIEJyb3dzZXInO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgQ2hyb21lIHZlcnNpb24gdG8gZGVzY3JpcHRpb24gZm9yIEVsZWN0cm9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0VsZWN0cm9uJyAmJiAoZGF0YSA9ICgvXFxiQ2hyb21lXFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyBkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IG5vbi1PcGVyYSAoUHJlc3RvLWJhc2VkKSB2ZXJzaW9ucyAob3JkZXIgaXMgaW1wb3J0YW50KS5cbiAgICBpZiAoIXZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSBnZXRWZXJzaW9uKFtcbiAgICAgICAgJyg/OkNsb3VkOXxDcmlPU3xDck1vfEVkZ2V8RnhpT1N8SUVNb2JpbGV8SXJvbnxPcGVyYSA/TWluaXxPUGlPU3xPUFJ8UmF2ZW58U2Ftc3VuZ0Jyb3dzZXJ8U2lsayg/IS9bXFxcXGQuXSskKSknLFxuICAgICAgICAnVmVyc2lvbicsXG4gICAgICAgIHF1YWxpZnkobmFtZSksXG4gICAgICAgICcoPzpGaXJlZm94fE1pbmVmaWVsZHxOZXRGcm9udCknXG4gICAgICBdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHN0dWJib3JuIGxheW91dCBlbmdpbmVzLlxuICAgIGlmICgoZGF0YSA9XG4gICAgICAgICAgbGF5b3V0ID09ICdpQ2FiJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID4gMyAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgIC9cXGJPcGVyYVxcYi8udGVzdChuYW1lKSAmJiAoL1xcYk9QUlxcYi8udGVzdCh1YSkgPyAnQmxpbmsnIDogJ1ByZXN0bycpIHx8XG4gICAgICAgICAgL1xcYig/Ok1pZG9yaXxOb29rfFNhZmFyaSlcXGIvaS50ZXN0KHVhKSAmJiAhL14oPzpUcmlkZW50fEVkZ2VIVE1MKSQvLnRlc3QobGF5b3V0KSAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgICFsYXlvdXQgJiYgL1xcYk1TSUVcXGIvaS50ZXN0KHVhKSAmJiAob3MgPT0gJ01hYyBPUycgPyAnVGFzbWFuJyA6ICdUcmlkZW50JykgfHxcbiAgICAgICAgICBsYXlvdXQgPT0gJ1dlYktpdCcgJiYgL1xcYlBsYXlTdGF0aW9uXFxiKD8hIFZpdGFcXGIpL2kudGVzdChuYW1lKSAmJiAnTmV0RnJvbnQnXG4gICAgICAgICkpIHtcbiAgICAgIGxheW91dCA9IFtkYXRhXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgUGhvbmUgNyBkZXNrdG9wIG1vZGUuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAoZGF0YSA9ICgvOyAqKD86WEJMV1B8WnVuZVdQKShcXGQrKS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lICcgKyAoL1xcKyQvLnRlc3QoZGF0YSkgPyBkYXRhIDogZGF0YSArICcueCcpO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDgueCBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAoL1xcYldQRGVza3RvcFxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBuYW1lID0gJ0lFIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lIDgueCc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIHZlcnNpb24gfHwgKHZlcnNpb24gPSAoL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkgfHwgMClbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgMTEgaWRlbnRpZnlpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAobmFtZSAhPSAnSUUnICYmIGxheW91dCA9PSAnVHJpZGVudCcgJiYgKGRhdGEgPSAvXFxicnY6KFtcXGQuXSspLy5leGVjKHVhKSkpIHtcbiAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzICcgKyBuYW1lICsgKHZlcnNpb24gPyAnICcgKyB2ZXJzaW9uIDogJycpKTtcbiAgICAgIH1cbiAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgdmVyc2lvbiA9IGRhdGFbMV07XG4gICAgfVxuICAgIC8vIExldmVyYWdlIGVudmlyb25tZW50IGZlYXR1cmVzLlxuICAgIGlmICh1c2VGZWF0dXJlcykge1xuICAgICAgLy8gRGV0ZWN0IHNlcnZlci1zaWRlIGVudmlyb25tZW50cy5cbiAgICAgIC8vIFJoaW5vIGhhcyBhIGdsb2JhbCBmdW5jdGlvbiB3aGlsZSBvdGhlcnMgaGF2ZSBhIGdsb2JhbCBvYmplY3QuXG4gICAgICBpZiAoaXNIb3N0VHlwZShjb250ZXh0LCAnZ2xvYmFsJykpIHtcbiAgICAgICAgaWYgKGphdmEpIHtcbiAgICAgICAgICBkYXRhID0gamF2YS5sYW5nLlN5c3RlbTtcbiAgICAgICAgICBhcmNoID0gZGF0YS5nZXRQcm9wZXJ0eSgnb3MuYXJjaCcpO1xuICAgICAgICAgIG9zID0gb3MgfHwgZGF0YS5nZXRQcm9wZXJ0eSgnb3MubmFtZScpICsgJyAnICsgZGF0YS5nZXRQcm9wZXJ0eSgnb3MudmVyc2lvbicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyaGlubykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2ZXJzaW9uID0gY29udGV4dC5yZXF1aXJlKCdyaW5nby9lbmdpbmUnKS52ZXJzaW9uLmpvaW4oJy4nKTtcbiAgICAgICAgICAgIG5hbWUgPSAnUmluZ29KUyc7XG4gICAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgICBpZiAoKGRhdGEgPSBjb250ZXh0LnN5c3RlbSkgJiYgZGF0YS5nbG9iYWwuc3lzdGVtID09IGNvbnRleHQuc3lzdGVtKSB7XG4gICAgICAgICAgICAgIG5hbWUgPSAnTmFyd2hhbCc7XG4gICAgICAgICAgICAgIG9zIHx8IChvcyA9IGRhdGFbMF0ub3MgfHwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdSaGlubyc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKFxuICAgICAgICAgIHR5cGVvZiBjb250ZXh0LnByb2Nlc3MgPT0gJ29iamVjdCcgJiYgIWNvbnRleHQucHJvY2Vzcy5icm93c2VyICYmXG4gICAgICAgICAgKGRhdGEgPSBjb250ZXh0LnByb2Nlc3MpXG4gICAgICAgICkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucyA9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLmVsZWN0cm9uID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ05vZGUgJyArIGRhdGEudmVyc2lvbnMubm9kZSk7XG4gICAgICAgICAgICAgIG5hbWUgPSAnRWxlY3Ryb24nO1xuICAgICAgICAgICAgICB2ZXJzaW9uID0gZGF0YS52ZXJzaW9ucy5lbGVjdHJvbjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMubncgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnQ2hyb21pdW0gJyArIHZlcnNpb24sICdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ05XLmpzJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMubnc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdOb2RlLmpzJztcbiAgICAgICAgICAgIGFyY2ggPSBkYXRhLmFyY2g7XG4gICAgICAgICAgICBvcyA9IGRhdGEucGxhdGZvcm07XG4gICAgICAgICAgICB2ZXJzaW9uID0gL1tcXGQuXSsvLmV4ZWMoZGF0YS52ZXJzaW9uKTtcbiAgICAgICAgICAgIHZlcnNpb24gPSB2ZXJzaW9uID8gdmVyc2lvblswXSA6IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgQWRvYmUgQUlSLlxuICAgICAgZWxzZSBpZiAoZ2V0Q2xhc3NPZigoZGF0YSA9IGNvbnRleHQucnVudGltZSkpID09IGFpclJ1bnRpbWVDbGFzcykge1xuICAgICAgICBuYW1lID0gJ0Fkb2JlIEFJUic7XG4gICAgICAgIG9zID0gZGF0YS5mbGFzaC5zeXN0ZW0uQ2FwYWJpbGl0aWVzLm9zO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IFBoYW50b21KUy5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnBoYW50b20pKSA9PSBwaGFudG9tQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdQaGFudG9tSlMnO1xuICAgICAgICB2ZXJzaW9uID0gKGRhdGEgPSBkYXRhLnZlcnNpb24gfHwgbnVsbCkgJiYgKGRhdGEubWFqb3IgKyAnLicgKyBkYXRhLm1pbm9yICsgJy4nICsgZGF0YS5wYXRjaCk7XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSUUgY29tcGF0aWJpbGl0eSBtb2Rlcy5cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBkb2MuZG9jdW1lbnRNb2RlID09ICdudW1iZXInICYmIChkYXRhID0gL1xcYlRyaWRlbnRcXC8oXFxkKykvaS5leGVjKHVhKSkpIHtcbiAgICAgICAgLy8gV2UncmUgaW4gY29tcGF0aWJpbGl0eSBtb2RlIHdoZW4gdGhlIFRyaWRlbnQgdmVyc2lvbiArIDQgZG9lc24ndFxuICAgICAgICAvLyBlcXVhbCB0aGUgZG9jdW1lbnQgbW9kZS5cbiAgICAgICAgdmVyc2lvbiA9IFt2ZXJzaW9uLCBkb2MuZG9jdW1lbnRNb2RlXTtcbiAgICAgICAgaWYgKChkYXRhID0gK2RhdGFbMV0gKyA0KSAhPSB2ZXJzaW9uWzFdKSB7XG4gICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnSUUgJyArIHZlcnNpb25bMV0gKyAnIG1vZGUnKTtcbiAgICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICcnKTtcbiAgICAgICAgICB2ZXJzaW9uWzFdID0gZGF0YTtcbiAgICAgICAgfVxuICAgICAgICB2ZXJzaW9uID0gbmFtZSA9PSAnSUUnID8gU3RyaW5nKHZlcnNpb25bMV0udG9GaXhlZCgxKSkgOiB2ZXJzaW9uWzBdO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIDExIG1hc2tpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAvXig/OkNocm9tZXxGaXJlZm94KVxcYi8udGVzdChuYW1lKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdtYXNraW5nIGFzICcgKyBuYW1lICsgJyAnICsgdmVyc2lvbik7XG4gICAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgICB2ZXJzaW9uID0gJzExLjAnO1xuICAgICAgICBsYXlvdXQgPSBbJ1RyaWRlbnQnXTtcbiAgICAgICAgb3MgPSAnV2luZG93cyc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zICYmIGZvcm1hdChvcyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBwcmVyZWxlYXNlIHBoYXNlcy5cbiAgICBpZiAodmVyc2lvbiAmJiAoZGF0YSA9XG4gICAgICAgICAgLyg/OlthYl18ZHB8cHJlfFthYl1cXGQrcHJlKSg/OlxcZCtcXCs/KT8kL2kuZXhlYyh2ZXJzaW9uKSB8fFxuICAgICAgICAgIC8oPzphbHBoYXxiZXRhKSg/OiA/XFxkKT8vaS5leGVjKHVhICsgJzsnICsgKHVzZUZlYXR1cmVzICYmIG5hdi5hcHBNaW5vclZlcnNpb24pKSB8fFxuICAgICAgICAgIC9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAnYSdcbiAgICAgICAgKSkge1xuICAgICAgcHJlcmVsZWFzZSA9IC9iL2kudGVzdChkYXRhKSA/ICdiZXRhJyA6ICdhbHBoYSc7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKFJlZ0V4cChkYXRhICsgJ1xcXFwrPyQnKSwgJycpICtcbiAgICAgICAgKHByZXJlbGVhc2UgPT0gJ2JldGEnID8gYmV0YSA6IGFscGhhKSArICgvXFxkK1xcKz8vLmV4ZWMoZGF0YSkgfHwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBNb2JpbGUuXG4gICAgaWYgKG5hbWUgPT0gJ0Zlbm5lYycgfHwgbmFtZSA9PSAnRmlyZWZveCcgJiYgL1xcYig/OkFuZHJvaWR8RmlyZWZveCBPUylcXGIvLnRlc3Qob3MpKSB7XG4gICAgICBuYW1lID0gJ0ZpcmVmb3ggTW9iaWxlJztcbiAgICB9XG4gICAgLy8gT2JzY3VyZSBNYXh0aG9uJ3MgdW5yZWxpYWJsZSB2ZXJzaW9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ01heHRob24nICYmIHZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSB2ZXJzaW9uLnJlcGxhY2UoL1xcLltcXGQuXSsvLCAnLngnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFhib3ggMzYwIGFuZCBYYm94IE9uZS5cbiAgICBlbHNlIGlmICgvXFxiWGJveFxcYi9pLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcpIHtcbiAgICAgICAgb3MgPSBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHByb2R1Y3QgPT0gJ1hib3ggMzYwJyAmJiAvXFxiSUVNb2JpbGVcXGIvLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ21vYmlsZSBtb2RlJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFkZCBtb2JpbGUgcG9zdGZpeC5cbiAgICBlbHNlIGlmICgoL14oPzpDaHJvbWV8SUV8T3BlcmEpJC8udGVzdChuYW1lKSB8fCBuYW1lICYmICFwcm9kdWN0ICYmICEvQnJvd3NlcnxNb2JpLy50ZXN0KG5hbWUpKSAmJlxuICAgICAgICAob3MgPT0gJ1dpbmRvd3MgQ0UnIHx8IC9Nb2JpL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lICs9ICcgTW9iaWxlJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIHBsYXRmb3JtIHByZXZpZXcuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnSUUnICYmIHVzZUZlYXR1cmVzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoY29udGV4dC5leHRlcm5hbCA9PT0gbnVsbCkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ3BsYXRmb3JtIHByZXZpZXcnKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2VtYmVkZGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBCbGFja0JlcnJ5IE9TIHZlcnNpb24uXG4gICAgLy8gaHR0cDovL2RvY3MuYmxhY2tiZXJyeS5jb20vZW4vZGV2ZWxvcGVycy9kZWxpdmVyYWJsZXMvMTgxNjkvSFRUUF9oZWFkZXJzX3NlbnRfYnlfQkJfQnJvd3Nlcl8xMjM0OTExXzExLmpzcFxuICAgIGVsc2UgaWYgKCgvXFxiQmxhY2tCZXJyeVxcYi8udGVzdChwcm9kdWN0KSB8fCAvXFxiQkIxMFxcYi8udGVzdCh1YSkpICYmIChkYXRhID1cbiAgICAgICAgICAoUmVnRXhwKHByb2R1Y3QucmVwbGFjZSgvICsvZywgJyAqJykgKyAnLyhbLlxcXFxkXSspJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fFxuICAgICAgICAgIHZlcnNpb25cbiAgICAgICAgKSkge1xuICAgICAgZGF0YSA9IFtkYXRhLCAvQkIxMC8udGVzdCh1YSldO1xuICAgICAgb3MgPSAoZGF0YVsxXSA/IChwcm9kdWN0ID0gbnVsbCwgbWFudWZhY3R1cmVyID0gJ0JsYWNrQmVycnknKSA6ICdEZXZpY2UgU29mdHdhcmUnKSArICcgJyArIGRhdGFbMF07XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGlkZW50aWZ5aW5nL21hc2tpbmcgaXRzZWxmIGFzIGFub3RoZXIgYnJvd3Nlci5cbiAgICAvLyBodHRwOi8vd3d3Lm9wZXJhLmNvbS9zdXBwb3J0L2tiL3ZpZXcvODQzL1xuICAgIGVsc2UgaWYgKHRoaXMgIT0gZm9yT3duICYmIHByb2R1Y3QgIT0gJ1dpaScgJiYgKFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiBvcGVyYSkgfHxcbiAgICAgICAgICAoL09wZXJhLy50ZXN0KG5hbWUpICYmIC9cXGIoPzpNU0lFfEZpcmVmb3gpXFxiL2kudGVzdCh1YSkpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGJPUyBYICg/OlxcZCtcXC4pezIsfS8udGVzdChvcykpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0lFJyAmJiAoXG4gICAgICAgICAgICAob3MgJiYgIS9eV2luLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gNS41KSB8fFxuICAgICAgICAgICAgL1xcYldpbmRvd3MgWFBcXGIvLnRlc3Qob3MpICYmIHZlcnNpb24gPiA4IHx8XG4gICAgICAgICAgICB2ZXJzaW9uID09IDggJiYgIS9cXGJUcmlkZW50XFxiLy50ZXN0KHVhKVxuICAgICAgICAgICkpXG4gICAgICAgICkgJiYgIXJlT3BlcmEudGVzdCgoZGF0YSA9IHBhcnNlLmNhbGwoZm9yT3duLCB1YS5yZXBsYWNlKHJlT3BlcmEsICcnKSArICc7JykpKSAmJiBkYXRhLm5hbWUpIHtcbiAgICAgIC8vIFdoZW4gXCJpZGVudGlmeWluZ1wiLCB0aGUgVUEgY29udGFpbnMgYm90aCBPcGVyYSBhbmQgdGhlIG90aGVyIGJyb3dzZXIncyBuYW1lLlxuICAgICAgZGF0YSA9ICdpbmcgYXMgJyArIGRhdGEubmFtZSArICgoZGF0YSA9IGRhdGEudmVyc2lvbikgPyAnICcgKyBkYXRhIDogJycpO1xuICAgICAgaWYgKHJlT3BlcmEudGVzdChuYW1lKSkge1xuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpICYmIG9zID09ICdNYWMgT1MnKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGRhdGEgPSAnaWRlbnRpZnknICsgZGF0YTtcbiAgICAgIH1cbiAgICAgIC8vIFdoZW4gXCJtYXNraW5nXCIsIHRoZSBVQSBjb250YWlucyBvbmx5IHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGVsc2Uge1xuICAgICAgICBkYXRhID0gJ21hc2snICsgZGF0YTtcbiAgICAgICAgaWYgKG9wZXJhQ2xhc3MpIHtcbiAgICAgICAgICBuYW1lID0gZm9ybWF0KG9wZXJhQ2xhc3MucmVwbGFjZSgvKFthLXpdKShbQS1aXSkvZywgJyQxICQyJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5hbWUgPSAnT3BlcmEnO1xuICAgICAgICB9XG4gICAgICAgIGlmICgvXFxiSUVcXGIvLnRlc3QoZGF0YSkpIHtcbiAgICAgICAgICBvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF1c2VGZWF0dXJlcykge1xuICAgICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsYXlvdXQgPSBbJ1ByZXN0byddO1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdlYktpdCBOaWdodGx5IGFuZCBhcHByb3hpbWF0ZSBDaHJvbWUvU2FmYXJpIHZlcnNpb25zLlxuICAgIGlmICgoZGF0YSA9ICgvXFxiQXBwbGVXZWJLaXRcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAvLyBDb3JyZWN0IGJ1aWxkIG51bWJlciBmb3IgbnVtZXJpYyBjb21wYXJpc29uLlxuICAgICAgLy8gKGUuZy4gXCI1MzIuNVwiIGJlY29tZXMgXCI1MzIuMDVcIilcbiAgICAgIGRhdGEgPSBbcGFyc2VGbG9hdChkYXRhLnJlcGxhY2UoL1xcLihcXGQpJC8sICcuMCQxJykpLCBkYXRhXTtcbiAgICAgIC8vIE5pZ2h0bHkgYnVpbGRzIGFyZSBwb3N0Zml4ZWQgd2l0aCBhIFwiK1wiLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgZGF0YVsxXS5zbGljZSgtMSkgPT0gJysnKSB7XG4gICAgICAgIG5hbWUgPSAnV2ViS2l0IE5pZ2h0bHknO1xuICAgICAgICBwcmVyZWxlYXNlID0gJ2FscGhhJztcbiAgICAgICAgdmVyc2lvbiA9IGRhdGFbMV0uc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuICAgICAgLy8gQ2xlYXIgaW5jb3JyZWN0IGJyb3dzZXIgdmVyc2lvbnMuXG4gICAgICBlbHNlIGlmICh2ZXJzaW9uID09IGRhdGFbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uID09IChkYXRhWzJdID0gKC9cXGJTYWZhcmlcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHRoZSBmdWxsIENocm9tZSB2ZXJzaW9uIHdoZW4gYXZhaWxhYmxlLlxuICAgICAgZGF0YVsxXSA9ICgvXFxiQ2hyb21lXFwvKFtcXGQuXSspL2kuZXhlYyh1YSkgfHwgMClbMV07XG4gICAgICAvLyBEZXRlY3QgQmxpbmsgbGF5b3V0IGVuZ2luZS5cbiAgICAgIGlmIChkYXRhWzBdID09IDUzNy4zNiAmJiBkYXRhWzJdID09IDUzNy4zNiAmJiBwYXJzZUZsb2F0KGRhdGFbMV0pID49IDI4ICYmIGxheW91dCA9PSAnV2ViS2l0Jykge1xuICAgICAgICBsYXlvdXQgPSBbJ0JsaW5rJ107XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSmF2YVNjcmlwdENvcmUuXG4gICAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY3Njg0NzQvaG93LWNhbi1pLWRldGVjdC13aGljaC1qYXZhc2NyaXB0LWVuZ2luZS12OC1vci1qc2MtaXMtdXNlZC1hdC1ydW50aW1lLWluLWFuZHJvaVxuICAgICAgaWYgKCF1c2VGZWF0dXJlcyB8fCAoIWxpa2VDaHJvbWUgJiYgIWRhdGFbMV0pKSB7XG4gICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJ2xpa2UgU2FmYXJpJyk7XG4gICAgICAgIGRhdGEgPSAoZGF0YSA9IGRhdGFbMF0sIGRhdGEgPCA0MDAgPyAxIDogZGF0YSA8IDUwMCA/IDIgOiBkYXRhIDwgNTI2ID8gMyA6IGRhdGEgPCA1MzMgPyA0IDogZGF0YSA8IDUzNCA/ICc0KycgOiBkYXRhIDwgNTM1ID8gNSA6IGRhdGEgPCA1MzcgPyA2IDogZGF0YSA8IDUzOCA/IDcgOiBkYXRhIDwgNjAxID8gOCA6ICc4Jyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIENocm9tZScpO1xuICAgICAgICBkYXRhID0gZGF0YVsxXSB8fCAoZGF0YSA9IGRhdGFbMF0sIGRhdGEgPCA1MzAgPyAxIDogZGF0YSA8IDUzMiA/IDIgOiBkYXRhIDwgNTMyLjA1ID8gMyA6IGRhdGEgPCA1MzMgPyA0IDogZGF0YSA8IDUzNC4wMyA/IDUgOiBkYXRhIDwgNTM0LjA3ID8gNiA6IGRhdGEgPCA1MzQuMTAgPyA3IDogZGF0YSA8IDUzNC4xMyA/IDggOiBkYXRhIDwgNTM0LjE2ID8gOSA6IGRhdGEgPCA1MzQuMjQgPyAxMCA6IGRhdGEgPCA1MzQuMzAgPyAxMSA6IGRhdGEgPCA1MzUuMDEgPyAxMiA6IGRhdGEgPCA1MzUuMDIgPyAnMTMrJyA6IGRhdGEgPCA1MzUuMDcgPyAxNSA6IGRhdGEgPCA1MzUuMTEgPyAxNiA6IGRhdGEgPCA1MzUuMTkgPyAxNyA6IGRhdGEgPCA1MzYuMDUgPyAxOCA6IGRhdGEgPCA1MzYuMTAgPyAxOSA6IGRhdGEgPCA1MzcuMDEgPyAyMCA6IGRhdGEgPCA1MzcuMTEgPyAnMjErJyA6IGRhdGEgPCA1MzcuMTMgPyAyMyA6IGRhdGEgPCA1MzcuMTggPyAyNCA6IGRhdGEgPCA1MzcuMjQgPyAyNSA6IGRhdGEgPCA1MzcuMzYgPyAyNiA6IGxheW91dCAhPSAnQmxpbmsnID8gJzI3JyA6ICcyOCcpO1xuICAgICAgfVxuICAgICAgLy8gQWRkIHRoZSBwb3N0Zml4IG9mIFwiLnhcIiBvciBcIitcIiBmb3IgYXBwcm94aW1hdGUgdmVyc2lvbnMuXG4gICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSArPSAnICcgKyAoZGF0YSArPSB0eXBlb2YgZGF0YSA9PSAnbnVtYmVyJyA/ICcueCcgOiAvWy4rXS8udGVzdChkYXRhKSA/ICcnIDogJysnKSk7XG4gICAgICAvLyBPYnNjdXJlIHZlcnNpb24gZm9yIHNvbWUgU2FmYXJpIDEtMiByZWxlYXNlcy5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmICghdmVyc2lvbiB8fCBwYXJzZUludCh2ZXJzaW9uKSA+IDQ1KSkge1xuICAgICAgICB2ZXJzaW9uID0gZGF0YTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGRlc2t0b3AgbW9kZXMuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhJyAmJiAgKGRhdGEgPSAvXFxiemJvdnx6dmF2JC8uZXhlYyhvcykpKSB7XG4gICAgICBuYW1lICs9ICcgJztcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgaWYgKGRhdGEgPT0gJ3p2YXYnKSB7XG4gICAgICAgIG5hbWUgKz0gJ01pbmknO1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5hbWUgKz0gJ01vYmlsZSc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhICsgJyQnKSwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQ2hyb21lIGRlc2t0b3AgbW9kZS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTYWZhcmknICYmIC9cXGJDaHJvbWVcXGIvLmV4ZWMobGF5b3V0ICYmIGxheW91dFsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgbmFtZSA9ICdDaHJvbWUgTW9iaWxlJztcbiAgICAgIHZlcnNpb24gPSBudWxsO1xuXG4gICAgICBpZiAoL1xcYk9TIFhcXGIvLnRlc3Qob3MpKSB7XG4gICAgICAgIG1hbnVmYWN0dXJlciA9ICdBcHBsZSc7XG4gICAgICAgIG9zID0gJ2lPUyA0LjMrJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gU3RyaXAgaW5jb3JyZWN0IE9TIHZlcnNpb25zLlxuICAgIGlmICh2ZXJzaW9uICYmIHZlcnNpb24uaW5kZXhPZigoZGF0YSA9IC9bXFxkLl0rJC8uZXhlYyhvcykpKSA9PSAwICYmXG4gICAgICAgIHVhLmluZGV4T2YoJy8nICsgZGF0YSArICctJykgPiAtMSkge1xuICAgICAgb3MgPSB0cmltKG9zLnJlcGxhY2UoZGF0YSwgJycpKTtcbiAgICB9XG4gICAgLy8gQWRkIGxheW91dCBlbmdpbmUuXG4gICAgaWYgKGxheW91dCAmJiAhL1xcYig/OkF2YW50fE5vb2spXFxiLy50ZXN0KG5hbWUpICYmIChcbiAgICAgICAgL0Jyb3dzZXJ8THVuYXNjYXBlfE1heHRob24vLnRlc3QobmFtZSkgfHxcbiAgICAgICAgbmFtZSAhPSAnU2FmYXJpJyAmJiAvXmlPUy8udGVzdChvcykgJiYgL1xcYlNhZmFyaVxcYi8udGVzdChsYXlvdXRbMV0pIHx8XG4gICAgICAgIC9eKD86QWRvYmV8QXJvcmF8QnJlYWNofE1pZG9yaXxPcGVyYXxQaGFudG9tfFJla29ucXxSb2NrfFNhbXN1bmcgSW50ZXJuZXR8U2xlaXBuaXJ8V2ViKS8udGVzdChuYW1lKSAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICAvLyBEb24ndCBhZGQgbGF5b3V0IGRldGFpbHMgdG8gZGVzY3JpcHRpb24gaWYgdGhleSBhcmUgZmFsc2V5LlxuICAgICAgKGRhdGEgPSBsYXlvdXRbbGF5b3V0Lmxlbmd0aCAtIDFdKSAmJiBkZXNjcmlwdGlvbi5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICAvLyBDb21iaW5lIGNvbnRleHR1YWwgaW5mb3JtYXRpb24uXG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgZGVzY3JpcHRpb24gPSBbJygnICsgZGVzY3JpcHRpb24uam9pbignOyAnKSArICcpJ107XG4gICAgfVxuICAgIC8vIEFwcGVuZCBtYW51ZmFjdHVyZXIgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiBwcm9kdWN0ICYmIHByb2R1Y3QuaW5kZXhPZihtYW51ZmFjdHVyZXIpIDwgMCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnb24gJyArIG1hbnVmYWN0dXJlcik7XG4gICAgfVxuICAgIC8vIEFwcGVuZCBwcm9kdWN0IHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChwcm9kdWN0KSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCgvXm9uIC8udGVzdChkZXNjcmlwdGlvbltkZXNjcmlwdGlvbi5sZW5ndGggLSAxXSkgPyAnJyA6ICdvbiAnKSArIHByb2R1Y3QpO1xuICAgIH1cbiAgICAvLyBQYXJzZSB0aGUgT1MgaW50byBhbiBvYmplY3QuXG4gICAgaWYgKG9zKSB7XG4gICAgICBkYXRhID0gLyAoW1xcZC4rXSspJC8uZXhlYyhvcyk7XG4gICAgICBpc1NwZWNpYWxDYXNlZE9TID0gZGF0YSAmJiBvcy5jaGFyQXQob3MubGVuZ3RoIC0gZGF0YVswXS5sZW5ndGggLSAxKSA9PSAnLyc7XG4gICAgICBvcyA9IHtcbiAgICAgICAgJ2FyY2hpdGVjdHVyZSc6IDMyLFxuICAgICAgICAnZmFtaWx5JzogKGRhdGEgJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gb3MucmVwbGFjZShkYXRhWzBdLCAnJykgOiBvcyxcbiAgICAgICAgJ3ZlcnNpb24nOiBkYXRhID8gZGF0YVsxXSA6IG51bGwsXG4gICAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciB2ZXJzaW9uID0gdGhpcy52ZXJzaW9uO1xuICAgICAgICAgIHJldHVybiB0aGlzLmZhbWlseSArICgodmVyc2lvbiAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyAnICcgKyB2ZXJzaW9uIDogJycpICsgKHRoaXMuYXJjaGl0ZWN0dXJlID09IDY0ID8gJyA2NC1iaXQnIDogJycpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBBZGQgYnJvd3Nlci9PUyBhcmNoaXRlY3R1cmUuXG4gICAgaWYgKChkYXRhID0gL1xcYig/OkFNRHxJQXxXaW58V09XfHg4Nl98eCk2NFxcYi9pLmV4ZWMoYXJjaCkpICYmICEvXFxiaTY4NlxcYi9pLnRlc3QoYXJjaCkpIHtcbiAgICAgIGlmIChvcykge1xuICAgICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICAgICAgb3MuZmFtaWx5ID0gb3MuZmFtaWx5LnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhKSwgJycpO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICAgIG5hbWUgJiYgKC9cXGJXT1c2NFxcYi9pLnRlc3QodWEpIHx8XG4gICAgICAgICAgKHVzZUZlYXR1cmVzICYmIC9cXHcoPzo4NnwzMikkLy50ZXN0KG5hdi5jcHVDbGFzcyB8fCBuYXYucGxhdGZvcm0pICYmICEvXFxiV2luNjQ7IHg2NFxcYi9pLnRlc3QodWEpKSlcbiAgICAgICkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCczMi1iaXQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQ2hyb21lIDM5IGFuZCBhYm92ZSBvbiBPUyBYIGlzIGFsd2F5cyA2NC1iaXQuXG4gICAgZWxzZSBpZiAoXG4gICAgICAgIG9zICYmIC9eT1MgWC8udGVzdChvcy5mYW1pbHkpICYmXG4gICAgICAgIG5hbWUgPT0gJ0Nocm9tZScgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+PSAzOVxuICAgICkge1xuICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgfVxuXG4gICAgdWEgfHwgKHVhID0gbnVsbCk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gb2JqZWN0LlxuICAgICAqXG4gICAgICogQG5hbWUgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICB2YXIgcGxhdGZvcm0gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBkZXNjcmlwdGlvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyJ3MgbGF5b3V0IGVuZ2luZS5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBsYXlvdXQgZW5naW5lcyBpbmNsdWRlOlxuICAgICAqIFwiQmxpbmtcIiwgXCJFZGdlSFRNTFwiLCBcIkdlY2tvXCIsIFwiVHJpZGVudFwiIGFuZCBcIldlYktpdFwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmxheW91dCA9IGxheW91dCAmJiBsYXlvdXRbMF07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCdzIG1hbnVmYWN0dXJlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIG1hbnVmYWN0dXJlcnMgaW5jbHVkZTpcbiAgICAgKiBcIkFwcGxlXCIsIFwiQXJjaG9zXCIsIFwiQW1hem9uXCIsIFwiQXN1c1wiLCBcIkJhcm5lcyAmIE5vYmxlXCIsIFwiQmxhY2tCZXJyeVwiLFxuICAgICAqIFwiR29vZ2xlXCIsIFwiSFBcIiwgXCJIVENcIiwgXCJMR1wiLCBcIk1pY3Jvc29mdFwiLCBcIk1vdG9yb2xhXCIsIFwiTmludGVuZG9cIixcbiAgICAgKiBcIk5va2lhXCIsIFwiU2Ftc3VuZ1wiIGFuZCBcIlNvbnlcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5tYW51ZmFjdHVyZXIgPSBtYW51ZmFjdHVyZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3Nlci9lbnZpcm9ubWVudC5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBicm93c2VyIG5hbWVzIGluY2x1ZGU6XG4gICAgICogXCJDaHJvbWVcIiwgXCJFbGVjdHJvblwiLCBcIkZpcmVmb3hcIiwgXCJGaXJlZm94IGZvciBpT1NcIiwgXCJJRVwiLFxuICAgICAqIFwiTWljcm9zb2Z0IEVkZ2VcIiwgXCJQaGFudG9tSlNcIiwgXCJTYWZhcmlcIiwgXCJTZWFNb25rZXlcIiwgXCJTaWxrXCIsXG4gICAgICogXCJPcGVyYSBNaW5pXCIgYW5kIFwiT3BlcmFcIlxuICAgICAqXG4gICAgICogTW9iaWxlIHZlcnNpb25zIG9mIHNvbWUgYnJvd3NlcnMgaGF2ZSBcIk1vYmlsZVwiIGFwcGVuZGVkIHRvIHRoZWlyIG5hbWU6XG4gICAgICogZWcuIFwiQ2hyb21lIE1vYmlsZVwiLCBcIkZpcmVmb3ggTW9iaWxlXCIsIFwiSUUgTW9iaWxlXCIgYW5kIFwiT3BlcmEgTW9iaWxlXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubmFtZSA9IG5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYWxwaGEvYmV0YSByZWxlYXNlIGluZGljYXRvci5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJlcmVsZWFzZSA9IHByZXJlbGVhc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCBob3N0aW5nIHRoZSBicm93c2VyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIHByb2R1Y3RzIGluY2x1ZGU6XG4gICAgICpcbiAgICAgKiBcIkJsYWNrQmVycnlcIiwgXCJHYWxheHkgUzRcIiwgXCJMdW1pYVwiLCBcImlQYWRcIiwgXCJpUG9kXCIsIFwiaVBob25lXCIsIFwiS2luZGxlXCIsXG4gICAgICogXCJLaW5kbGUgRmlyZVwiLCBcIk5leHVzXCIsIFwiTm9va1wiLCBcIlBsYXlCb29rXCIsIFwiVG91Y2hQYWRcIiBhbmQgXCJUcmFuc2Zvcm1lclwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByb2R1Y3QgPSBwcm9kdWN0O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIncyB1c2VyIGFnZW50IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udWEgPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyL2Vudmlyb25tZW50IHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnZlcnNpb24gPSBuYW1lICYmIHZlcnNpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgb3BlcmF0aW5nIHN5c3RlbS5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm9zID0gb3MgfHwge1xuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlIHRoZSBPUyBpcyBidWlsdCBmb3IuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBudW1iZXJ8bnVsbFxuICAgICAgICovXG4gICAgICAnYXJjaGl0ZWN0dXJlJzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgZmFtaWx5IG9mIHRoZSBPUy5cbiAgICAgICAqXG4gICAgICAgKiBDb21tb24gdmFsdWVzIGluY2x1ZGU6XG4gICAgICAgKiBcIldpbmRvd3NcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IFIyIC8gN1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggLyBWaXN0YVwiLFxuICAgICAgICogXCJXaW5kb3dzIFhQXCIsIFwiT1MgWFwiLCBcIlVidW50dVwiLCBcIkRlYmlhblwiLCBcIkZlZG9yYVwiLCBcIlJlZCBIYXRcIiwgXCJTdVNFXCIsXG4gICAgICAgKiBcIkFuZHJvaWRcIiwgXCJpT1NcIiBhbmQgXCJXaW5kb3dzIFBob25lXCJcbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICAgKi9cbiAgICAgICdmYW1pbHknOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSB2ZXJzaW9uIG9mIHRoZSBPUy5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICAgKi9cbiAgICAgICd2ZXJzaW9uJzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBSZXR1cm5zIHRoZSBPUyBzdHJpbmcuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgT1Mgc3RyaW5nLlxuICAgICAgICovXG4gICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHsgcmV0dXJuICdudWxsJzsgfVxuICAgIH07XG5cbiAgICBwbGF0Zm9ybS5wYXJzZSA9IHBhcnNlO1xuICAgIHBsYXRmb3JtLnRvU3RyaW5nID0gdG9TdHJpbmdQbGF0Zm9ybTtcblxuICAgIGlmIChwbGF0Zm9ybS52ZXJzaW9uKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KHZlcnNpb24pO1xuICAgIH1cbiAgICBpZiAocGxhdGZvcm0ubmFtZSkge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdChuYW1lKTtcbiAgICB9XG4gICAgaWYgKG9zICYmIG5hbWUgJiYgIShvcyA9PSBTdHJpbmcob3MpLnNwbGl0KCcgJylbMF0gJiYgKG9zID09IG5hbWUuc3BsaXQoJyAnKVswXSB8fCBwcm9kdWN0KSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2gocHJvZHVjdCA/ICcoJyArIG9zICsgJyknIDogJ29uICcgKyBvcyk7XG4gICAgfVxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gZGVzY3JpcHRpb24uam9pbignICcpO1xuICAgIH1cbiAgICByZXR1cm4gcGxhdGZvcm07XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvLyBFeHBvcnQgcGxhdGZvcm0uXG4gIHZhciBwbGF0Zm9ybSA9IHBhcnNlKCk7XG5cbiAgLy8gU29tZSBBTUQgYnVpbGQgb3B0aW1pemVycywgbGlrZSByLmpzLCBjaGVjayBmb3IgY29uZGl0aW9uIHBhdHRlcm5zIGxpa2UgdGhlIGZvbGxvd2luZzpcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PSAnb2JqZWN0JyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gRXhwb3NlIHBsYXRmb3JtIG9uIHRoZSBnbG9iYWwgb2JqZWN0IHRvIHByZXZlbnQgZXJyb3JzIHdoZW4gcGxhdGZvcm0gaXNcbiAgICAvLyBsb2FkZWQgYnkgYSBzY3JpcHQgdGFnIGluIHRoZSBwcmVzZW5jZSBvZiBhbiBBTUQgbG9hZGVyLlxuICAgIC8vIFNlZSBodHRwOi8vcmVxdWlyZWpzLm9yZy9kb2NzL2Vycm9ycy5odG1sI21pc21hdGNoIGZvciBtb3JlIGRldGFpbHMuXG4gICAgcm9vdC5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuXG4gICAgLy8gRGVmaW5lIGFzIGFuIGFub255bW91cyBtb2R1bGUgc28gcGxhdGZvcm0gY2FuIGJlIGFsaWFzZWQgdGhyb3VnaCBwYXRoIG1hcHBpbmcuXG4gICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHBsYXRmb3JtO1xuICAgIH0pO1xuICB9XG4gIC8vIENoZWNrIGZvciBgZXhwb3J0c2AgYWZ0ZXIgYGRlZmluZWAgaW4gY2FzZSBhIGJ1aWxkIG9wdGltaXplciBhZGRzIGFuIGBleHBvcnRzYCBvYmplY3QuXG4gIGVsc2UgaWYgKGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUpIHtcbiAgICAvLyBFeHBvcnQgZm9yIENvbW1vbkpTIHN1cHBvcnQuXG4gICAgZm9yT3duKHBsYXRmb3JtLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICBmcmVlRXhwb3J0c1trZXldID0gdmFsdWU7XG4gICAgfSk7XG4gIH1cbiAgZWxzZSB7XG4gICAgLy8gRXhwb3J0IHRvIHRoZSBnbG9iYWwgb2JqZWN0LlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcbiAgfVxufS5jYWxsKHRoaXMpKTtcbiIsInZhciBncmFtbWFyID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIHY6IFt7XG4gICAgICBuYW1lOiAndmVyc2lvbicsXG4gICAgICByZWc6IC9eKFxcZCopJC9cbiAgfV0sXG4gIG86IFt7IC8vbz0tIDIwNTE4IDAgSU4gSVA0IDIwMy4wLjExMy4xXG4gICAgLy8gTkI6IHNlc3Npb25JZCB3aWxsIGJlIGEgU3RyaW5nIGluIG1vc3QgY2FzZXMgYmVjYXVzZSBpdCBpcyBodWdlXG4gICAgbmFtZTogJ29yaWdpbicsXG4gICAgcmVnOiAvXihcXFMqKSAoXFxkKikgKFxcZCopIChcXFMqKSBJUChcXGQpIChcXFMqKS8sXG4gICAgbmFtZXM6IFsndXNlcm5hbWUnLCAnc2Vzc2lvbklkJywgJ3Nlc3Npb25WZXJzaW9uJywgJ25ldFR5cGUnLCAnaXBWZXInLCAnYWRkcmVzcyddLFxuICAgIGZvcm1hdDogXCIlcyAlcyAlZCAlcyBJUCVkICVzXCJcbiAgfV0sXG4gIC8vIGRlZmF1bHQgcGFyc2luZyBvZiB0aGVzZSBvbmx5ICh0aG91Z2ggc29tZSBvZiB0aGVzZSBmZWVsIG91dGRhdGVkKVxuICBzOiBbeyBuYW1lOiAnbmFtZScgfV0sXG4gIGk6IFt7IG5hbWU6ICdkZXNjcmlwdGlvbicgfV0sXG4gIHU6IFt7IG5hbWU6ICd1cmknIH1dLFxuICBlOiBbeyBuYW1lOiAnZW1haWwnIH1dLFxuICBwOiBbeyBuYW1lOiAncGhvbmUnIH1dLFxuICB6OiBbeyBuYW1lOiAndGltZXpvbmVzJyB9XSwgLy8gVE9ETzogdGhpcyBvbmUgY2FuIGFjdHVhbGx5IGJlIHBhcnNlZCBwcm9wZXJseS4uXG4gIHI6IFt7IG5hbWU6ICdyZXBlYXRzJyB9XSwgICAvLyBUT0RPOiB0aGlzIG9uZSBjYW4gYWxzbyBiZSBwYXJzZWQgcHJvcGVybHlcbiAgLy9rOiBbe31dLCAvLyBvdXRkYXRlZCB0aGluZyBpZ25vcmVkXG4gIHQ6IFt7IC8vdD0wIDBcbiAgICBuYW1lOiAndGltaW5nJyxcbiAgICByZWc6IC9eKFxcZCopIChcXGQqKS8sXG4gICAgbmFtZXM6IFsnc3RhcnQnLCAnc3RvcCddLFxuICAgIGZvcm1hdDogXCIlZCAlZFwiXG4gIH1dLFxuICBjOiBbeyAvL2M9SU4gSVA0IDEwLjQ3LjE5Ny4yNlxuICAgICAgbmFtZTogJ2Nvbm5lY3Rpb24nLFxuICAgICAgcmVnOiAvXklOIElQKFxcZCkgKFxcUyopLyxcbiAgICAgIG5hbWVzOiBbJ3ZlcnNpb24nLCAnaXAnXSxcbiAgICAgIGZvcm1hdDogXCJJTiBJUCVkICVzXCJcbiAgfV0sXG4gIGI6IFt7IC8vYj1BUzo0MDAwXG4gICAgICBwdXNoOiAnYmFuZHdpZHRoJyxcbiAgICAgIHJlZzogL14oVElBU3xBU3xDVHxSUnxSUyk6KFxcZCopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbGltaXQnXSxcbiAgICAgIGZvcm1hdDogXCIlczolc1wiXG4gIH1dLFxuICBtOiBbeyAvL209dmlkZW8gNTE3NDQgUlRQL0FWUCAxMjYgOTcgOTggMzQgMzFcbiAgICAgIC8vIE5COiBzcGVjaWFsIC0gcHVzaGVzIHRvIHNlc3Npb25cbiAgICAgIC8vIFRPRE86IHJ0cC9mbXRwIHNob3VsZCBiZSBmaWx0ZXJlZCBieSB0aGUgcGF5bG9hZHMgZm91bmQgaGVyZT9cbiAgICAgIHJlZzogL14oXFx3KikgKFxcZCopIChbXFx3XFwvXSopKD86ICguKikpPy8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ3BvcnQnLCAncHJvdG9jb2wnLCAncGF5bG9hZHMnXSxcbiAgICAgIGZvcm1hdDogXCIlcyAlZCAlcyAlc1wiXG4gIH1dLFxuICBhOiBbXG4gICAgeyAvL2E9cnRwbWFwOjExMCBvcHVzLzQ4MDAwLzJcbiAgICAgIHB1c2g6ICdydHAnLFxuICAgICAgcmVnOiAvXnJ0cG1hcDooXFxkKikgKFtcXHdcXC1dKikoPzpcXHMqXFwvKFxcZCopKD86XFxzKlxcLyhcXFMqKSk/KT8vLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb2RlYycsICdyYXRlJywgJ2VuY29kaW5nJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5lbmNvZGluZykgP1xuICAgICAgICAgIFwicnRwbWFwOiVkICVzLyVzLyVzXCI6XG4gICAgICAgICAgby5yYXRlID9cbiAgICAgICAgICBcInJ0cG1hcDolZCAlcy8lc1wiOlxuICAgICAgICAgIFwicnRwbWFwOiVkICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Zm10cDoxMDggcHJvZmlsZS1sZXZlbC1pZD0yNDtvYmplY3Q9MjM7Yml0cmF0ZT02NDAwMFxuICAgICAgLy9hPWZtdHA6MTExIG1pbnB0aW1lPTEwOyB1c2VpbmJhbmRmZWM9MVxuICAgICAgcHVzaDogJ2ZtdHAnLFxuICAgICAgcmVnOiAvXmZtdHA6KFxcZCopIChbXFxTfCBdKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb25maWcnXSxcbiAgICAgIGZvcm1hdDogXCJmbXRwOiVkICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWNvbnRyb2w6c3RyZWFtaWQ9MFxuICAgICAgICBuYW1lOiAnY29udHJvbCcsXG4gICAgICAgIHJlZzogL15jb250cm9sOiguKikvLFxuICAgICAgICBmb3JtYXQ6IFwiY29udHJvbDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwOjY1MTc5IElOIElQNCAxOTMuODQuNzcuMTk0XG4gICAgICBuYW1lOiAncnRjcCcsXG4gICAgICByZWc6IC9ecnRjcDooXFxkKikoPzogKFxcUyopIElQKFxcZCkgKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsncG9ydCcsICduZXRUeXBlJywgJ2lwVmVyJywgJ2FkZHJlc3MnXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmFkZHJlc3MgIT0gbnVsbCkgP1xuICAgICAgICAgIFwicnRjcDolZCAlcyBJUCVkICVzXCI6XG4gICAgICAgICAgXCJydGNwOiVkXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IHRyci1pbnQgMTAwXG4gICAgICBwdXNoOiAncnRjcEZiVHJySW50JyxcbiAgICAgIHJlZzogL15ydGNwLWZiOihcXCp8XFxkKikgdHJyLWludCAoXFxkKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICd2YWx1ZSddLFxuICAgICAgZm9ybWF0OiBcInJ0Y3AtZmI6JWQgdHJyLWludCAlZFwiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IG5hY2sgcnBzaVxuICAgICAgcHVzaDogJ3J0Y3BGYicsXG4gICAgICByZWc6IC9ecnRjcC1mYjooXFwqfFxcZCopIChbXFx3LV9dKikoPzogKFtcXHctX10qKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAndHlwZScsICdzdWJ0eXBlJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zdWJ0eXBlICE9IG51bGwpID9cbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXNcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPWV4dG1hcDoyIHVybjppZXRmOnBhcmFtczpydHAtaGRyZXh0OnRvZmZzZXRcbiAgICAgIC8vYT1leHRtYXA6MS9yZWN2b25seSBVUkktZ3BzLXN0cmluZ1xuICAgICAgcHVzaDogJ2V4dCcsXG4gICAgICByZWc6IC9eZXh0bWFwOihbXFx3X1xcL10qKSAoXFxTKikoPzogKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsndmFsdWUnLCAndXJpJywgJ2NvbmZpZyddLCAvLyB2YWx1ZSBtYXkgaW5jbHVkZSBcIi9kaXJlY3Rpb25cIiBzdWZmaXhcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmNvbmZpZyAhPSBudWxsKSA/XG4gICAgICAgICAgXCJleHRtYXA6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcImV4dG1hcDolcyAlc1wiO1xuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAgLy9hPWNyeXB0bzoxIEFFU19DTV8xMjhfSE1BQ19TSEExXzgwIGlubGluZTpQUzF1UUNWZWVDRkNhblZtY2prcFB5d2pOV2hjWUQwbVhYdHhhVkJSfDJeMjB8MTozMlxuICAgICAgcHVzaDogJ2NyeXB0bycsXG4gICAgICByZWc6IC9eY3J5cHRvOihcXGQqKSAoW1xcd19dKikgKFxcUyopKD86IChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2lkJywgJ3N1aXRlJywgJ2NvbmZpZycsICdzZXNzaW9uQ29uZmlnJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zZXNzaW9uQ29uZmlnICE9IG51bGwpID9cbiAgICAgICAgICBcImNyeXB0bzolZCAlcyAlcyAlc1wiOlxuICAgICAgICAgIFwiY3J5cHRvOiVkICVzICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1zZXR1cDphY3RwYXNzXG4gICAgICBuYW1lOiAnc2V0dXAnLFxuICAgICAgcmVnOiAvXnNldHVwOihcXHcqKS8sXG4gICAgICBmb3JtYXQ6IFwic2V0dXA6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9bWlkOjFcbiAgICAgIG5hbWU6ICdtaWQnLFxuICAgICAgcmVnOiAvXm1pZDooW15cXHNdKikvLFxuICAgICAgZm9ybWF0OiBcIm1pZDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkOjBjOGIwNjRkLWQ4MDctNDNiNC1iNDM0LWY5MmE4ODlkODU4NyA5ODE3ODY4NS1kNDA5LTQ2ZTAtOGUxNi03ZWYwZGIwZGI2NGFcbiAgICAgIG5hbWU6ICdtc2lkJyxcbiAgICAgIHJlZzogL15tc2lkOiguKikvLFxuICAgICAgZm9ybWF0OiBcIm1zaWQ6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9cHRpbWU6MjBcbiAgICAgIG5hbWU6ICdwdGltZScsXG4gICAgICByZWc6IC9ecHRpbWU6KFxcZCopLyxcbiAgICAgIGZvcm1hdDogXCJwdGltZTolZFwiXG4gICAgfSxcbiAgICB7IC8vYT1tYXhwdGltZTo2MFxuICAgICAgbmFtZTogJ21heHB0aW1lJyxcbiAgICAgIHJlZzogL15tYXhwdGltZTooXFxkKikvLFxuICAgICAgZm9ybWF0OiBcIm1heHB0aW1lOiVkXCJcbiAgICB9LFxuICAgIHsgLy9hPXNlbmRyZWN2XG4gICAgICBuYW1lOiAnZGlyZWN0aW9uJyxcbiAgICAgIHJlZzogL14oc2VuZHJlY3Z8cmVjdm9ubHl8c2VuZG9ubHl8aW5hY3RpdmUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLWxpdGVcbiAgICAgIG5hbWU6ICdpY2VsaXRlJyxcbiAgICAgIHJlZzogL14oaWNlLWxpdGUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLXVmcmFnOkY3Z0lcbiAgICAgIG5hbWU6ICdpY2VVZnJhZycsXG4gICAgICByZWc6IC9eaWNlLXVmcmFnOihcXFMqKS8sXG4gICAgICBmb3JtYXQ6IFwiaWNlLXVmcmFnOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1wd2Q6eDljbWwvWXppY2hWMitYbGhpTXU4Z1xuICAgICAgbmFtZTogJ2ljZVB3ZCcsXG4gICAgICByZWc6IC9eaWNlLXB3ZDooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1wd2Q6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9ZmluZ2VycHJpbnQ6U0hBLTEgMDA6MTE6MjI6MzM6NDQ6NTU6NjY6Nzc6ODg6OTk6QUE6QkI6Q0M6REQ6RUU6RkY6MDA6MTE6MjI6MzNcbiAgICAgIG5hbWU6ICdmaW5nZXJwcmludCcsXG4gICAgICByZWc6IC9eZmluZ2VycHJpbnQ6KFxcUyopIChcXFMqKS8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ2hhc2gnXSxcbiAgICAgIGZvcm1hdDogXCJmaW5nZXJwcmludDolcyAlc1wiXG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Y2FuZGlkYXRlOjAgMSBVRFAgMjExMzY2NzMyNyAyMDMuMC4xMTMuMSA1NDQwMCB0eXAgaG9zdFxuICAgICAgLy9hPWNhbmRpZGF0ZToxMTYyODc1MDgxIDEgdWRwIDIxMTM5MzcxNTEgMTkyLjE2OC4zNC43NSA2MDAxNyB0eXAgaG9zdCBnZW5lcmF0aW9uIDBcbiAgICAgIC8vYT1jYW5kaWRhdGU6MzI4OTkxMjk1NyAyIHVkcCAxODQ1NTAxNjk1IDE5My44NC43Ny4xOTQgNjAwMTcgdHlwIHNyZmx4IHJhZGRyIDE5Mi4xNjguMzQuNzUgcnBvcnQgNjAwMTcgZ2VuZXJhdGlvbiAwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjIyOTgxNTYyMCAxIHRjcCAxNTE4MjgwNDQ3IDE5Mi4xNjguMTUwLjE5IDYwMDE3IHR5cCBob3N0IHRjcHR5cGUgYWN0aXZlIGdlbmVyYXRpb24gMFxuICAgICAgLy9hPWNhbmRpZGF0ZTozMjg5OTEyOTU3IDIgdGNwIDE4NDU1MDE2OTUgMTkzLjg0Ljc3LjE5NCA2MDAxNyB0eXAgc3JmbHggcmFkZHIgMTkyLjE2OC4zNC43NSBycG9ydCA2MDAxNyB0Y3B0eXBlIHBhc3NpdmUgZ2VuZXJhdGlvbiAwXG4gICAgICBwdXNoOidjYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL15jYW5kaWRhdGU6KFxcUyopIChcXGQqKSAoXFxTKikgKFxcZCopIChcXFMqKSAoXFxkKikgdHlwIChcXFMqKSg/OiByYWRkciAoXFxTKikgcnBvcnQgKFxcZCopKT8oPzogdGNwdHlwZSAoXFxTKikpPyg/OiBnZW5lcmF0aW9uIChcXGQqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2ZvdW5kYXRpb24nLCAnY29tcG9uZW50JywgJ3RyYW5zcG9ydCcsICdwcmlvcml0eScsICdpcCcsICdwb3J0JywgJ3R5cGUnLCAncmFkZHInLCAncnBvcnQnLCAndGNwdHlwZScsICdnZW5lcmF0aW9uJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHZhciBzdHIgPSBcImNhbmRpZGF0ZTolcyAlZCAlcyAlZCAlcyAlZCB0eXAgJXNcIjtcblxuICAgICAgICBzdHIgKz0gKG8ucmFkZHIgIT0gbnVsbCkgPyBcIiByYWRkciAlcyBycG9ydCAlZFwiIDogXCIldiV2XCI7XG5cbiAgICAgICAgLy8gTkI6IGNhbmRpZGF0ZSBoYXMgdGhyZWUgb3B0aW9uYWwgY2h1bmtzLCBzbyAldm9pZCBtaWRkbGVzIG9uZSBpZiBpdCdzIG1pc3NpbmdcbiAgICAgICAgc3RyICs9IChvLnRjcHR5cGUgIT0gbnVsbCkgPyBcIiB0Y3B0eXBlICVzXCIgOiBcIiV2XCI7XG5cbiAgICAgICAgaWYgKG8uZ2VuZXJhdGlvbiAhPSBudWxsKSB7XG4gICAgICAgICAgc3RyICs9IFwiIGdlbmVyYXRpb24gJWRcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9ZW5kLW9mLWNhbmRpZGF0ZXMgKGtlZXAgYWZ0ZXIgdGhlIGNhbmRpZGF0ZXMgbGluZSBmb3IgcmVhZGFiaWxpdHkpXG4gICAgICBuYW1lOiAnZW5kT2ZDYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL14oZW5kLW9mLWNhbmRpZGF0ZXMpL1xuICAgIH0sXG4gICAgeyAvL2E9cmVtb3RlLWNhbmRpZGF0ZXM6MSAyMDMuMC4xMTMuMSA1NDQwMCAyIDIwMy4wLjExMy4xIDU0NDAxIC4uLlxuICAgICAgbmFtZTogJ3JlbW90ZUNhbmRpZGF0ZXMnLFxuICAgICAgcmVnOiAvXnJlbW90ZS1jYW5kaWRhdGVzOiguKikvLFxuICAgICAgZm9ybWF0OiBcInJlbW90ZS1jYW5kaWRhdGVzOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1vcHRpb25zOmdvb2dsZS1pY2VcbiAgICAgIG5hbWU6ICdpY2VPcHRpb25zJyxcbiAgICAgIHJlZzogL15pY2Utb3B0aW9uczooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1vcHRpb25zOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXNzcmM6MjU2NjEwNzU2OSBjbmFtZTp0OVlVOE0xVXhURjhZMUExXG4gICAgICBwdXNoOiBcInNzcmNzXCIsXG4gICAgICByZWc6IC9ec3NyYzooXFxkKikgKFtcXHdfXSopOiguKikvLFxuICAgICAgbmFtZXM6IFsnaWQnLCAnYXR0cmlidXRlJywgJ3ZhbHVlJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYzolZCAlczolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1zc3JjLWdyb3VwOkZFQyAxIDJcbiAgICAgIHB1c2g6IFwic3NyY0dyb3Vwc1wiLFxuICAgICAgcmVnOiAvXnNzcmMtZ3JvdXA6KFxcdyopICguKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWNzJywgJ3NzcmNzJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYy1ncm91cDolcyAlc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkLXNlbWFudGljOiBXTVMgSnZsYW01WDNTWDFPUDZwbjIweldvZ3ZhS0p6NUhqZjlPbmxWXG4gICAgICBuYW1lOiBcIm1zaWRTZW1hbnRpY1wiLFxuICAgICAgcmVnOiAvXm1zaWQtc2VtYW50aWM6XFxzPyhcXHcqKSAoXFxTKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWMnLCAndG9rZW4nXSxcbiAgICAgIGZvcm1hdDogXCJtc2lkLXNlbWFudGljOiAlcyAlc1wiIC8vIHNwYWNlIGFmdGVyIFwiOlwiIGlzIG5vdCBhY2NpZGVudGFsXG4gICAgfSxcbiAgICB7IC8vYT1ncm91cDpCVU5ETEUgYXVkaW8gdmlkZW9cbiAgICAgIHB1c2g6ICdncm91cHMnLFxuICAgICAgcmVnOiAvXmdyb3VwOihcXHcqKSAoLiopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbWlkcyddLFxuICAgICAgZm9ybWF0OiBcImdyb3VwOiVzICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtbXV4XG4gICAgICBuYW1lOiAncnRjcE11eCcsXG4gICAgICByZWc6IC9eKHJ0Y3AtbXV4KS9cbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtcnNpemVcbiAgICAgIG5hbWU6ICdydGNwUnNpemUnLFxuICAgICAgcmVnOiAvXihydGNwLXJzaXplKS9cbiAgICB9LFxuICAgIHsgLy8gYW55IGE9IHRoYXQgd2UgZG9uJ3QgdW5kZXJzdGFuZCBpcyBrZXB0cyB2ZXJiYXRpbSBvbiBtZWRpYS5pbnZhbGlkXG4gICAgICBwdXNoOiAnaW52YWxpZCcsXG4gICAgICBuYW1lczogW1widmFsdWVcIl1cbiAgICB9XG4gIF1cbn07XG5cbi8vIHNldCBzZW5zaWJsZSBkZWZhdWx0cyB0byBhdm9pZCBwb2xsdXRpbmcgdGhlIGdyYW1tYXIgd2l0aCBib3JpbmcgZGV0YWlsc1xuT2JqZWN0LmtleXMoZ3JhbW1hcikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gIHZhciBvYmpzID0gZ3JhbW1hcltrZXldO1xuICBvYmpzLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgIGlmICghb2JqLnJlZykge1xuICAgICAgb2JqLnJlZyA9IC8oLiopLztcbiAgICB9XG4gICAgaWYgKCFvYmouZm9ybWF0KSB7XG4gICAgICBvYmouZm9ybWF0ID0gXCIlc1wiO1xuICAgIH1cbiAgfSk7XG59KTtcbiIsInZhciBwYXJzZXIgPSByZXF1aXJlKCcuL3BhcnNlcicpO1xudmFyIHdyaXRlciA9IHJlcXVpcmUoJy4vd3JpdGVyJyk7XG5cbmV4cG9ydHMud3JpdGUgPSB3cml0ZXI7XG5leHBvcnRzLnBhcnNlID0gcGFyc2VyLnBhcnNlO1xuZXhwb3J0cy5wYXJzZUZtdHBDb25maWcgPSBwYXJzZXIucGFyc2VGbXRwQ29uZmlnO1xuZXhwb3J0cy5wYXJzZVBheWxvYWRzID0gcGFyc2VyLnBhcnNlUGF5bG9hZHM7XG5leHBvcnRzLnBhcnNlUmVtb3RlQ2FuZGlkYXRlcyA9IHBhcnNlci5wYXJzZVJlbW90ZUNhbmRpZGF0ZXM7XG4iLCJ2YXIgdG9JbnRJZkludCA9IGZ1bmN0aW9uICh2KSB7XG4gIHJldHVybiBTdHJpbmcoTnVtYmVyKHYpKSA9PT0gdiA/IE51bWJlcih2KSA6IHY7XG59O1xuXG52YXIgYXR0YWNoUHJvcGVydGllcyA9IGZ1bmN0aW9uIChtYXRjaCwgbG9jYXRpb24sIG5hbWVzLCByYXdOYW1lKSB7XG4gIGlmIChyYXdOYW1lICYmICFuYW1lcykge1xuICAgIGxvY2F0aW9uW3Jhd05hbWVdID0gdG9JbnRJZkludChtYXRjaFsxXSk7XG4gIH1cbiAgZWxzZSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgaWYgKG1hdGNoW2krMV0gIT0gbnVsbCkge1xuICAgICAgICBsb2NhdGlvbltuYW1lc1tpXV0gPSB0b0ludElmSW50KG1hdGNoW2krMV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxudmFyIHBhcnNlUmVnID0gZnVuY3Rpb24gKG9iaiwgbG9jYXRpb24sIGNvbnRlbnQpIHtcbiAgdmFyIG5lZWRzQmxhbmsgPSBvYmoubmFtZSAmJiBvYmoubmFtZXM7XG4gIGlmIChvYmoucHVzaCAmJiAhbG9jYXRpb25bb2JqLnB1c2hdKSB7XG4gICAgbG9jYXRpb25bb2JqLnB1c2hdID0gW107XG4gIH1cbiAgZWxzZSBpZiAobmVlZHNCbGFuayAmJiAhbG9jYXRpb25bb2JqLm5hbWVdKSB7XG4gICAgbG9jYXRpb25bb2JqLm5hbWVdID0ge307XG4gIH1cbiAgdmFyIGtleUxvY2F0aW9uID0gb2JqLnB1c2ggP1xuICAgIHt9IDogIC8vIGJsYW5rIG9iamVjdCB0aGF0IHdpbGwgYmUgcHVzaGVkXG4gICAgbmVlZHNCbGFuayA/IGxvY2F0aW9uW29iai5uYW1lXSA6IGxvY2F0aW9uOyAvLyBvdGhlcndpc2UsIG5hbWVkIGxvY2F0aW9uIG9yIHJvb3RcblxuICBhdHRhY2hQcm9wZXJ0aWVzKGNvbnRlbnQubWF0Y2gob2JqLnJlZyksIGtleUxvY2F0aW9uLCBvYmoubmFtZXMsIG9iai5uYW1lKTtcblxuICBpZiAob2JqLnB1c2gpIHtcbiAgICBsb2NhdGlvbltvYmoucHVzaF0ucHVzaChrZXlMb2NhdGlvbik7XG4gIH1cbn07XG5cbnZhciBncmFtbWFyID0gcmVxdWlyZSgnLi9ncmFtbWFyJyk7XG52YXIgdmFsaWRMaW5lID0gUmVnRXhwLnByb3RvdHlwZS50ZXN0LmJpbmQoL14oW2Etel0pPSguKikvKTtcblxuZXhwb3J0cy5wYXJzZSA9IGZ1bmN0aW9uIChzZHApIHtcbiAgdmFyIHNlc3Npb24gPSB7fVxuICAgICwgbWVkaWEgPSBbXVxuICAgICwgbG9jYXRpb24gPSBzZXNzaW9uOyAvLyBwb2ludHMgYXQgd2hlcmUgcHJvcGVydGllcyBnbyB1bmRlciAob25lIG9mIHRoZSBhYm92ZSlcblxuICAvLyBwYXJzZSBsaW5lcyB3ZSB1bmRlcnN0YW5kXG4gIHNkcC5zcGxpdCgvKFxcclxcbnxcXHJ8XFxuKS8pLmZpbHRlcih2YWxpZExpbmUpLmZvckVhY2goZnVuY3Rpb24gKGwpIHtcbiAgICB2YXIgdHlwZSA9IGxbMF07XG4gICAgdmFyIGNvbnRlbnQgPSBsLnNsaWNlKDIpO1xuICAgIGlmICh0eXBlID09PSAnbScpIHtcbiAgICAgIG1lZGlhLnB1c2goe3J0cDogW10sIGZtdHA6IFtdfSk7XG4gICAgICBsb2NhdGlvbiA9IG1lZGlhW21lZGlhLmxlbmd0aC0xXTsgLy8gcG9pbnQgYXQgbGF0ZXN0IG1lZGlhIGxpbmVcbiAgICB9XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IChncmFtbWFyW3R5cGVdIHx8IFtdKS5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgdmFyIG9iaiA9IGdyYW1tYXJbdHlwZV1bal07XG4gICAgICBpZiAob2JqLnJlZy50ZXN0KGNvbnRlbnQpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVJlZyhvYmosIGxvY2F0aW9uLCBjb250ZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHNlc3Npb24ubWVkaWEgPSBtZWRpYTsgLy8gbGluayBpdCB1cFxuICByZXR1cm4gc2Vzc2lvbjtcbn07XG5cbnZhciBmbXRwUmVkdWNlciA9IGZ1bmN0aW9uIChhY2MsIGV4cHIpIHtcbiAgdmFyIHMgPSBleHByLnNwbGl0KCc9Jyk7XG4gIGlmIChzLmxlbmd0aCA9PT0gMikge1xuICAgIGFjY1tzWzBdXSA9IHRvSW50SWZJbnQoc1sxXSk7XG4gIH1cbiAgcmV0dXJuIGFjYztcbn07XG5cbmV4cG9ydHMucGFyc2VGbXRwQ29uZmlnID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KC9cXDtcXHM/LykucmVkdWNlKGZtdHBSZWR1Y2VyLCB7fSk7XG59O1xuXG5leHBvcnRzLnBhcnNlUGF5bG9hZHMgPSBmdW5jdGlvbiAoc3RyKSB7XG4gIHJldHVybiBzdHIuc3BsaXQoJyAnKS5tYXAoTnVtYmVyKTtcbn07XG5cbmV4cG9ydHMucGFyc2VSZW1vdGVDYW5kaWRhdGVzID0gZnVuY3Rpb24gKHN0cikge1xuICB2YXIgY2FuZGlkYXRlcyA9IFtdO1xuICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoJyAnKS5tYXAodG9JbnRJZkludCk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpICs9IDMpIHtcbiAgICBjYW5kaWRhdGVzLnB1c2goe1xuICAgICAgY29tcG9uZW50OiBwYXJ0c1tpXSxcbiAgICAgIGlwOiBwYXJ0c1tpICsgMV0sXG4gICAgICBwb3J0OiBwYXJ0c1tpICsgMl1cbiAgICB9KTtcbiAgfVxuICByZXR1cm4gY2FuZGlkYXRlcztcbn07XG4iLCJ2YXIgZ3JhbW1hciA9IHJlcXVpcmUoJy4vZ3JhbW1hcicpO1xuXG4vLyBjdXN0b21pemVkIHV0aWwuZm9ybWF0IC0gZGlzY2FyZHMgZXhjZXNzIGFyZ3VtZW50cyBhbmQgY2FuIHZvaWQgbWlkZGxlIG9uZXNcbnZhciBmb3JtYXRSZWdFeHAgPSAvJVtzZHYlXS9nO1xudmFyIGZvcm1hdCA9IGZ1bmN0aW9uIChmb3JtYXRTdHIpIHtcbiAgdmFyIGkgPSAxO1xuICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgdmFyIGxlbiA9IGFyZ3MubGVuZ3RoO1xuICByZXR1cm4gZm9ybWF0U3RyLnJlcGxhY2UoZm9ybWF0UmVnRXhwLCBmdW5jdGlvbiAoeCkge1xuICAgIGlmIChpID49IGxlbikge1xuICAgICAgcmV0dXJuIHg7IC8vIG1pc3NpbmcgYXJndW1lbnRcbiAgICB9XG4gICAgdmFyIGFyZyA9IGFyZ3NbaV07XG4gICAgaSArPSAxO1xuICAgIHN3aXRjaCAoeCkge1xuICAgICAgY2FzZSAnJSUnOlxuICAgICAgICByZXR1cm4gJyUnO1xuICAgICAgY2FzZSAnJXMnOlxuICAgICAgICByZXR1cm4gU3RyaW5nKGFyZyk7XG4gICAgICBjYXNlICclZCc6XG4gICAgICAgIHJldHVybiBOdW1iZXIoYXJnKTtcbiAgICAgIGNhc2UgJyV2JzpcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfSk7XG4gIC8vIE5COiB3ZSBkaXNjYXJkIGV4Y2VzcyBhcmd1bWVudHMgLSB0aGV5IGFyZSB0eXBpY2FsbHkgdW5kZWZpbmVkIGZyb20gbWFrZUxpbmVcbn07XG5cbnZhciBtYWtlTGluZSA9IGZ1bmN0aW9uICh0eXBlLCBvYmosIGxvY2F0aW9uKSB7XG4gIHZhciBzdHIgPSBvYmouZm9ybWF0IGluc3RhbmNlb2YgRnVuY3Rpb24gP1xuICAgIChvYmouZm9ybWF0KG9iai5wdXNoID8gbG9jYXRpb24gOiBsb2NhdGlvbltvYmoubmFtZV0pKSA6XG4gICAgb2JqLmZvcm1hdDtcblxuICB2YXIgYXJncyA9IFt0eXBlICsgJz0nICsgc3RyXTtcbiAgaWYgKG9iai5uYW1lcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqLm5hbWVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICB2YXIgbiA9IG9iai5uYW1lc1tpXTtcbiAgICAgIGlmIChvYmoubmFtZSkge1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVdW25dKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgeyAvLyBmb3IgbUxpbmUgYW5kIHB1c2ggYXR0cmlidXRlc1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVzW2ldXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIGFyZ3MucHVzaChsb2NhdGlvbltvYmoubmFtZV0pO1xuICB9XG4gIHJldHVybiBmb3JtYXQuYXBwbHkobnVsbCwgYXJncyk7XG59O1xuXG4vLyBSRkMgc3BlY2lmaWVkIG9yZGVyXG4vLyBUT0RPOiBleHRlbmQgdGhpcyB3aXRoIGFsbCB0aGUgcmVzdFxudmFyIGRlZmF1bHRPdXRlck9yZGVyID0gW1xuICAndicsICdvJywgJ3MnLCAnaScsXG4gICd1JywgJ2UnLCAncCcsICdjJyxcbiAgJ2InLCAndCcsICdyJywgJ3onLCAnYSdcbl07XG52YXIgZGVmYXVsdElubmVyT3JkZXIgPSBbJ2knLCAnYycsICdiJywgJ2EnXTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzZXNzaW9uLCBvcHRzKSB7XG4gIG9wdHMgPSBvcHRzIHx8IHt9O1xuICAvLyBlbnN1cmUgY2VydGFpbiBwcm9wZXJ0aWVzIGV4aXN0XG4gIGlmIChzZXNzaW9uLnZlcnNpb24gPT0gbnVsbCkge1xuICAgIHNlc3Npb24udmVyc2lvbiA9IDA7IC8vIFwidj0wXCIgbXVzdCBiZSB0aGVyZSAob25seSBkZWZpbmVkIHZlcnNpb24gYXRtKVxuICB9XG4gIGlmIChzZXNzaW9uLm5hbWUgPT0gbnVsbCkge1xuICAgIHNlc3Npb24ubmFtZSA9IFwiIFwiOyAvLyBcInM9IFwiIG11c3QgYmUgdGhlcmUgaWYgbm8gbWVhbmluZ2Z1bCBuYW1lIHNldFxuICB9XG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBpZiAobUxpbmUucGF5bG9hZHMgPT0gbnVsbCkge1xuICAgICAgbUxpbmUucGF5bG9hZHMgPSBcIlwiO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIG91dGVyT3JkZXIgPSBvcHRzLm91dGVyT3JkZXIgfHwgZGVmYXVsdE91dGVyT3JkZXI7XG4gIHZhciBpbm5lck9yZGVyID0gb3B0cy5pbm5lck9yZGVyIHx8IGRlZmF1bHRJbm5lck9yZGVyO1xuICB2YXIgc2RwID0gW107XG5cbiAgLy8gbG9vcCB0aHJvdWdoIG91dGVyT3JkZXIgZm9yIG1hdGNoaW5nIHByb3BlcnRpZXMgb24gc2Vzc2lvblxuICBvdXRlck9yZGVyLmZvckVhY2goZnVuY3Rpb24gKHR5cGUpIHtcbiAgICBncmFtbWFyW3R5cGVdLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgICAgaWYgKG9iai5uYW1lIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoubmFtZV0gIT0gbnVsbCkge1xuICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIHNlc3Npb24pKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoucHVzaF0gIT0gbnVsbCkge1xuICAgICAgICBzZXNzaW9uW29iai5wdXNoXS5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIHNkcC5wdXNoKG1ha2VMaW5lKHR5cGUsIG9iaiwgZWwpKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIHRoZW4gZm9yIGVhY2ggbWVkaWEgbGluZSwgZm9sbG93IHRoZSBpbm5lck9yZGVyXG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBzZHAucHVzaChtYWtlTGluZSgnbScsIGdyYW1tYXIubVswXSwgbUxpbmUpKTtcblxuICAgIGlubmVyT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAodHlwZSkge1xuICAgICAgZ3JhbW1hclt0eXBlXS5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgaWYgKG9iai5uYW1lIGluIG1MaW5lICYmIG1MaW5lW29iai5uYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBtTGluZSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIG1MaW5lICYmIG1MaW5lW29iai5wdXNoXSAhPSBudWxsKSB7XG4gICAgICAgICAgbUxpbmVbb2JqLnB1c2hdLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIGVsKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gc2RwLmpvaW4oJ1xcclxcbicpICsgJ1xcclxcbic7XG59O1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGFycmF5RXF1YWxzKGFycmF5KSB7XG4gICAgLy8gaWYgdGhlIG90aGVyIGFycmF5IGlzIGEgZmFsc3kgdmFsdWUsIHJldHVyblxuICAgIGlmICghYXJyYXkpXG4gICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgIC8vIGNvbXBhcmUgbGVuZ3RocyAtIGNhbiBzYXZlIGEgbG90IG9mIHRpbWVcbiAgICBpZiAodGhpcy5sZW5ndGggIT0gYXJyYXkubGVuZ3RoKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgbmVzdGVkIGFycmF5c1xuICAgICAgICBpZiAodGhpc1tpXSBpbnN0YW5jZW9mIEFycmF5ICYmIGFycmF5W2ldIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIHJlY3Vyc2UgaW50byB0aGUgbmVzdGVkIGFycmF5c1xuICAgICAgICAgICAgaWYgKCFhcnJheUVxdWFscy5hcHBseSh0aGlzW2ldLCBbYXJyYXlbaV1dKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpc1tpXSAhPSBhcnJheVtpXSkge1xuICAgICAgICAgICAgLy8gV2FybmluZyAtIHR3byBkaWZmZXJlbnQgb2JqZWN0IGluc3RhbmNlcyB3aWxsIG5ldmVyIGJlIGVxdWFsOlxuICAgICAgICAgICAgLy8ge3g6MjB9ICE9IHt4OjIwfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufTtcblxuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnRzLkludGVyb3AgPSByZXF1aXJlKCcuL2ludGVyb3AnKTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyogZ2xvYmFsIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbiAqL1xuLyogZ2xvYmFsIFJUQ0ljZUNhbmRpZGF0ZSAqL1xuLyoganNoaW50IC1XMDk3ICovXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIHRyYW5zZm9ybSA9IHJlcXVpcmUoJy4vdHJhbnNmb3JtJyk7XG52YXIgYXJyYXlFcXVhbHMgPSByZXF1aXJlKCcuL2FycmF5LWVxdWFscycpO1xuXG5mdW5jdGlvbiBJbnRlcm9wKCkge1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtYXAgaG9sZHMgdGhlIG1vc3QgcmVjZW50IFVuaWZpZWQgUGxhbiBvZmZlci9hbnN3ZXIgU0RQIHRoYXQgd2FzXG4gICAgICogY29udmVydGVkIHRvIFBsYW4gQiwgd2l0aCB0aGUgU0RQIHR5cGUgKCdvZmZlcicgb3IgJ2Fuc3dlcicpIGFzIGtleXMgYW5kXG4gICAgICogdGhlIFNEUCBzdHJpbmcgYXMgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHR5cGUge3t9fVxuICAgICAqL1xuICAgIHRoaXMuY2FjaGUgPSB7XG4gICAgICAgIG1sQjJVTWFwIDoge30sXG4gICAgICAgIG1sVTJCTWFwIDoge31cbiAgICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEludGVyb3A7XG5cbi8qKlxuICogQ2hhbmdlcyB0aGUgY2FuZGlkYXRlIGFyZ3MgdG8gbWF0Y2ggd2l0aCB0aGUgcmVsYXRlZCBVbmlmaWVkIFBsYW5cbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuY2FuZGlkYXRlVG9VbmlmaWVkUGxhbiA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHZhciBjYW5kID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuXG4gICAgY2FuZC5zZHBNTGluZUluZGV4ID0gdGhpcy5jYWNoZS5tbEIyVU1hcFtjYW5kLnNkcE1MaW5lSW5kZXhdO1xuICAgIC8qIFRPRE86IGNoYW5nZSBzZHBNaWQgdG8gKGF1ZGlvfHZpZGVvKS1TU1JDICovXG5cbiAgICByZXR1cm4gY2FuZDtcbn07XG5cbi8qKlxuICogQ2hhbmdlcyB0aGUgY2FuZGlkYXRlIGFyZ3MgdG8gbWF0Y2ggd2l0aCB0aGUgcmVsYXRlZCBQbGFuIEJcbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuY2FuZGlkYXRlVG9QbGFuQiA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHZhciBjYW5kID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuXG4gICAgaWYgKGNhbmQuc2RwTWlkLmluZGV4T2YoJ2F1ZGlvJykgPT09IDApIHtcbiAgICAgIGNhbmQuc2RwTWlkID0gJ2F1ZGlvJztcbiAgICB9IGVsc2UgaWYgKGNhbmQuc2RwTWlkLmluZGV4T2YoJ3ZpZGVvJykgPT09IDApIHtcbiAgICAgIGNhbmQuc2RwTWlkID0gJ3ZpZGVvJztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5kaWRhdGUgd2l0aCAnICsgY2FuZC5zZHBNaWQgKyAnIG5vdCBhbGxvd2VkJyk7XG4gICAgfVxuXG4gICAgY2FuZC5zZHBNTGluZUluZGV4ID0gdGhpcy5jYWNoZS5tbFUyQk1hcFtjYW5kLnNkcE1MaW5lSW5kZXhdO1xuXG4gICAgcmV0dXJuIGNhbmQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBtLWxpbmUgd2l0aCB0aGUgZ2l2ZW4gbWVkaWEgdHlwZSBhbmQgd2l0aCBhXG4gKiBkaXJlY3Rpb24gd2hpY2ggYWxsb3dzIHNlbmRpbmcsIGluIHRoZSBsYXN0IFVuaWZpZWQgUGxhbiBkZXNjcmlwdGlvbiB3aXRoXG4gKiB0eXBlIFwiYW5zd2VyXCIgY29udmVydGVkIHRvIFBsYW4gQi4gUmV0dXJucyB7bnVsbH0gaWYgdGhlcmUgaXMgbm8gc2F2ZWRcbiAqIGFuc3dlciwgb3IgaWYgbm9uZSBvZiBpdHMgbS1saW5lcyB3aXRoIHRoZSBnaXZlbiB0eXBlIGFsbG93IHNlbmRpbmcuXG4gKiBAcGFyYW0gdHlwZSB0aGUgbWVkaWEgdHlwZSAoXCJhdWRpb1wiIG9yIFwidmlkZW9cIikuXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyID0gZnVuY3Rpb24odHlwZSkge1xuICAgIGlmICghdGhpcy5jYWNoZS5hbnN3ZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UodGhpcy5jYWNoZS5hbnN3ZXIpO1xuICAgIGlmIChzZXNzaW9uICYmIHNlc3Npb24ubWVkaWEgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSl7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vzc2lvbi5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHNlc3Npb24ubWVkaWFbaV0udHlwZSA9PSB0eXBlICYmXG4gICAgICAgICAgICAgICAgKCFzZXNzaW9uLm1lZGlhW2ldLmRpcmVjdGlvbiAvKiBkZWZhdWx0IHRvIHNlbmRyZWN2ICovIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn07XG5cbi8qKlxuICogVGhpcyBtZXRob2QgdHJhbnNmb3JtcyBhIFVuaWZpZWQgUGxhbiBTRFAgdG8gYW4gZXF1aXZhbGVudCBQbGFuIEIgU0RQLiBBXG4gKiBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIHRyYW5zZm9ybXMgdGhlIFNEUCB0byBQbGFuIEIgYmVmb3JlIHBhc3NpbmcgaXQgdG8gdGhlXG4gKiBhcHBsaWNhdGlvbi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvUGxhbkIgPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBPYmplY3RpZnkgdGhlIFNEUCBmb3IgZWFzaWVyIG1hbmlwdWxhdGlvbi5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFVuaWZpZWQgUGxhbiBTRFAuIFBsYW4gQlxuICAgIC8vIFNEUCBoYXMgYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA8PSAzICYmIHNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBVbmlmaWVkIFBsYW4uJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vI2VuZHJlZ2lvblxuXG4gICAgLy8gSEFDSyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMTEzNDQzXG4gICAgdmFyIHNkcCA9IGRlc2Muc2RwO1xuICAgIHZhciByZXdyaXRlID0gZmFsc2U7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB1TGluZSA9IHNlc3Npb24ubWVkaWFbaV07XG4gICAgICAgIHVMaW5lLnJ0cC5mb3JFYWNoKGZ1bmN0aW9uKHJ0cCkge1xuICAgICAgICAgICAgaWYgKHJ0cC5jb2RlYyA9PT0gJ05VTEwnKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHJld3JpdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBvZmZlciA9IHRyYW5zZm9ybS5wYXJzZShzZWxmLmNhY2hlLm9mZmVyKTtcbiAgICAgICAgICAgICAgICBydHAuY29kZWMgPSBvZmZlci5tZWRpYVtpXS5ydHBbMF0uY29kZWM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAocmV3cml0ZSkge1xuICAgICAgICBzZHAgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG4gICAgfVxuXG4gICAgLy8gVW5pZmllZCBQbGFuIFNEUCBpcyBvdXIgXCJwcmVjaW91c1wiLiBDYWNoZSBpdCBmb3IgbGF0ZXIgdXNlIGluIHRoZSBQbGFuIEJcbiAgICAvLyAtPiBVbmlmaWVkIFBsYW4gdHJhbnNmb3JtYXRpb24uXG4gICAgdGhpcy5jYWNoZVtkZXNjLnR5cGVdID0gc2RwO1xuXG4gICAgLy8jcmVnaW9uIENvbnZlcnQgZnJvbSBVbmlmaWVkIFBsYW4gdG8gUGxhbiBCLlxuXG4gICAgLy8gV2UgcmVidWlsZCB0aGUgc2Vzc2lvbi5tZWRpYSBhcnJheS5cbiAgICB2YXIgbWVkaWEgPSBzZXNzaW9uLm1lZGlhO1xuICAgIHNlc3Npb24ubWVkaWEgPSBbXTtcblxuICAgIC8vIEFzc29jaWF0aXZlIGFycmF5IHRoYXQgbWFwcyBjaGFubmVsIHR5cGVzIHRvIGNoYW5uZWwgb2JqZWN0cyBmb3IgZmFzdFxuICAgIC8vIGFjY2VzcyB0byBjaGFubmVsIG9iamVjdHMgYnkgdGhlaXIgdHlwZSwgZS5nLiB0eXBlMmJsWydhdWRpbyddLT5jaGFubmVsXG4gICAgLy8gb2JqLlxuICAgIHZhciB0eXBlMmJsID0ge307XG5cbiAgICAvLyBVc2VkIHRvIGJ1aWxkIHRoZSBncm91cDpCVU5ETEUgdmFsdWUgYWZ0ZXIgdGhlIGNoYW5uZWxzIGNvbnN0cnVjdGlvblxuICAgIC8vIGxvb3AuXG4gICAgdmFyIHR5cGVzID0gW107XG5cbiAgICBtZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKHVMaW5lKSB7XG4gICAgICAgIC8vIHJ0Y3AtbXV4IGlzIHJlcXVpcmVkIGluIHRoZSBQbGFuIEIgU0RQLlxuICAgICAgICBpZiAoKHR5cGVvZiB1TGluZS5ydGNwTXV4ICE9PSAnc3RyaW5nJyB8fFxuICAgICAgICAgICAgdUxpbmUucnRjcE11eCAhPT0gJ3J0Y3AtbXV4JykgJiZcbiAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29udmVydCB0byBQbGFuIEIgYmVjYXVzZSBtLWxpbmVzICcgK1xuICAgICAgICAgICAgICAgICd3aXRob3V0IHRoZSBydGNwLW11eCBhdHRyaWJ1dGUgd2VyZSBmb3VuZC4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHdlIGRvbid0IGhhdmUgYSBjaGFubmVsIGZvciB0aGlzIHVMaW5lLnR5cGUgT1IgdGhlIHNlbGVjdGVkIGlzXG4gICAgICAgIC8vIGluYWN0aXZlLCB0aGVuIHNlbGVjdCB0aGlzIHVMaW5lIGFzIHRoZSBjaGFubmVsIGJhc2lzLlxuICAgICAgICBpZiAodHlwZW9mIHR5cGUyYmxbdUxpbmUudHlwZV0gPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLmRpcmVjdGlvbiA9PT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXSA9IHVMaW5lO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVMaW5lLnByb3RvY29sICE9IHR5cGUyYmxbdUxpbmUudHlwZV0ucHJvdG9jb2wpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHRvIFBsYW4gQiBiZWNhdXNlIG0tbGluZXMgJyArXG4gICAgICAgICAgICAgICdoYXZlIGRpZmZlcmVudCBwcm90b2NvbHMgYW5kIHRoaXMgbGlicmFyeSBkb2VzIG5vdCBoYXZlICcgK1xuICAgICAgICAgICAgICAnc3VwcG9ydCBmb3IgdGhhdCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVMaW5lLnBheWxvYWRzICE9IHR5cGUyYmxbdUxpbmUudHlwZV0ucGF5bG9hZHMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHRvIFBsYW4gQiBiZWNhdXNlIG0tbGluZXMgJyArXG4gICAgICAgICAgICAgICdoYXZlIGRpZmZlcmVudCBwYXlsb2FkcyBhbmQgdGhpcyBsaWJyYXJ5IGRvZXMgbm90IGhhdmUgJyArXG4gICAgICAgICAgICAgICdzdXBwb3J0IGZvciB0aGF0Jyk7XG4gICAgICAgIH1cblxuICAgIH0pO1xuXG4gICAgLy8gSW1wbG9kZSB0aGUgVW5pZmllZCBQbGFuIG0tbGluZXMvdHJhY2tzIGludG8gUGxhbiBCIGNoYW5uZWxzLlxuICAgIG1lZGlhLmZvckVhY2goZnVuY3Rpb24odUxpbmUpIHtcbiAgICAgICAgaWYgKHVMaW5lLnR5cGUgPT09ICdhcHBsaWNhdGlvbicpIHtcbiAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG4gICAgICAgICAgICB0eXBlcy5wdXNoKHVMaW5lLm1pZCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgc291cmNlcyB0byB0aGUgY2hhbm5lbCBhbmQgaGFuZGxlIGE9bXNpZC5cbiAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5zb3VyY2VzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgT2JqZWN0LmtleXModUxpbmUuc291cmNlcykuZm9yRWFjaChmdW5jdGlvbihzc3JjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXMgIT09ICdvYmplY3QnKVxuICAgICAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXMgPSB7fTtcblxuICAgICAgICAgICAgICAgIC8vIEFzc2lnbiB0aGUgc291cmNlcyB0byB0aGUgY2hhbm5lbC5cbiAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXNbc3NyY10gPVxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5tc2lkICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbiBQbGFuIEIgdGhlIG1zaWQgaXMgYW4gU1NSQyBhdHRyaWJ1dGUuIEFsc28sIHdlIGRvbid0XG4gICAgICAgICAgICAgICAgICAgIC8vIGNhcmUgYWJvdXQgdGhlIG9ic29sZXRlIGxhYmVsIGFuZCBtc2xhYmVsIGF0dHJpYnV0ZXMuXG4gICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGUgdGhhdCBpdCBpcyBub3QgZ3VhcmFudGVlZCB0aGF0IHRoZSB1TGluZSB3aWxsXG4gICAgICAgICAgICAgICAgICAgIC8vIGhhdmUgYW4gbXNpZC4gcmVjdm9ubHkgY2hhbm5lbHMgaW4gcGFydGljdWxhciBkb24ndCBoYXZlXG4gICAgICAgICAgICAgICAgICAgIC8vIG9uZS5cbiAgICAgICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzW3NzcmNdLm1zaWQgPVxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubXNpZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gTk9URSBzc3JjcyBpbiBzc3JjIGdyb3VwcyB3aWxsIHNoYXJlIG1zaWRzLCBhc1xuICAgICAgICAgICAgICAgIC8vIGRyYWZ0LXViZXJ0aS1ydGN3ZWItcGxhbi0wMCBtYW5kYXRlcy5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHNzcmMgZ3JvdXBzIHRvIHRoZSBjaGFubmVsLlxuICAgICAgICBpZiAodHlwZW9mIHVMaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheSh1TGluZS5zc3JjR3JvdXBzKSkge1xuXG4gICAgICAgICAgICAvLyBDcmVhdGUgdGhlIHNzcmNHcm91cHMgYXJyYXksIGlmIGl0J3Mgbm90IGRlZmluZWQuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcyA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgIUFycmF5LmlzQXJyYXkodHlwZTJibFt1TGluZS50eXBlXS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcyA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMgPVxuICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3Vwcy5jb25jYXQoXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNzcmNHcm91cHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUyYmxbdUxpbmUudHlwZV0gPT09IHVMaW5lKSB7XG4gICAgICAgICAgICAvLyBQbGFuIEIgbWlkcyBhcmUgaW4gWydhdWRpbycsICd2aWRlbycsICdkYXRhJ11cbiAgICAgICAgICAgIHVMaW5lLm1pZCA9IHVMaW5lLnR5cGU7XG5cbiAgICAgICAgICAgIC8vIFBsYW4gQiBkb2Vzbid0IHN1cHBvcnQvbmVlZCB0aGUgYnVuZGxlLW9ubHkgYXR0cmlidXRlLlxuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLmJ1bmRsZU9ubHk7XG5cbiAgICAgICAgICAgIC8vIEluIFBsYW4gQiB0aGUgbXNpZCBpcyBhbiBTU1JDIGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuXG5cdCAgICBpZiAodUxpbmUudHlwZSA9PSBtZWRpYVswXS50eXBlKSB7XG5cdCAgICAgIHR5cGVzLnVuc2hpZnQodUxpbmUudHlwZSk7XG5cdCAgICAgIC8vIEFkZCB0aGUgY2hhbm5lbCB0byB0aGUgbmV3IG1lZGlhIGFycmF5LlxuXHQgICAgICBzZXNzaW9uLm1lZGlhLnVuc2hpZnQodUxpbmUpO1xuXHQgICAgfSBlbHNlIHtcblx0ICAgICAgdHlwZXMucHVzaCh1TGluZS50eXBlKTtcblx0ICAgICAgLy8gQWRkIHRoZSBjaGFubmVsIHRvIHRoZSBuZXcgbWVkaWEgYXJyYXkuXG5cdCAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG5cdCAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAvLyBXZSByZWdlbmVyYXRlIHRoZSBCVU5ETEUgZ3JvdXAgd2l0aCB0aGUgbmV3IG1pZHMuXG4gICAgICBzZXNzaW9uLmdyb3Vwcy5zb21lKGZ1bmN0aW9uKGdyb3VwKSB7XG5cdCAgaWYgKGdyb3VwLnR5cGUgPT09ICdCVU5ETEUnKSB7XG5cdCAgICAgIGdyb3VwLm1pZHMgPSB0eXBlcy5qb2luKCcgJyk7XG5cdCAgICAgIHJldHVybiB0cnVlO1xuXHQgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIG1zaWQgc2VtYW50aWNcbiAgICBzZXNzaW9uLm1zaWRTZW1hbnRpYyA9IHtcbiAgICAgICAgc2VtYW50aWM6ICdXTVMnLFxuICAgICAgICB0b2tlbjogJyonXG4gICAgfTtcblxuICAgIHZhciByZXNTdHIgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG5cbiAgICByZXR1cm4gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgIHR5cGU6IGRlc2MudHlwZSxcbiAgICAgICAgc2RwOiByZXNTdHJcbiAgICB9KTtcblxuICAgIC8vI2VuZHJlZ2lvblxufTtcblxuLyogZm9sbG93IHJ1bGVzIGRlZmluZWQgaW4gUkZDNDE0NSAqL1xuZnVuY3Rpb24gYWRkU2V0dXBBdHRyKHVMaW5lKSB7XG4gICAgaWYgKHR5cGVvZiB1TGluZS5zZXR1cCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh1TGluZS5zZXR1cCA9PT0gXCJhY3RpdmVcIikge1xuICAgICAgICAgICAgdUxpbmUuc2V0dXAgPSBcInBhc3NpdmVcIjtcbiAgICB9IGVsc2UgaWYgKHVMaW5lLnNldHVwID09PSBcInBhc3NpdmVcIikge1xuICAgICAgICB1TGluZS5zZXR1cCA9IFwiYWN0aXZlXCI7XG4gICAgfVxufVxuXG4vKipcbiAqIFRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYSBQbGFuIEIgU0RQIHRvIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIFNEUC4gQVxuICogUGVlckNvbm5lY3Rpb24gd3JhcHBlciB0cmFuc2Zvcm1zIHRoZSBTRFAgdG8gVW5pZmllZCBQbGFuIGJlZm9yZSBwYXNzaW5nIGl0XG4gKiB0byBGRi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvVW5pZmllZFBsYW4gPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFBsYW4gQiBTRFAuIFBsYW4gQiBTRFAgaGFzXG4gICAgLy8gYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA+IDMgfHwgIXNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBQbGFuIEIuJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vIE1ha2Ugc3VyZSB0aGlzIFBsYW4gQiBTRFAgY2FuIGJlIGNvbnZlcnRlZCB0byBhIFVuaWZpZWQgUGxhbiBTRFAuXG4gICAgdmFyIG1pZHMgPSBbXTtcbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24obSkge1xuICAgICAgICBtaWRzLnB1c2gobS5taWQpO1xuICAgIH0pO1xuXG4gICAgdmFyIGhhc0J1bmRsZSA9IGZhbHNlO1xuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG4gICAgICAgIGhhc0J1bmRsZSA9IHNlc3Npb24uZ3JvdXBzLmV2ZXJ5KGZ1bmN0aW9uKGcpIHtcbiAgICAgICAgICAgIHJldHVybiBnLnR5cGUgIT09ICdCVU5ETEUnIHx8XG4gICAgICAgICAgICAgICAgYXJyYXlFcXVhbHMuYXBwbHkoZy5taWRzLnNvcnQoKSwgW21pZHMuc29ydCgpXSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICghaGFzQnVuZGxlKSB7XG4gICAgICAgIHZhciBtdXN0QmVCdW5kbGUgPSBmYWxzZTtcblxuICAgICAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgaWYgKG0uZGlyZWN0aW9uICE9PSAnaW5hY3RpdmUnKSB7XG4gICAgICAgICAgICAgICAgbXVzdEJlQnVuZGxlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKG11c3RCZUJ1bmRsZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNvbnZlcnQgdG8gVW5pZmllZCBQbGFuIGJlY2F1c2UgbS1saW5lcyB0aGF0XCIgK1xuICAgICAgICAgICAgICBcIiBhcmUgbm90IGJ1bmRsZWQgd2VyZSBmb3VuZC5cIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyNlbmRyZWdpb25cblxuXG4gICAgLy8jcmVnaW9uIENvbnZlcnQgZnJvbSBQbGFuIEIgdG8gVW5pZmllZCBQbGFuLlxuXG4gICAgLy8gVW5mb3J0dW5hdGVseSwgYSBQbGFuIEIgb2ZmZXIvYW5zd2VyIGRvZXNuJ3QgaGF2ZSBlbm91Z2ggaW5mb3JtYXRpb24gdG9cbiAgICAvLyByZWJ1aWxkIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIG9mZmVyL2Fuc3dlci5cbiAgICAvL1xuICAgIC8vIEZvciBleGFtcGxlLCBpZiB0aGlzIGlzIGEgbG9jYWwgYW5zd2VyIChpbiBVbmlmaWVkIFBsYW4gc3R5bGUpIHRoYXQgd2VcbiAgICAvLyBjb252ZXJ0IHRvIFBsYW4gQiBwcmlvciB0byBoYW5kaW5nIGl0IG92ZXIgdG8gdGhlIGFwcGxpY2F0aW9uICh0aGVcbiAgICAvLyBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIGNhbGxlZCB1cywgZm9yIGluc3RhbmNlLCBhZnRlciBhIHN1Y2Nlc3NmdWxcbiAgICAvLyBjcmVhdGVBbnN3ZXIpLCB3ZSB3YW50IHRvIHJlbWVtYmVyIHRoZSBtLWxpbmUgYXQgd2hpY2ggd2UndmUgc2VlbiB0aGVcbiAgICAvLyAobG9jYWwpIFNTUkMuIFRoYXQncyBiZWNhdXNlIHdoZW4gdGhlIGFwcGxpY2F0aW9uIHdhbnRzIHRvIGRvIGNhbGwgdGhlXG4gICAgLy8gU0xEIG1ldGhvZCwgZm9yY2luZyB1cyB0byBkbyB0aGUgaW52ZXJzZSB0cmFuc2Zvcm1hdGlvbiAoZnJvbSBQbGFuIEIgdG9cbiAgICAvLyBVbmlmaWVkIFBsYW4pLCB3ZSBuZWVkIHRvIGtub3cgdG8gd2hpY2ggbS1saW5lIHRvIGFzc2lnbiB0aGUgKGxvY2FsKVxuICAgIC8vIFNTUkMuIFdlIGFsc28gbmVlZCB0byBrbm93IGFsbCB0aGUgb3RoZXIgbS1saW5lcyB0aGF0IHRoZSBvcmlnaW5hbFxuICAgIC8vIGFuc3dlciBoYWQgYW5kIGluY2x1ZGUgdGhlbSBpbiB0aGUgdHJhbnNmb3JtZWQgYW5zd2VyIGFzIHdlbGwuXG4gICAgLy9cbiAgICAvLyBBbm90aGVyIGV4YW1wbGUgaXMgaWYgdGhpcyBpcyBhIHJlbW90ZSBvZmZlciB0aGF0IHdlIGNvbnZlcnQgdG8gUGxhbiBCXG4gICAgLy8gcHJpb3IgdG8gZ2l2aW5nIGl0IHRvIHRoZSBhcHBsaWNhdGlvbiwgd2Ugd2FudCB0byByZW1lbWJlciB0aGUgbWlkIGF0XG4gICAgLy8gd2hpY2ggd2UndmUgc2VlbiB0aGUgKHJlbW90ZSkgU1NSQy5cbiAgICAvL1xuICAgIC8vIEluIHRoZSBpdGVyYXRpb24gdGhhdCBmb2xsb3dzLCB3ZSB1c2UgdGhlIGNhY2hlZCBVbmlmaWVkIFBsYW4gKGlmIGl0XG4gICAgLy8gZXhpc3RzKSB0byBhc3NpZ24gbWlkcyB0byBzc3Jjcy5cblxuICAgIHZhciB0eXBlO1xuICAgIGlmIChkZXNjLnR5cGUgPT09ICdhbnN3ZXInKSB7XG4gICAgICAgIHR5cGUgPSAnb2ZmZXInO1xuICAgIH0gZWxzZSBpZiAoZGVzYy50eXBlID09PSAnb2ZmZXInKSB7XG4gICAgICAgIHR5cGUgPSAnYW5zd2VyJztcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUeXBlICdcIiArIGRlc2MudHlwZSArIFwiJyBub3Qgc3VwcG9ydGVkLlwiKTtcbiAgICB9XG5cbiAgICB2YXIgY2FjaGVkO1xuICAgIGlmICh0eXBlb2YgdGhpcy5jYWNoZVt0eXBlXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY2FjaGVkID0gdHJhbnNmb3JtLnBhcnNlKHRoaXMuY2FjaGVbdHlwZV0pO1xuICAgIH1cblxuICAgIHZhciByZWN2b25seVNzcmNzID0ge1xuICAgICAgICBhdWRpbzoge30sXG4gICAgICAgIHZpZGVvOiB7fVxuICAgIH07XG5cbiAgICAvLyBBIGhlbHBlciBtYXAgdGhhdCBzZW5kcyBtaWRzIHRvIG0tbGluZSBvYmplY3RzLiBXZSB1c2UgaXQgbGF0ZXIgdG9cbiAgICAvLyByZWJ1aWxkIHRoZSBVbmlmaWVkIFBsYW4gc3R5bGUgc2Vzc2lvbi5tZWRpYSBhcnJheS5cbiAgICB2YXIgbWlkMnVsID0ge307XG4gICAgdmFyIGJJZHggPSAwO1xuICAgIHZhciB1SWR4ID0gMDtcblxuICAgIHZhciBzb3VyY2VzMnVsID0ge307XG5cbiAgICB2YXIgY2FuZGlkYXRlcztcbiAgICB2YXIgaWNlVWZyYWc7XG4gICAgdmFyIGljZVB3ZDtcbiAgICB2YXIgZmluZ2VycHJpbnQ7XG4gICAgdmFyIHBheWxvYWRzID0ge307XG4gICAgdmFyIHJ0Y3BGYiA9IHt9O1xuICAgIHZhciBydHAgPSB7fTtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbihiTGluZSkge1xuICAgICAgICBpZiAoKHR5cGVvZiBiTGluZS5ydGNwTXV4ICE9PSAnc3RyaW5nJyB8fFxuICAgICAgICAgICAgYkxpbmUucnRjcE11eCAhPT0gJ3J0Y3AtbXV4JykgJiZcbiAgICAgICAgICAgIGJMaW5lLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNvbnZlcnQgdG8gVW5pZmllZCBQbGFuIGJlY2F1c2UgbS1saW5lcyBcIiArXG4gICAgICAgICAgICAgICAgXCJ3aXRob3V0IHRoZSBydGNwLW11eCBhdHRyaWJ1dGUgd2VyZSBmb3VuZC5cIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYkxpbmUudHlwZSA9PT0gJ2FwcGxpY2F0aW9uJykge1xuICAgICAgICAgICAgbWlkMnVsW2JMaW5lLm1pZF0gPSBiTGluZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdpdGggcnRjcC1tdXggYW5kIGJ1bmRsZSBhbGwgdGhlIGNoYW5uZWxzIHNob3VsZCBoYXZlIHRoZSBzYW1lIElDRVxuICAgICAgICAvLyBzdHVmZi5cbiAgICAgICAgdmFyIHNvdXJjZXMgPSBiTGluZS5zb3VyY2VzO1xuICAgICAgICB2YXIgc3NyY0dyb3VwcyA9IGJMaW5lLnNzcmNHcm91cHM7XG4gICAgICAgIHZhciBwb3J0ID0gYkxpbmUucG9ydDtcblxuICAgICAgICAvKiBDaHJvbWUgYWRkcyBkaWZmZXJlbnQgY2FuZGlkYXRlcyBldmVuIHVzaW5nIGJ1bmRsZSwgc28gd2UgY29uY2F0IHRoZSBjYW5kaWRhdGVzIGxpc3QgKi9cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5jYW5kaWRhdGVzICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNhbmRpZGF0ZXMgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBjYW5kaWRhdGVzID0gY2FuZGlkYXRlcy5jb25jYXQoYkxpbmUuY2FuZGlkYXRlcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbmRpZGF0ZXMgPSBiTGluZS5jYW5kaWRhdGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCh0eXBlb2YgaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpICYmICh0eXBlb2YgYkxpbmUuaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpICYmIChpY2VVZnJhZyAhPSBiTGluZS5pY2VVZnJhZykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgQlVORExFIHN1cHBvcnRlZCwgaWNlVWZyYWcgbXVzdCBiZSB0aGUgc2FtZSBmb3IgYWxsIG0tbGluZXMuXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TGFzdCBpY2VVZnJhZzogXCIgKyBpY2VVZnJhZyArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGljZVVmcmFnOiBcIiArIGJMaW5lLmljZVVmcmFnXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5pY2VVZnJhZyAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGljZVVmcmFnID0gYkxpbmUuaWNlVWZyYWc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHR5cGVvZiBpY2VQd2QgIT0gJ3VuZGVmaW5lZCcpICYmICh0eXBlb2YgYkxpbmUuaWNlUHdkICE9ICd1bmRlZmluZWQnKSAmJiAoaWNlUHdkICE9IGJMaW5lLmljZVB3ZCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgQlVORExFIHN1cHBvcnRlZCwgaWNlUHdkIG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgaWNlUHdkOiBcIiArIGljZVB3ZCArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGljZVB3ZDogXCIgKyBiTGluZS5pY2VQd2RcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGJMaW5lLmljZVB3ZCAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGljZVB3ZCA9IGJMaW5lLmljZVB3ZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgodHlwZW9mIGZpbmdlcnByaW50ICE9ICd1bmRlZmluZWQnKSAmJiAodHlwZW9mIGJMaW5lLmZpbmdlcnByaW50ICE9ICd1bmRlZmluZWQnKSAmJlxuICAgICAgICAgICAgKGZpbmdlcnByaW50LnR5cGUgIT0gYkxpbmUuZmluZ2VycHJpbnQudHlwZSB8fCBmaW5nZXJwcmludC5oYXNoICE9IGJMaW5lLmZpbmdlcnByaW50Lmhhc2gpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IEJVTkRMRSBzdXBwb3J0ZWQsIGZpbmdlcnByaW50IG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgZmluZ2VycHJpbnQ6IFwiICsgSlNPTi5zdHJpbmdpZnkoZmluZ2VycHJpbnQpICsgXCJcXG5cIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcXHROZXcgZmluZ2VycHJpbnQ6IFwiICsgSlNPTi5zdHJpbmdpZnkoYkxpbmUuZmluZ2VycHJpbnQpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5maW5nZXJwcmludCAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGZpbmdlcnByaW50ID0gYkxpbmUuZmluZ2VycHJpbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBwYXlsb2Fkc1tiTGluZS50eXBlXSA9IGJMaW5lLnBheWxvYWRzO1xuICAgICAgICBydGNwRmJbYkxpbmUudHlwZV0gPSBiTGluZS5ydGNwRmI7XG4gICAgICAgIHJ0cFtiTGluZS50eXBlXSA9IGJMaW5lLnJ0cDtcblxuICAgICAgICAvLyBpbnZlcnRlZCBzc3JjIGdyb3VwIG1hcFxuICAgICAgICB2YXIgc3NyYzJncm91cCA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICAgIHNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgLy8gWFhYIFRoaXMgbWlnaHQgYnJha2UgaWYgYW4gU1NSQyBpcyBpbiBtb3JlIHRoYW4gb25lIGdyb3VwXG4gICAgICAgICAgICAgICAgLy8gZm9yIHNvbWUgcmVhc29uLlxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyY0dyb3VwLnNzcmNzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmNHcm91cC5zc3JjcykpIHtcbiAgICAgICAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzLmZvckVhY2goZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyYzJncm91cFtzc3JjXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzc3JjMmdyb3VwW3NzcmNdID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNzcmMyZ3JvdXBbc3NyY10ucHVzaChzc3JjR3JvdXApO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHNzcmMgdG8gbS1saW5lIGluZGV4LlxuICAgICAgICB2YXIgc3NyYzJtbCA9IHt9O1xuXG4gICAgICAgIGlmICh0eXBlb2Ygc291cmNlcyA9PT0gJ29iamVjdCcpIHtcblxuICAgICAgICAgICAgLy8gV2UnbGwgdXNlIHRoZSBcImJMaW5lXCIgb2JqZWN0IGFzIGEgcHJvdG90eXBlIGZvciBlYWNoIG5ldyBcIm1MaW5lXCJcbiAgICAgICAgICAgIC8vIHRoYXQgd2UgY3JlYXRlLCBidXQgZmlyc3Qgd2UgbmVlZCB0byBjbGVhbiBpdCB1cCBhIGJpdC5cbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5zb3VyY2VzO1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLnNzcmNHcm91cHM7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuY2FuZGlkYXRlcztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5pY2VVZnJhZztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5pY2VQd2Q7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuZmluZ2VycHJpbnQ7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUucG9ydDtcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5taWQ7XG5cbiAgICAgICAgICAgIC8vIEV4cGxvZGUgdGhlIFBsYW4gQiBjaGFubmVsIHNvdXJjZXMgd2l0aCBvbmUgbS1saW5lIHBlciBzb3VyY2UuXG4gICAgICAgICAgICBPYmplY3Qua2V5cyhzb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uKHNzcmMpIHtcblxuICAgICAgICAgICAgICAgIC8vIFRoZSAodW5pZmllZCkgbS1saW5lIGZvciB0aGlzIFNTUkMuIFdlIGVpdGhlciBjcmVhdGUgaXQgZnJvbVxuICAgICAgICAgICAgICAgIC8vIHNjcmF0Y2ggb3IsIGlmIGl0J3MgYSBncm91cGVkIFNTUkMsIHdlIHJlLXVzZSBhIHJlbGF0ZWRcbiAgICAgICAgICAgICAgICAvLyBtbGluZS4gSW4gb3RoZXIgd29yZHMsIGlmIHRoZSBzb3VyY2UgaXMgZ3JvdXBlZCB3aXRoIGFub3RoZXJcbiAgICAgICAgICAgICAgICAvLyBzb3VyY2UsIHB1dCB0aGUgdHdvIHRvZ2V0aGVyIGluIHRoZSBzYW1lIG0tbGluZS5cbiAgICAgICAgICAgICAgICB2YXIgdUxpbmU7XG5cbiAgICAgICAgICAgICAgICAvLyBXZSBhc3N1bWUgaGVyZSB0aGF0IHdlIGFyZSB0aGUgYW5zd2VyZXIgaW4gdGhlIE8vQSwgc28gYW55XG4gICAgICAgICAgICAgICAgLy8gb2ZmZXJzIHdoaWNoIHdlIHRyYW5zbGF0ZSBjb21lIGZyb20gdGhlIHJlbW90ZSBzaWRlLCB3aGlsZVxuICAgICAgICAgICAgICAgIC8vIGFuc3dlcnMgYXJlIGxvY2FsLiBTbyB0aGUgY2hlY2sgYmVsb3cgaXMgdG8gbWFrZSB0aGF0IHdlXG4gICAgICAgICAgICAgICAgLy8gaGFuZGxlIHJlY2VpdmUtb25seSBTU1JDcyBpbiBhIHNwZWNpYWwgd2F5IG9ubHkgaWYgdGhleSBjb21lXG4gICAgICAgICAgICAgICAgLy8gZnJvbSB0aGUgcmVtb3RlIHNpZGUuXG4gICAgICAgICAgICAgICAgaWYgKGRlc2MudHlwZT09PSdvZmZlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2Ugd2FudCB0byBkZXRlY3QgU1NSQ3Mgd2hpY2ggYXJlIHVzZWQgYnkgYSByZW1vdGUgcGVlclxuICAgICAgICAgICAgICAgICAgICAvLyBpbiBhbiBtLWxpbmUgd2l0aCBkaXJlY3Rpb249cmVjdm9ubHkgKGkuZS4gdGhleSBhcmVcbiAgICAgICAgICAgICAgICAgICAgLy8gYmVpbmcgdXNlZCBmb3IgUlRDUCBvbmx5KS5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBpbmZvcm1hdGlvbiB3b3VsZCBoYXZlIGdvdHRlbiBsb3N0IGlmIHRoZSByZW1vdGVcbiAgICAgICAgICAgICAgICAgICAgLy8gcGVlciB1c2VkIFVuaWZpZWQgUGxhbiBhbmQgdGhlaXIgbG9jYWwgZGVzY3JpcHRpb24gd2FzXG4gICAgICAgICAgICAgICAgICAgIC8vIHRyYW5zbGF0ZWQgdG8gUGxhbiBCLiBTbyB3ZSB1c2UgdGhlIGxhY2sgb2YgYW4gTVNJRFxuICAgICAgICAgICAgICAgICAgICAvLyBhdHRyaWJ1dGUgdG8gZGVkdWNlIGEgXCJyZWNlaXZlIG9ubHlcIiBTU1JDLlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNvdXJjZXNbc3NyY10ubXNpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjdm9ubHlTc3Jjc1tiTGluZS50eXBlXVtzc3JjXSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWNlaXZlLW9ubHkgU1NSQ3MgbXVzdCBub3QgY3JlYXRlIG5ldyBtLWxpbmVzLiBXZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2lsbCBhc3NpZ24gdGhlbSB0byBhbiBleGlzdGluZyBtLWxpbmUgbGF0ZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNzcmMyZ3JvdXBbc3NyY10gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoc3NyYzJncm91cFtzc3JjXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3NyYzJncm91cFtzc3JjXS5zb21lKGZ1bmN0aW9uIChzc3JjR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNzcmNHcm91cC5zc3JjcyAqaXMqIGFuIEFycmF5LCBubyBuZWVkIHRvIGNoZWNrXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhZ2FpbiBoZXJlLlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNzcmNHcm91cC5zc3Jjcy5zb21lKGZ1bmN0aW9uIChyZWxhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjMm1sW3JlbGF0ZWRdID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZSA9IHNzcmMybWxbcmVsYXRlZF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVMaW5lID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbS1saW5lIGFscmVhZHkgZXhpc3RzLiBKdXN0IGFkZCB0aGUgc291cmNlLlxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID0gc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIFwiYkxpbmVcIiBhcyBhIHByb3RvdHlwZSBmb3IgdGhlIFwidUxpbmVcIi5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUgPSBPYmplY3QuY3JlYXRlKGJMaW5lKTtcbiAgICAgICAgICAgICAgICAgICAgc3NyYzJtbFtzc3JjXSA9IHVMaW5lO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc291cmNlc1tzc3JjXS5tc2lkICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXNzaWduIHRoZSBtc2lkIG9mIHRoZSBzb3VyY2UgdG8gdGhlIG0tbGluZS4gTm90ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhhdCBpdCBpcyBub3QgZ3VhcmFudGVlZCB0aGF0IHRoZSBzb3VyY2Ugd2lsbCBoYXZlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtc2lkLiBJbiBwYXJ0aWN1bGFyIFwicmVjdm9ubHlcIiBzb3VyY2VzIGRvbid0IGhhdmUgYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1zaWQuIE5vdGUgdGhhdCBcInJlY3Zvbmx5XCIgaXMgYSB0ZXJtIG9ubHkgZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZm9yIG0tbGluZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5tc2lkID0gc291cmNlc1tzc3JjXS5tc2lkO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIGFzc2lnbiBvbmUgU1NSQyBwZXIgbWVkaWEgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID0gc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc3NyY0dyb3VwcyA9IHNzcmMyZ3JvdXBbc3NyY107XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHRoZSBjYWNoZWQgVW5pZmllZCBQbGFuIFNEUCAoaWYgaXQgZXhpc3RzKSB0byBhc3NpZ25cbiAgICAgICAgICAgICAgICAgICAgLy8gU1NSQ3MgdG8gbWlkcy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjYWNoZWQgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlb2YgY2FjaGVkLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShjYWNoZWQubWVkaWEpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZC5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtLnNvdXJjZXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKG0uc291cmNlcykuZm9yRWFjaChmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMgPT09IHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5taWQgPSBtLm1pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVMaW5lLm1pZCA9PT0gJ3VuZGVmaW5lZCcpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyBhbiBTU1JDIHRoYXQgd2Ugc2VlIGZvciB0aGUgZmlyc3QgdGltZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGl0IGEgbmV3IG1pZC4gVGhpcyBpcyB0eXBpY2FsbHkgdGhlIGNhc2Ugd2hlblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBtZXRob2QgaXMgY2FsbGVkIHRvIHRyYW5zZm9ybSBhIHJlbW90ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGVzY3JpcHRpb24gZm9yIHRoZSBmaXJzdCB0aW1lIG9yIHdoZW4gdGhlcmUgaXMgYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbmV3IFNTUkMgaW4gdGhlIHJlbW90ZSBkZXNjcmlwdGlvbiBiZWNhdXNlIGEgbmV3XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwZWVyIGhhcyBqb2luZWQgdGhlIGNvbmZlcmVuY2UuIExvY2FsIFNTUkNzIHNob3VsZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaGF2ZSBhbHJlYWR5IGJlZW4gYWRkZWQgdG8gdGhlIG1hcCBpbiB0aGUgdG9QbGFuQlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWV0aG9kLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2UgRkYgZ2VuZXJhdGVzIGFuc3dlcnMgaW4gVW5pZmllZCBQbGFuIHN0eWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UgTVVTVCBhbHJlYWR5IGhhdmUgYSBjYWNoZWQgYW5zd2VyIHdpdGggYWxsIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbG9jYWwgU1NSQ3MgbWFwcGVkIHRvIHNvbWUgbS1saW5lL21pZC5cblxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubWlkID0gW2JMaW5lLnR5cGUsICctJywgc3NyY10uam9pbignJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBJbmNsdWRlIHRoZSBjYW5kaWRhdGVzIGluIHRoZSAxc3QgbWVkaWEgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVVmcmFnID0gaWNlVWZyYWc7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUucG9ydCA9IHBvcnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgbWlkMnVsW3VMaW5lLm1pZF0gPSB1TGluZTtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlczJ1bFt1SWR4XSA9IHVMaW5lLnNvdXJjZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWNoZS5tbFUyQk1hcFt1SWR4XSA9IGJJZHg7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNhY2hlLm1sQjJVTWFwW2JJZHhdID0gdUlkeDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB1SWR4Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHVMaW5lID0gYkxpbmU7XG5cbiAgICAgICAgICB1TGluZS5jYW5kaWRhdGVzID0gY2FuZGlkYXRlcztcbiAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICB1TGluZS5maW5nZXJwcmludCA9IGZpbmdlcnByaW50O1xuICAgICAgICAgIHVMaW5lLnBvcnQgPSBwb3J0O1xuXG4gICAgICAgICAgbWlkMnVsW3VMaW5lLm1pZF0gPSB1TGluZTtcblxuICAgICAgICAgIHNlbGYuY2FjaGUubWxVMkJNYXBbdUlkeF0gPSBiSWR4O1xuICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHNlbGYuY2FjaGUubWxCMlVNYXBbYklkeF0gPSB1SWR4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGJJZHgrKztcbiAgICB9KTtcblxuICAgIC8vIFJlYnVpbGQgdGhlIG1lZGlhIGFycmF5IGluIHRoZSByaWdodCBvcmRlciBhbmQgYWRkIHRoZSBtaXNzaW5nIG1MaW5lc1xuICAgIC8vIChtaXNzaW5nIGZyb20gdGhlIFBsYW4gQiBTRFApLlxuICAgIHNlc3Npb24ubWVkaWEgPSBbXTtcbiAgICBtaWRzID0gW107IC8vIHJldXNlXG5cbiAgICBpZiAoZGVzYy50eXBlID09PSAnYW5zd2VyJykge1xuXG4gICAgICAgIC8vIFRoZSBtZWRpYSBsaW5lcyBpbiB0aGUgYW5zd2VyIG11c3QgbWF0Y2ggdGhlIG1lZGlhIGxpbmVzIGluIHRoZVxuICAgICAgICAvLyBvZmZlci4gVGhlIG9yZGVyIGlzIGltcG9ydGFudCB0b28uIEhlcmUgd2UgYXNzdW1lIHRoYXQgRmlyZWZveCBpc1xuICAgICAgICAvLyB0aGUgYW5zd2VyZXIsIHNvIHdlIG1lcmVseSBoYXZlIHRvIHVzZSB0aGUgcmVjb25zdHJ1Y3RlZCAodW5pZmllZClcbiAgICAgICAgLy8gYW5zd2VyIHRvIHVwZGF0ZSB0aGUgY2FjaGVkICh1bmlmaWVkKSBhbnN3ZXIgYWNjb3JkaW5nbHkuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEluIHRoZSBnZW5lcmFsIGNhc2UsIG9uZSB3b3VsZCBoYXZlIHRvIHVzZSB0aGUgY2FjaGVkICh1bmlmaWVkKVxuICAgICAgICAvLyBvZmZlciB0byBmaW5kIHRoZSBtLWxpbmVzIHRoYXQgYXJlIG1pc3NpbmcgZnJvbSB0aGUgcmVjb25zdHJ1Y3RlZFxuICAgICAgICAvLyBhbnN3ZXIsIHBvdGVudGlhbGx5IGdyYWJiaW5nIHRoZW0gZnJvbSB0aGUgY2FjaGVkICh1bmlmaWVkKSBhbnN3ZXIuXG4gICAgICAgIC8vIE9uZSBoYXMgdG8gYmUgY2FyZWZ1bCB3aXRoIHRoaXMgYXBwcm9hY2ggYmVjYXVzZSBpbmFjdGl2ZSBtLWxpbmVzIGRvXG4gICAgICAgIC8vIG5vdCBhbHdheXMgaGF2ZSBhbiBtaWQsIG1ha2luZyBpdCB0cmlja3kgKGltcG9zc2libGU/KSB0byBmaW5kIHdoZXJlXG4gICAgICAgIC8vIGV4YWN0bHkgYW5kIHdoaWNoIG0tbGluZXMgYXJlIG1pc3NpbmcgZnJvbSB0aGUgcmVjb25zdHJ1Y3RlZCBhbnN3ZXIuXG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjYWNoZWQubWVkaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB1TGluZSA9IGNhY2hlZC5tZWRpYVtpXTtcblxuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICBkZWxldGUgdUxpbmUuc291cmNlcztcbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zc3JjR3JvdXBzO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHNvdXJjZXMydWxbaV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAncmVjdm9ubHknO1xuICAgICAgICAgICAgICBlbHNlIGlmICh1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kb25seScpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnaW5hY3RpdmUnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKCF1TGluZS5kaXJlY3Rpb25cbiAgICAgICAgICAgICAgICAgIHx8IHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JylcbiAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICAgIGVsc2UgaWYgKHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3JlY3Zvbmx5JylcbiAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdzZW5kb25seSc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHVMaW5lLnNvdXJjZXMgPSBzb3VyY2VzMnVsW2ldO1xuICAgICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgICAgdUxpbmUuaWNlUHdkID0gaWNlUHdkO1xuICAgICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcblxuICAgICAgICAgICAgdUxpbmUucnRwID0gcnRwW3VMaW5lLnR5cGVdO1xuICAgICAgICAgICAgdUxpbmUucGF5bG9hZHMgPSBwYXlsb2Fkc1t1TGluZS50eXBlXTtcbiAgICAgICAgICAgIHVMaW5lLnJ0Y3BGYiA9IHJ0Y3BGYlt1TGluZS50eXBlXTtcblxuICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5taWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgLy8gaW5hY3RpdmUgbGluZXMgZG9uJ3QvbWF5IG5vdCBoYXZlIGFuIG1pZC5cbiAgICAgICAgICAgICAgICBtaWRzLnB1c2godUxpbmUubWlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgLy8gU0RQIG9mZmVyL2Fuc3dlciAoYW5kIHRoZSBKU0VQIHNwZWMpIGZvcmJpZHMgcmVtb3ZpbmcgYW4gbS1zZWN0aW9uXG4gICAgICAgIC8vIHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzLiBJZiB3ZSBhcmUgbm8gbG9uZ2VyIGludGVyZXN0ZWQgaW4gc2VuZGluZyBhXG4gICAgICAgIC8vIHRyYWNrLCB3ZSBqdXN0IHJlbW92ZSB0aGUgbXNpZCBhbmQgc3NyYyBhdHRyaWJ1dGVzIGFuZCBzZXQgaXQgdG9cbiAgICAgICAgLy8gZWl0aGVyIGE9cmVjdm9ubHkgKGFzIHRoZSByZW9mZmVyZXIsIHdlIG11c3QgdXNlIHJlY3Zvbmx5IGlmIHRoZVxuICAgICAgICAvLyBvdGhlciBzaWRlIHdhcyBwcmV2aW91c2x5IHNlbmRpbmcgb24gdGhlIG0tc2VjdGlvbiwgYnV0IHdlIGNhbiBhbHNvXG4gICAgICAgIC8vIGxlYXZlIHRoZSBwb3NzaWJpbGl0eSBvcGVuIGlmIGl0IHdhc24ndCBwcmV2aW91c2x5IGluIHVzZSksIG9yXG4gICAgICAgIC8vIGE9aW5hY3RpdmUuXG5cbiAgICAgICAgaWYgKHR5cGVvZiBjYWNoZWQgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICB0eXBlb2YgY2FjaGVkLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgQXJyYXkuaXNBcnJheShjYWNoZWQubWVkaWEpKSB7XG4gICAgICAgICAgICBjYWNoZWQubWVkaWEuZm9yRWFjaChmdW5jdGlvbih1TGluZSkge1xuICAgICAgICAgICAgICAgIG1pZHMucHVzaCh1TGluZS5taWQpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWlkMnVsW3VMaW5lLm1pZF0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaChtaWQydWxbdUxpbmUubWlkXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zb3VyY2VzO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdUxpbmUuc3NyY0dyb3VwcztcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXVMaW5lLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnc2VuZG9ubHknO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdyZWN2b25seScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdpbmFjdGl2ZSc7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhZGRTZXR1cEF0dHIgKHVMaW5lKTtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBhbGwgdGhlIHJlbWFpbmluZyAobmV3KSBtLWxpbmVzIG9mIHRoZSB0cmFuc2Zvcm1lZCBTRFAuXG4gICAgICAgIE9iamVjdC5rZXlzKG1pZDJ1bCkuZm9yRWFjaChmdW5jdGlvbihtaWQpIHtcbiAgICAgICAgICAgIGlmIChtaWRzLmluZGV4T2YobWlkKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtaWRzLnB1c2gobWlkKTtcbiAgICAgICAgICAgICAgICBpZiAobWlkMnVsW21pZF0uZGlyZWN0aW9uID09PSAncmVjdm9ubHknKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYSByZW1vdGUgcmVjdm9ubHkgY2hhbm5lbC4gQWRkIGl0cyBTU1JDIHRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyBhcHByb3ByaWF0ZSBzZW5kcmVjdiBvciBzZW5kb25seSBjaGFubmVsLlxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPKGdwKSB3aGF0IGlmIHdlIGRvbid0IGhhdmUgc2VuZHJlY3Yvc2VuZG9ubHlcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hhbm5lbD9cblxuICAgICAgICAgICAgICAgICAgICB2YXIgZG9uZSA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEuc29tZShmdW5jdGlvbiAodUxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLnR5cGUgPT09IG1pZDJ1bFttaWRdLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtaWQydWxbbWlkXSBzaG91bGRuJ3QgaGF2ZSBhbnkgc3NyYy1ncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhtaWQydWxbbWlkXS5zb3VyY2VzKS5mb3JFYWNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pZDJ1bFttaWRdLnNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb25lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2gobWlkMnVsW21pZF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKG1pZDJ1bFttaWRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEFmdGVyIHdlIGhhdmUgY29uc3RydWN0ZWQgdGhlIFBsYW4gVW5pZmllZCBtLWxpbmVzIHdlIGNhbiBmaWd1cmUgb3V0XG4gICAgLy8gd2hlcmUgKGluIHdoaWNoIG0tbGluZSkgdG8gcGxhY2UgdGhlICdyZWN2b25seSBTU1JDcycuXG4gICAgLy8gTm90ZTogd2UgYXNzdW1lIGhlcmUgdGhhdCB3ZSBhcmUgdGhlIGFuc3dlcmVyIGluIHRoZSBPL0EsIHNvIGFueSBvZmZlcnNcbiAgICAvLyB3aGljaCB3ZSB0cmFuc2xhdGUgY29tZSBmcm9tIHRoZSByZW1vdGUgc2lkZSwgd2hpbGUgYW5zd2VycyBhcmUgbG9jYWxcbiAgICAvLyAoYW5kIHNvIG91ciBsYXN0IGxvY2FsIGRlc2NyaXB0aW9uIGlzIGNhY2hlZCBhcyBhbiAnYW5zd2VyJykuXG4gICAgW1wiYXVkaW9cIiwgXCJ2aWRlb1wiXS5mb3JFYWNoKGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIGlmICghc2Vzc2lvbiB8fCAhc2Vzc2lvbi5tZWRpYSB8fCAhQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB2YXIgaWR4ID0gbnVsbDtcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGlkeCA9IHNlbGYuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyKHR5cGUpO1xuICAgICAgICAgICAgaWYgKGlkeCA9PT0gbnVsbCl7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyB0aGUgZmlyc3Qgb2ZmZXIgd2UgcmVjZWl2ZSwgd2UgZG9uJ3QgaGF2ZSBhXG4gICAgICAgICAgICAgICAgLy8gY2FjaGVkIGFuc3dlci4gQXNzdW1lIHRoYXQgd2Ugd2lsbCBiZSBzZW5kaW5nIG1lZGlhIHVzaW5nXG4gICAgICAgICAgICAgICAgLy8gdGhlIGZpcnN0IG0tbGluZSBmb3IgZWFjaCBtZWRpYSB0eXBlLlxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZXNzaW9uLm1lZGlhW2ldLnR5cGUgPT09IHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkeCA9IGk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpZHggJiYgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPiBpZHgpIHtcbiAgICAgICAgICAgIHZhciBtTGluZSA9IHNlc3Npb24ubWVkaWFbaWR4XTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmZvckVhY2goZnVuY3Rpb24oc3NyYykge1xuICAgICAgICAgICAgICAgIGlmIChtTGluZS5zb3VyY2VzICYmIG1MaW5lLnNvdXJjZXNbc3NyY10pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiUmVwbGFjaW5nIGFuIGV4aXN0aW5nIFNTUkMuXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIW1MaW5lLnNvdXJjZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgbUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIG1MaW5lLnNvdXJjZXNbc3NyY10gPSByZWN2b25seVNzcmNzW3R5cGVdW3NzcmNdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAvLyBXZSByZWdlbmVyYXRlIHRoZSBCVU5ETEUgZ3JvdXAgKHNpbmNlIHdlIHJlZ2VuZXJhdGVkIHRoZSBtaWRzKVxuICAgICAgc2Vzc2lvbi5ncm91cHMuc29tZShmdW5jdGlvbihncm91cCkge1xuXHQgIGlmIChncm91cC50eXBlID09PSAnQlVORExFJykge1xuXHQgICAgICBncm91cC5taWRzID0gbWlkcy5qb2luKCcgJyk7XG5cdCAgICAgIHJldHVybiB0cnVlO1xuXHQgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIG1zaWQgc2VtYW50aWNcbiAgICBzZXNzaW9uLm1zaWRTZW1hbnRpYyA9IHtcbiAgICAgICAgc2VtYW50aWM6ICdXTVMnLFxuICAgICAgICB0b2tlbjogJyonXG4gICAgfTtcblxuICAgIHZhciByZXNTdHIgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG5cbiAgICAvLyBDYWNoZSB0aGUgdHJhbnNmb3JtZWQgU0RQIChVbmlmaWVkIFBsYW4pIGZvciBsYXRlciByZS11c2UgaW4gdGhpc1xuICAgIC8vIGZ1bmN0aW9uLlxuICAgIHRoaXMuY2FjaGVbZGVzYy50eXBlXSA9IHJlc1N0cjtcblxuICAgIHJldHVybiBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgICAgdHlwZTogZGVzYy50eXBlLFxuICAgICAgICBzZHA6IHJlc1N0clxuICAgIH0pO1xuXG4gICAgLy8jZW5kcmVnaW9uXG59O1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgdHJhbnNmb3JtID0gcmVxdWlyZSgnc2RwLXRyYW5zZm9ybScpO1xuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24oc2Vzc2lvbiwgb3B0cykge1xuXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSkge1xuXG4gICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtTGluZSkge1xuICAgICAgLy8gZXhwYW5kIHNvdXJjZXMgdG8gc3NyY3NcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc291cmNlcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgT2JqZWN0LmtleXMobUxpbmUuc291cmNlcykubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbUxpbmUuc3NyY3MgPSBbXTtcbiAgICAgICAgICBPYmplY3Qua2V5cyhtTGluZS5zb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gbUxpbmUuc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHNvdXJjZSkuZm9yRWFjaChmdW5jdGlvbiAoYXR0cmlidXRlKSB7XG4gICAgICAgICAgICAgIG1MaW5lLnNzcmNzLnB1c2goe1xuICAgICAgICAgICAgICAgIGlkOiBzc3JjLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogYXR0cmlidXRlLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBzb3VyY2VbYXR0cmlidXRlXVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGRlbGV0ZSBtTGluZS5zb3VyY2VzO1xuICAgICAgICB9XG5cbiAgICAgIC8vIGpvaW4gc3NyY3MgaW4gc3NyYyBncm91cHNcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmNHcm91cC5zc3JjcykpIHtcbiAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzID0gc3NyY0dyb3VwLnNzcmNzLmpvaW4oJyAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gam9pbiBncm91cCBtaWRzXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLmdyb3VwcykpIHtcblxuICAgIHNlc3Npb24uZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgIGlmICh0eXBlb2YgZy5taWRzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KGcubWlkcykpIHtcbiAgICAgICAgZy5taWRzID0gZy5taWRzLmpvaW4oJyAnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbiwgb3B0cyk7XG59O1xuXG5leHBvcnRzLnBhcnNlID0gZnVuY3Rpb24oc2RwKSB7XG4gIHZhciBzZXNzaW9uID0gdHJhbnNmb3JtLnBhcnNlKHNkcCk7XG5cbiAgaWYgKHR5cGVvZiBzZXNzaW9uICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygc2Vzc2lvbi5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpIHtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICAgIC8vIGdyb3VwIHNvdXJjZXMgYXR0cmlidXRlcyBieSBzc3JjXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KG1MaW5lLnNzcmNzKSkge1xuICAgICAgICBtTGluZS5zb3VyY2VzID0ge307XG4gICAgICAgIG1MaW5lLnNzcmNzLmZvckVhY2goZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICBpZiAoIW1MaW5lLnNvdXJjZXNbc3NyYy5pZF0pXG4gICAgICAgICAgbUxpbmUuc291cmNlc1tzc3JjLmlkXSA9IHt9O1xuICAgICAgICBtTGluZS5zb3VyY2VzW3NzcmMuaWRdW3NzcmMuYXR0cmlidXRlXSA9IHNzcmMudmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlbGV0ZSBtTGluZS5zc3JjcztcbiAgICAgIH1cblxuICAgICAgLy8gc3BsaXQgc3NyY3MgaW4gc3NyYyBncm91cHNcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzID0gc3NyY0dyb3VwLnNzcmNzLnNwbGl0KCcgJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuICAvLyBzcGxpdCBncm91cCBtaWRzXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLmdyb3VwcykpIHtcblxuICAgIHNlc3Npb24uZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgIGlmICh0eXBlb2YgZy5taWRzID09PSAnc3RyaW5nJykge1xuICAgICAgICBnLm1pZHMgPSBnLm1pZHMuc3BsaXQoJyAnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzZXNzaW9uO1xufTtcblxuIiwiLyohXG4gKiBVQVBhcnNlci5qcyB2MC43LjE4XG4gKiBMaWdodHdlaWdodCBKYXZhU2NyaXB0LWJhc2VkIFVzZXItQWdlbnQgc3RyaW5nIHBhcnNlclxuICogaHR0cHM6Ly9naXRodWIuY29tL2ZhaXNhbG1hbi91YS1wYXJzZXItanNcbiAqXG4gKiBDb3B5cmlnaHQgwqkgMjAxMi0yMDE2IEZhaXNhbCBTYWxtYW4gPGZ5emxtYW5AZ21haWwuY29tPlxuICogRHVhbCBsaWNlbnNlZCB1bmRlciBHUEx2MiBvciBNSVRcbiAqL1xuXG4oZnVuY3Rpb24gKHdpbmRvdywgdW5kZWZpbmVkKSB7XG5cbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvLy8vLy8vLy8vLy8vL1xuICAgIC8vIENvbnN0YW50c1xuICAgIC8vLy8vLy8vLy8vLy9cblxuXG4gICAgdmFyIExJQlZFUlNJT04gID0gJzAuNy4xOCcsXG4gICAgICAgIEVNUFRZICAgICAgID0gJycsXG4gICAgICAgIFVOS05PV04gICAgID0gJz8nLFxuICAgICAgICBGVU5DX1RZUEUgICA9ICdmdW5jdGlvbicsXG4gICAgICAgIFVOREVGX1RZUEUgID0gJ3VuZGVmaW5lZCcsXG4gICAgICAgIE9CSl9UWVBFICAgID0gJ29iamVjdCcsXG4gICAgICAgIFNUUl9UWVBFICAgID0gJ3N0cmluZycsXG4gICAgICAgIE1BSk9SICAgICAgID0gJ21ham9yJywgLy8gZGVwcmVjYXRlZFxuICAgICAgICBNT0RFTCAgICAgICA9ICdtb2RlbCcsXG4gICAgICAgIE5BTUUgICAgICAgID0gJ25hbWUnLFxuICAgICAgICBUWVBFICAgICAgICA9ICd0eXBlJyxcbiAgICAgICAgVkVORE9SICAgICAgPSAndmVuZG9yJyxcbiAgICAgICAgVkVSU0lPTiAgICAgPSAndmVyc2lvbicsXG4gICAgICAgIEFSQ0hJVEVDVFVSRT0gJ2FyY2hpdGVjdHVyZScsXG4gICAgICAgIENPTlNPTEUgICAgID0gJ2NvbnNvbGUnLFxuICAgICAgICBNT0JJTEUgICAgICA9ICdtb2JpbGUnLFxuICAgICAgICBUQUJMRVQgICAgICA9ICd0YWJsZXQnLFxuICAgICAgICBTTUFSVFRWICAgICA9ICdzbWFydHR2JyxcbiAgICAgICAgV0VBUkFCTEUgICAgPSAnd2VhcmFibGUnLFxuICAgICAgICBFTUJFRERFRCAgICA9ICdlbWJlZGRlZCc7XG5cblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gSGVscGVyXG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgdXRpbCA9IHtcbiAgICAgICAgZXh0ZW5kIDogZnVuY3Rpb24gKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIHtcbiAgICAgICAgICAgIHZhciBtYXJnZWRSZWdleGVzID0ge307XG4gICAgICAgICAgICBmb3IgKHZhciBpIGluIHJlZ2V4ZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uc1tpXSAmJiBleHRlbnNpb25zW2ldLmxlbmd0aCAlIDIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2VkUmVnZXhlc1tpXSA9IGV4dGVuc2lvbnNbaV0uY29uY2F0KHJlZ2V4ZXNbaV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcmdlZFJlZ2V4ZXNbaV0gPSByZWdleGVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXJnZWRSZWdleGVzO1xuICAgICAgICB9LFxuICAgICAgICBoYXMgOiBmdW5jdGlvbiAoc3RyMSwgc3RyMikge1xuICAgICAgICAgIGlmICh0eXBlb2Ygc3RyMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHN0cjIudG9Mb3dlckNhc2UoKS5pbmRleE9mKHN0cjEudG9Mb3dlckNhc2UoKSkgIT09IC0xO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsb3dlcml6ZSA6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHIudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfSxcbiAgICAgICAgbWFqb3IgOiBmdW5jdGlvbiAodmVyc2lvbikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZih2ZXJzaW9uKSA9PT0gU1RSX1RZUEUgPyB2ZXJzaW9uLnJlcGxhY2UoL1teXFxkXFwuXS9nLCcnKS5zcGxpdChcIi5cIilbMF0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIHRyaW0gOiBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eW1xcc1xcdUZFRkZcXHhBMF0rfFtcXHNcXHVGRUZGXFx4QTBdKyQvZywgJycpO1xuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gTWFwIGhlbHBlclxuICAgIC8vLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciBtYXBwZXIgPSB7XG5cbiAgICAgICAgcmd4IDogZnVuY3Rpb24gKHVhLCBhcnJheXMpIHtcblxuICAgICAgICAgICAgLy92YXIgcmVzdWx0ID0ge30sXG4gICAgICAgICAgICB2YXIgaSA9IDAsIGosIGssIHAsIHEsIG1hdGNoZXMsIG1hdGNoOy8vLCBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAgICAgICAvKi8vIGNvbnN0cnVjdCBvYmplY3QgYmFyZWJvbmVzXG4gICAgICAgICAgICBmb3IgKHAgPSAwOyBwIDwgYXJnc1sxXS5sZW5ndGg7IHArKykge1xuICAgICAgICAgICAgICAgIHEgPSBhcmdzWzFdW3BdO1xuICAgICAgICAgICAgICAgIHJlc3VsdFt0eXBlb2YgcSA9PT0gT0JKX1RZUEUgPyBxWzBdIDogcV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9Ki9cblxuICAgICAgICAgICAgLy8gbG9vcCB0aHJvdWdoIGFsbCByZWdleGVzIG1hcHNcbiAgICAgICAgICAgIHdoaWxlIChpIDwgYXJyYXlzLmxlbmd0aCAmJiAhbWF0Y2hlcykge1xuXG4gICAgICAgICAgICAgICAgdmFyIHJlZ2V4ID0gYXJyYXlzW2ldLCAgICAgICAvLyBldmVuIHNlcXVlbmNlICgwLDIsNCwuLilcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSBhcnJheXNbaSArIDFdOyAgIC8vIG9kZCBzZXF1ZW5jZSAoMSwzLDUsLi4pXG4gICAgICAgICAgICAgICAgaiA9IGsgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gdHJ5IG1hdGNoaW5nIHVhc3RyaW5nIHdpdGggcmVnZXhlc1xuICAgICAgICAgICAgICAgIHdoaWxlIChqIDwgcmVnZXgubGVuZ3RoICYmICFtYXRjaGVzKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IHJlZ2V4W2orK10uZXhlYyh1YSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwID0gMDsgcCA8IHByb3BzLmxlbmd0aDsgcCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBtYXRjaGVzWysra107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcSA9IHByb3BzW3BdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIGdpdmVuIHByb3BlcnR5IGlzIGFjdHVhbGx5IGFycmF5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBxID09PSBPQkpfVFlQRSAmJiBxLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHEubGVuZ3RoID09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcVsxXSA9PSBGVU5DX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhc3NpZ24gbW9kaWZpZWQgbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXS5jYWxsKHRoaXMsIG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGdpdmVuIHZhbHVlLCBpZ25vcmUgcmVnZXggbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayB3aGV0aGVyIGZ1bmN0aW9uIG9yIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHFbMV0gPT09IEZVTkNfVFlQRSAmJiAhKHFbMV0uZXhlYyAmJiBxWzFdLnRlc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FsbCBmdW5jdGlvbiAodXN1YWxseSBzdHJpbmcgbWFwcGVyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbcVswXV0gPSBtYXRjaCA/IHFbMV0uY2FsbCh0aGlzLCBtYXRjaCwgcVsyXSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNhbml0aXplIG1hdGNoIHVzaW5nIGdpdmVuIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gbWF0Y2gucmVwbGFjZShxWzFdLCBxWzJdKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gcVszXS5jYWxsKHRoaXMsIG1hdGNoLnJlcGxhY2UocVsxXSwgcVsyXSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txXSA9IG1hdGNoID8gbWF0Y2ggOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMpO1xuICAgICAgICAgICAgLy9yZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICBzdHIgOiBmdW5jdGlvbiAoc3RyLCBtYXApIHtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBtYXApIHtcbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBhcnJheVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWFwW2ldID09PSBPQkpfVFlQRSAmJiBtYXBbaV0ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1hcFtpXS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHV0aWwuaGFzKG1hcFtpXVtqXSwgc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoaSA9PT0gVU5LTk9XTikgPyB1bmRlZmluZWQgOiBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh1dGlsLmhhcyhtYXBbaV0sIHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChpID09PSBVTktOT1dOKSA/IHVuZGVmaW5lZCA6IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgICAgfVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIFN0cmluZyBtYXBcbiAgICAvLy8vLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgbWFwcyA9IHtcblxuICAgICAgICBicm93c2VyIDoge1xuICAgICAgICAgICAgb2xkc2FmYXJpIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICcxLjAnICAgOiAnLzgnLFxuICAgICAgICAgICAgICAgICAgICAnMS4yJyAgIDogJy8xJyxcbiAgICAgICAgICAgICAgICAgICAgJzEuMycgICA6ICcvMycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAnICAgOiAnLzQxMicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMicgOiAnLzQxNicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMycgOiAnLzQxNycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuNCcgOiAnLzQxOScsXG4gICAgICAgICAgICAgICAgICAgICc/JyAgICAgOiAnLydcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGV2aWNlIDoge1xuICAgICAgICAgICAgYW1hem9uIDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRmlyZSBQaG9uZScgOiBbJ1NEJywgJ0tGJ11cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3ByaW50IDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRXZvIFNoaWZ0IDRHJyA6ICc3MzczS1QnXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB2ZW5kb3IgOiB7XG4gICAgICAgICAgICAgICAgICAgICdIVEMnICAgICAgIDogJ0FQQScsXG4gICAgICAgICAgICAgICAgICAgICdTcHJpbnQnICAgIDogJ1NwcmludCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgb3MgOiB7XG4gICAgICAgICAgICB3aW5kb3dzIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICdNRScgICAgICAgIDogJzQuOTAnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgMy4xMScgICA6ICdOVDMuNTEnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgNC4wJyAgICA6ICdOVDQuMCcsXG4gICAgICAgICAgICAgICAgICAgICcyMDAwJyAgICAgIDogJ05UIDUuMCcsXG4gICAgICAgICAgICAgICAgICAgICdYUCcgICAgICAgIDogWydOVCA1LjEnLCAnTlQgNS4yJ10sXG4gICAgICAgICAgICAgICAgICAgICdWaXN0YScgICAgIDogJ05UIDYuMCcsXG4gICAgICAgICAgICAgICAgICAgICc3JyAgICAgICAgIDogJ05UIDYuMScsXG4gICAgICAgICAgICAgICAgICAgICc4JyAgICAgICAgIDogJ05UIDYuMicsXG4gICAgICAgICAgICAgICAgICAgICc4LjEnICAgICAgIDogJ05UIDYuMycsXG4gICAgICAgICAgICAgICAgICAgICcxMCcgICAgICAgIDogWydOVCA2LjQnLCAnTlQgMTAuMCddLFxuICAgICAgICAgICAgICAgICAgICAnUlQnICAgICAgICA6ICdBUk0nXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy9cbiAgICAvLyBSZWdleCBtYXBcbiAgICAvLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciByZWdleGVzID0ge1xuXG4gICAgICAgIGJyb3dzZXIgOiBbW1xuXG4gICAgICAgICAgICAvLyBQcmVzdG8gYmFzZWRcbiAgICAgICAgICAgIC8ob3BlcmFcXHNtaW5pKVxcLyhbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1pbmlcbiAgICAgICAgICAgIC8ob3BlcmFcXHNbbW9iaWxldGFiXSspLit2ZXJzaW9uXFwvKFtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1vYmkvVGFibGV0XG4gICAgICAgICAgICAvKG9wZXJhKS4rdmVyc2lvblxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhID4gOS44MFxuICAgICAgICAgICAgLyhvcGVyYSlbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgPCA5LjgwXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhvcGlvcylbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgbWluaSBvbiBpcGhvbmUgPj0gOC4wXG4gICAgICAgICAgICBdLCBbW05BTUUsICdPcGVyYSBNaW5pJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9cXHMob3ByKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIFdlYmtpdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gTWl4ZWRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvKGx1bmFzY2FwZXxtYXh0aG9ufG5ldGZyb250fGphc21pbmV8YmxhemVyKVtcXC9cXHNdPyhbXFx3XFwuXSopL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEx1bmFzY2FwZS9NYXh0aG9uL05ldGZyb250L0phc21pbmUvQmxhemVyXG5cbiAgICAgICAgICAgIC8vIFRyaWRlbnQgYmFzZWRcbiAgICAgICAgICAgIC8oYXZhbnRcXHN8aWVtb2JpbGV8c2xpbXxiYWlkdSkoPzpicm93c2VyKT9bXFwvXFxzXT8oW1xcd1xcLl0qKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdmFudC9JRU1vYmlsZS9TbGltQnJvd3Nlci9CYWlkdVxuICAgICAgICAgICAgLyg/Om1zfFxcKCkoaWUpXFxzKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW50ZXJuZXQgRXhwbG9yZXJcblxuICAgICAgICAgICAgLy8gV2Via2l0L0tIVE1MIGJhc2VkXG4gICAgICAgICAgICAvKHJla29ucSlcXC8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJla29ucVxuICAgICAgICAgICAgLyhjaHJvbWl1bXxmbG9ja3xyb2NrbWVsdHxtaWRvcml8ZXBpcGhhbnl8c2lsa3xza3lmaXJlfG92aWJyb3dzZXJ8Ym9sdHxpcm9ufHZpdmFsZGl8aXJpZGl1bXxwaGFudG9tanN8Ym93c2VyfHF1YXJrKVxcLyhbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9taXVtL0Zsb2NrL1JvY2tNZWx0L01pZG9yaS9FcGlwaGFueS9TaWxrL1NreWZpcmUvQm9sdC9Jcm9uL0lyaWRpdW0vUGhhbnRvbUpTL0Jvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8odHJpZGVudCkuK3J2WzpcXHNdKFtcXHdcXC5dKykuK2xpa2VcXHNnZWNrby9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElFMTFcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0lFJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oZWRnZXxlZGdpb3N8ZWRnZWEpXFwvKChcXGQrKT9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBFZGdlXG4gICAgICAgICAgICBdLCBbW05BTUUsICdFZGdlJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oeWFicm93c2VyKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWWFuZGV4XG4gICAgICAgICAgICBdLCBbW05BTUUsICdZYW5kZXgnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhwdWZmaW4pXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQdWZmaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ1B1ZmZpbiddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKCg/OltcXHNcXC9dKXVjP1xccz9icm93c2VyfCg/Omp1Yy4rKXVjd2ViKVtcXC9cXHNdPyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVUNCcm93c2VyXG4gICAgICAgICAgICBdLCBbW05BTUUsICdVQ0Jyb3dzZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb21vZG9fZHJhZ29uKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb21vZG8gRHJhZ29uXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obWljcm9tZXNzZW5nZXIpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2VDaGF0XG4gICAgICAgICAgICBdLCBbW05BTUUsICdXZUNoYXQnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhxcWJyb3dzZXJsaXRlKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUUJyb3dzZXJMaXRlXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhRUSlcXC8oW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUSwgYWthIFNob3VRXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL20/KHFxYnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUVFCcm93c2VyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhCSURVQnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmFpZHUgQnJvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oMjM0NUV4cGxvcmVyKVtcXC9cXHNdPyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDIzNDUgQnJvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oTWV0YVNyKVtcXC9cXHNdPyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvdUdvdUJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAvKExCQlJPV1NFUikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGllQmFvIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAveGlhb21pXFwvbWl1aWJyb3dzZXJcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNSVVJIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ01JVUkgQnJvd3NlciddXSwgW1xuXG4gICAgICAgICAgICAvO2ZiYXZcXC8oW1xcd1xcLl0rKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZhY2Vib29rIEFwcCBmb3IgaU9TICYgQW5kcm9pZFxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnRmFjZWJvb2snXV0sIFtcblxuICAgICAgICAgICAgL2hlYWRsZXNzY2hyb21lKD86XFwvKFtcXHdcXC5dKyl8XFxzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lIEhlYWRsZXNzXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdDaHJvbWUgSGVhZGxlc3MnXV0sIFtcblxuICAgICAgICAgICAgL1xcc3d2XFwpLisoY2hyb21lKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9tZSBXZWJWaWV3XG4gICAgICAgICAgICBdLCBbW05BTUUsIC8oLispLywgJyQxIFdlYlZpZXcnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLygoPzpvY3VsdXN8c2Ftc3VuZylicm93c2VyKVxcLyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgLyguKyg/Omd8dXMpKSguKykvLCAnJDEgJDInXSwgVkVSU0lPTl0sIFsgICAgICAgICAgICAgICAgLy8gT2N1bHVzIC8gU2Ftc3VuZyBCcm93c2VyXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLit2ZXJzaW9uXFwvKFtcXHdcXC5dKylcXHMrKD86bW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpKi9pICAgICAgICAvLyBBbmRyb2lkIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0FuZHJvaWQgQnJvd3NlciddXSwgW1xuXG4gICAgICAgICAgICAvKGNocm9tZXxvbW5pd2VifGFyb3JhfFt0aXplbm9rYV17NX1cXHM/YnJvd3NlcilcXC92PyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lL09tbmlXZWIvQXJvcmEvVGl6ZW4vTm9raWFcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGRvbGZpbilcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvbHBoaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0RvbHBoaW4nXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLygoPzphbmRyb2lkLispY3Jtb3xjcmlvcylcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaHJvbWUgZm9yIEFuZHJvaWQvaU9TXG4gICAgICAgICAgICBdLCBbW05BTUUsICdDaHJvbWUnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb2FzdClcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPcGVyYSBDb2FzdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEgQ29hc3QnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL2Z4aW9zXFwvKFtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IGZvciBpT1NcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0ZpcmVmb3gnXV0sIFtcblxuICAgICAgICAgICAgL3ZlcnNpb25cXC8oW1xcd1xcLl0rKS4rP21vYmlsZVxcL1xcdytcXHMoc2FmYXJpKS9pICAgICAgICAgICAgICAgICAgICAgICAvLyBNb2JpbGUgU2FmYXJpXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdNb2JpbGUgU2FmYXJpJ11dLCBbXG5cbiAgICAgICAgICAgIC92ZXJzaW9uXFwvKFtcXHdcXC5dKykuKz8obW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpL2kgICAgICAgICAgICAgICAgICAgIC8vIFNhZmFyaSAmIFNhZmFyaSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXSwgW1xuXG4gICAgICAgICAgICAvd2Via2l0Lis/KGdzYSlcXC8oW1xcd1xcLl0rKS4rPyhtb2JpbGVcXHM/c2FmYXJpfHNhZmFyaSkoXFwvW1xcd1xcLl0rKS9pICAvLyBHb29nbGUgU2VhcmNoIEFwcGxpYW5jZSBvbiBpT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0dTQSddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvd2Via2l0Lis/KG1vYmlsZVxccz9zYWZhcml8c2FmYXJpKShcXC9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAvLyBTYWZhcmkgPCAzLjBcbiAgICAgICAgICAgIF0sIFtOQU1FLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5icm93c2VyLm9sZHNhZmFyaS52ZXJzaW9uXV0sIFtcblxuICAgICAgICAgICAgLyhrb25xdWVyb3IpXFwvKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLb25xdWVyb3JcbiAgICAgICAgICAgIC8od2Via2l0fGtodG1sKVxcLyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBHZWNrbyBiYXNlZFxuICAgICAgICAgICAgLyhuYXZpZ2F0b3J8bmV0c2NhcGUpXFwvKFtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOZXRzY2FwZVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnTmV0c2NhcGUnXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oc3dpZnRmb3gpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3dpZnRmb3hcbiAgICAgICAgICAgIC8oaWNlZHJhZ29ufGljZXdlYXNlbHxjYW1pbm98Y2hpbWVyYXxmZW5uZWN8bWFlbW9cXHNicm93c2VyfG1pbmltb3xjb25rZXJvcilbXFwvXFxzXT8oW1xcd1xcLlxcK10rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJY2VEcmFnb24vSWNld2Vhc2VsL0NhbWluby9DaGltZXJhL0Zlbm5lYy9NYWVtby9NaW5pbW8vQ29ua2Vyb3JcbiAgICAgICAgICAgIC8oZmlyZWZveHxzZWFtb25rZXl8ay1tZWxlb258aWNlY2F0fGljZWFwZXxmaXJlYmlyZHxwaG9lbml4fHBhbGVtb29ufGJhc2lsaXNrfHdhdGVyZm94KVxcLyhbXFx3XFwuLV0rKSQvaSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94L1NlYU1vbmtleS9LLU1lbGVvbi9JY2VDYXQvSWNlQXBlL0ZpcmViaXJkL1Bob2VuaXhcbiAgICAgICAgICAgIC8obW96aWxsYSlcXC8oW1xcd1xcLl0rKS4rcnZcXDouK2dlY2tvXFwvXFxkKy9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW96aWxsYVxuXG4gICAgICAgICAgICAvLyBPdGhlclxuICAgICAgICAgICAgLyhwb2xhcmlzfGx5bnh8ZGlsbG98aWNhYnxkb3Jpc3xhbWF5YXx3M218bmV0c3VyZnxzbGVpcG5pcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQb2xhcmlzL0x5bngvRGlsbG8vaUNhYi9Eb3Jpcy9BbWF5YS93M20vTmV0U3VyZi9TbGVpcG5pclxuICAgICAgICAgICAgLyhsaW5rcylcXHNcXCgoW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGlua3NcbiAgICAgICAgICAgIC8oZ29icm93c2VyKVxcLz8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29Ccm93c2VyXG4gICAgICAgICAgICAvKGljZVxccz9icm93c2VyKVxcL3Y/KFtcXHdcXC5fXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQ0UgQnJvd3NlclxuICAgICAgICAgICAgLyhtb3NhaWMpW1xcL1xcc10oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9zYWljXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cblxuICAgICAgICAgICAgLyogLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAgICAgICAvLyBNZWRpYSBwbGF5ZXJzIEJFR0lOXG4gICAgICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICAgICAgICAgICAgLCBbXG5cbiAgICAgICAgICAgIC8oYXBwbGUoPzpjb3JlbWVkaWF8KSlcXC8oKFxcZCspW1xcd1xcLl9dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQXBwbGUgQ29yZU1lZGlhXG4gICAgICAgICAgICAvKGNvcmVtZWRpYSkgdigoXFxkKylbXFx3XFwuX10rKS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhhcXVhbHVuZ3xseXNzbmF8YnNwbGF5ZXIpXFwvKChcXGQrKT9bXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgLy8gQXF1YWx1bmcvTHlzc25hL0JTUGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhhcmVzfG9zc3Byb3h5KVxccygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXJlcy9PU1NQcm94eVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oYXVkYWNpb3VzfGF1ZGltdXNpY3N0cmVhbXxhbWFyb2t8YmFzc3xjb3JlfGRhbHZpa3xnbm9tZW1wbGF5ZXJ8bXVzaWMgb24gY29uc29sZXxuc3BsYXllcnxwc3AtaW50ZXJuZXRyYWRpb3BsYXllcnx2aWRlb3MpXFwvKChcXGQrKVtcXHdcXC4tXSspL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF1ZGFjaW91cy9BdWRpTXVzaWNTdHJlYW0vQW1hcm9rL0JBU1MvT3BlbkNPUkUvRGFsdmlrL0dub21lTXBsYXllci9Nb0NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTlNQbGF5ZXIvUFNQLUludGVybmV0UmFkaW9QbGF5ZXIvVmlkZW9zXG4gICAgICAgICAgICAvKGNsZW1lbnRpbmV8bXVzaWMgcGxheWVyIGRhZW1vbilcXHMoKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAvLyBDbGVtZW50aW5lL01QRFxuICAgICAgICAgICAgLyhsZyBwbGF5ZXJ8bmV4cGxheWVyKVxccygoXFxkKylbXFxkXFwuXSspL2ksXG4gICAgICAgICAgICAvcGxheWVyXFwvKG5leHBsYXllcnxsZyBwbGF5ZXIpXFxzKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgLy8gTmV4UGxheWVyL0xHIFBsYXllclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKG5leHBsYXllcilcXHMoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOZXhwbGF5ZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGZscnApXFwvKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGbGlwIFBsYXllclxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnRmxpcCBQbGF5ZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhmc3RyZWFtfG5hdGl2ZWhvc3R8cXVlcnlzZWVrc3BpZGVyfGlhLWFyY2hpdmVyfGZhY2Vib29rZXh0ZXJuYWxoaXQpL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRlN0cmVhbS9OYXRpdmVIb3N0L1F1ZXJ5U2Vla1NwaWRlci9JQSBBcmNoaXZlci9mYWNlYm9va2V4dGVybmFsaGl0XG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcblxuICAgICAgICAgICAgLyhnc3RyZWFtZXIpIHNvdXBodHRwc3JjICg/OlxcKFteXFwpXStcXCkpezAsMX0gbGlic291cFxcLygoXFxkKylbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdzdHJlYW1lclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjIHN0cmVhbWluZyBwbGF5ZXIpXFxzW1xcd19dK1xcc1xcL1xccygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAvLyBIVEMgU3RyZWFtaW5nIFBsYXllclxuICAgICAgICAgICAgLyhqYXZhfHB5dGhvbi11cmxsaWJ8cHl0aG9uLXJlcXVlc3RzfHdnZXR8bGliY3VybClcXC8oKFxcZCspW1xcd1xcLi1fXSspL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEphdmEvdXJsbGliL3JlcXVlc3RzL3dnZXQvY1VSTFxuICAgICAgICAgICAgLyhsYXZmKSgoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMYXZmIChGRk1QRUcpXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhodGNfb25lX3MpXFwvKChcXGQrKVtcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFRDIE9uZSBTXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikoPzpcXHN8XFwvKSg/Oig/OnNoZXJweWEtKXswLDF9c3ZuKSg/Oi18XFxzKShyXFxkKyg/Oi1cXGQrW1xcd1xcLi1dKyl7MCwxfSkvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyIFNWTlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikoPzpcXHN8XFwvfFt1bmtvdy1dKykoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhtcGxheWVyKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyIChubyBvdGhlciBpbmZvKVxuICAgICAgICAgICAgLyh5b3VybXV6ZSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBZb3VyTXV6ZVxuICAgICAgICAgICAgLyhtZWRpYSBwbGF5ZXIgY2xhc3NpY3xuZXJvIHNob3d0aW1lKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNZWRpYSBQbGF5ZXIgQ2xhc3NpYy9OZXJvIFNob3dUaW1lXG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcblxuICAgICAgICAgICAgLyhuZXJvICg/OmhvbWV8c2NvdXQpKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmVybyBIb21lL05lcm8gU2NvdXRcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG5va2lhXFxkKylcXC8oKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvXFxzKHNvbmdiaXJkKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29uZ2JpcmQvUGhpbGlwcy1Tb25nYmlyZFxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8od2luYW1wKTMgdmVyc2lvbiAoKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luYW1wXG4gICAgICAgICAgICAvKHdpbmFtcClcXHMoKFxcZCspW1xcd1xcLi1dKykvaSxcbiAgICAgICAgICAgIC8od2luYW1wKW1wZWdcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8ob2Ntcy1ib3R8dGFwaW5yYWRpb3x0dW5laW4gcmFkaW98dW5rbm93bnx3aW5hbXB8aW5saWdodCByYWRpbykvaSAgLy8gT0NNUy1ib3QvdGFwIGluIHJhZGlvL3R1bmVpbi91bmtub3duL3dpbmFtcCAobm8gb3RoZXIgaW5mbylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5saWdodCByYWRpb1xuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG5cbiAgICAgICAgICAgIC8ocXVpY2t0aW1lfHJtYXxyYWRpb2FwcHxyYWRpb2NsaWVudGFwcGxpY2F0aW9ufHNvdW5kdGFwfHRvdGVtfHN0YWdlZnJpZ2h0fHN0cmVhbWl1bSlcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRdWlja1RpbWUvUmVhbE1lZGlhL1JhZGlvQXBwL1JhZGlvQ2xpZW50QXBwbGljYXRpb24vXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvdW5kVGFwL1RvdGVtL1N0YWdlZnJpZ2h0L1N0cmVhbWl1bVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oc21wKSgoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU01QXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyh2bGMpIG1lZGlhIHBsYXllciAtIHZlcnNpb24gKChcXGQrKVtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAvLyBWTEMgVmlkZW9sYW5cbiAgICAgICAgICAgIC8odmxjKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLFxuICAgICAgICAgICAgLyh4Ym1jfGd2ZnN8eGluZXx4bW1zfGlyYXBwKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgLy8gWEJNQy9ndmZzL1hpbmUvWE1NUy9pcmFwcFxuICAgICAgICAgICAgLyhmb29iYXIyMDAwKVxcLygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRm9vYmFyMjAwMFxuICAgICAgICAgICAgLyhpdHVuZXMpXFwvKChcXGQrKVtcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVR1bmVzXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyh3bXBsYXllcilcXC8oKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBNZWRpYSBQbGF5ZXJcbiAgICAgICAgICAgIC8od2luZG93cy1tZWRpYS1wbGF5ZXIpXFwvKChcXGQrKVtcXHdcXC4tXSspL2lcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgLy0vZywgJyAnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL3dpbmRvd3NcXC8oKFxcZCspW1xcd1xcLi1dKykgdXBucFxcL1tcXGRcXC5dKyBkbG5hZG9jXFwvW1xcZFxcLl0rIChob21lIG1lZGlhIHNlcnZlcikvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaW5kb3dzIE1lZGlhIFNlcnZlclxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnV2luZG93cyddXSwgW1xuXG4gICAgICAgICAgICAvKGNvbVxcLnJpc2V1cHJhZGlvYWxhcm0pXFwvKChcXGQrKVtcXGRcXC5dKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmlzZVVQIFJhZGlvIEFsYXJtXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhyYWQuaW8pXFxzKChcXGQrKVtcXGRcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmFkLmlvXG4gICAgICAgICAgICAvKHJhZGlvLig/OmRlfGF0fGZyKSlcXHMoKFxcZCspW1xcZFxcLl0rKS9pXG4gICAgICAgICAgICBdLCBbW05BTUUsICdyYWQuaW8nXSwgVkVSU0lPTl1cblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gTWVkaWEgcGxheWVycyBFTkRcbiAgICAgICAgICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGNwdSA6IFtbXG5cbiAgICAgICAgICAgIC8oPzooYW1kfHgoPzooPzo4Nnw2NClbXy1dKT98d293fHdpbik2NClbO1xcKV0vaSAgICAgICAgICAgICAgICAgICAgIC8vIEFNRDY0XG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2FtZDY0J11dLCBbXG5cbiAgICAgICAgICAgIC8oaWEzMig/PTspKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUEzMiAocXVpY2t0aW1lKVxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIHV0aWwubG93ZXJpemVdXSwgW1xuXG4gICAgICAgICAgICAvKCg/OmlbMzQ2XXx4KTg2KVs7XFwpXS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQTMyXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2lhMzInXV0sIFtcblxuICAgICAgICAgICAgLy8gUG9ja2V0UEMgbWlzdGFrZW5seSBpZGVudGlmaWVkIGFzIFBvd2VyUENcbiAgICAgICAgICAgIC93aW5kb3dzXFxzKGNlfG1vYmlsZSk7XFxzcHBjOy9pXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2FybSddXSwgW1xuXG4gICAgICAgICAgICAvKCg/OnBwY3xwb3dlcnBjKSg/OjY0KT8pKD86XFxzbWFjfDt8XFwpKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUG93ZXJQQ1xuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIC9vd2VyLywgJycsIHV0aWwubG93ZXJpemVdXSwgW1xuXG4gICAgICAgICAgICAvKHN1bjRcXHcpWztcXCldL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU1BBUkNcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCAnc3BhcmMnXV0sIFtcblxuICAgICAgICAgICAgLygoPzphdnIzMnxpYTY0KD89OykpfDY4ayg/PVxcKSl8YXJtKD86NjR8KD89dlxcZCs7KSl8KD89YXRtZWxcXHMpYXZyfCg/OmlyaXh8bWlwc3xzcGFyYykoPzo2NCk/KD89Oyl8cGEtcmlzYykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQTY0LCA2OEssIEFSTS82NCwgQVZSLzMyLCBJUklYLzY0LCBNSVBTLzY0LCBTUEFSQy82NCwgUEEtUklTQ1xuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIHV0aWwubG93ZXJpemVdXVxuICAgICAgICBdLFxuXG4gICAgICAgIGRldmljZSA6IFtbXG5cbiAgICAgICAgICAgIC9cXCgoaXBhZHxwbGF5Ym9vayk7W1xcd1xcc1xcKTstXSsocmltfGFwcGxlKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQYWQvUGxheUJvb2tcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgVkVORE9SLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FwcGxlY29yZW1lZGlhXFwvW1xcd1xcLl0rIFxcKChpcGFkKS8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVBhZFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQXBwbGUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oYXBwbGVcXHN7MCwxfXR2KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFwcGxlIFRWXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnQXBwbGUgVFYnXSwgW1ZFTkRPUiwgJ0FwcGxlJ11dLCBbXG5cbiAgICAgICAgICAgIC8oYXJjaG9zKVxccyhnYW1lcGFkMj8pL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFyY2hvc1xuICAgICAgICAgICAgLyhocCkuKyh0b3VjaHBhZCkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIUCBUb3VjaFBhZFxuICAgICAgICAgICAgLyhocCkuKyh0YWJsZXQpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIUCBUYWJsZXRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvXFxzKG5vb2spW1xcd1xcc10rYnVpbGRcXC8oXFx3KykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9va1xuICAgICAgICAgICAgLyhkZWxsKVxccyhzdHJlYVtrcHJcXHNcXGRdKltcXGRrb10pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVsbCBTdHJlYWtcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhrZltBLXpdKylcXHNidWlsZFxcLy4rc2lsa1xcLy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLaW5kbGUgRmlyZSBIRFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhzZHxrZilbMDM0OWhpam9yc3R1d10rXFxzYnVpbGRcXC8uK3NpbGtcXC8vaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlIFBob25lXG4gICAgICAgICAgICBdLCBbW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5hbWF6b24ubW9kZWxdLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFwoKGlwW2hvbmVkfFxcc1xcdypdKyk7LisoYXBwbGUpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQb2QvaVBob25lXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFZFTkRPUiwgW1RZUEUsIE1PQklMRV1dLCBbXG4gICAgICAgICAgICAvXFwoKGlwW2hvbmVkfFxcc1xcdypdKyk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQb2QvaVBob25lXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBcHBsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhibGFja2JlcnJ5KVtcXHMtXT8oXFx3KykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnlcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeXxiZW5xfHBhbG0oPz1cXC0pfHNvbnllcmljc3NvbnxhY2VyfGFzdXN8ZGVsbHxtZWl6dXxtb3Rvcm9sYXxwb2x5dHJvbilbXFxzXy1dPyhbXFx3LV0qKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCZW5RL1BhbG0vU29ueS1Fcmljc3Nvbi9BY2VyL0FzdXMvRGVsbC9NZWl6dS9Nb3Rvcm9sYS9Qb2x5dHJvblxuICAgICAgICAgICAgLyhocClcXHMoW1xcd1xcc10rXFx3KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgaVBBUVxuICAgICAgICAgICAgLyhhc3VzKS0/KFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXN1c1xuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL1xcKGJiMTA7XFxzKFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCbGFja0JlcnJ5IDEwXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdCbGFja0JlcnJ5J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBc3VzIFRhYmxldHNcbiAgICAgICAgICAgIC9hbmRyb2lkLisodHJhbnNmb1twcmltZVxcc117NCwxMH1cXHNcXHcrfGVlZXBjfHNsaWRlclxcc1xcdyt8bmV4dXMgN3xwYWRmb25lKS9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBc3VzJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKHNvbnkpXFxzKHRhYmxldFxcc1twc10pXFxzYnVpbGRcXC8vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueVxuICAgICAgICAgICAgLyhzb255KT8oPzpzZ3AuKylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NvbnknXSwgW01PREVMLCAnWHBlcmlhIFRhYmxldCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcbiAgICAgICAgICAgIC9hbmRyb2lkLitcXHMoW2MtZ11cXGR7NH18c29bLWxdXFx3KylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFxzKG91eWEpXFxzL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3V5YVxuICAgICAgICAgICAgLyhuaW50ZW5kbylcXHMoW3dpZHMzdV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG9cbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKHNoaWVsZClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOdmlkaWFcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ052aWRpYSddLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC8ocGxheXN0YXRpb25cXHNbMzRwb3J0YWJsZXZpXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYXlzdGF0aW9uXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBDT05TT0xFXV0sIFtcblxuICAgICAgICAgICAgLyhzcHJpbnRcXHMoXFx3KykpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNwcmludCBQaG9uZXNcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQudmVuZG9yXSwgW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQubW9kZWxdLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhsZW5vdm8pXFxzPyhTKD86NTAwMHw2MDAwKSsoPzpbLV1bXFx3K10pKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92byB0YWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjKVs7X1xccy1dKyhbXFx3XFxzXSsoPz1cXCkpfFxcdyspKi9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIVENcbiAgICAgICAgICAgIC8oenRlKS0oXFx3KikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURVxuICAgICAgICAgICAgLyhhbGNhdGVsfGdlZWtzcGhvbmV8bGVub3ZvfG5leGlhbnxwYW5hc29uaWN8KD89O1xccylzb255KVtfXFxzLV0/KFtcXHctXSopL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxjYXRlbC9HZWVrc1Bob25lL0xlbm92by9OZXhpYW4vUGFuYXNvbmljL1NvbnlcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIFtNT0RFTCwgL18vZywgJyAnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8obmV4dXNcXHM5KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhUQyBOZXh1cyA5XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdIVEMnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9kXFwvaHVhd2VpKFtcXHdcXHMtXSspWztcXCldL2ksXG4gICAgICAgICAgICAvKG5leHVzXFxzNnApL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdWF3ZWlcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0h1YXdlaSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtaWNyb3NvZnQpO1xccyhsdW1pYVtcXHNcXHddKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaWNyb3NvZnQgTHVtaWFcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL1tcXHNcXCg7XSh4Ym94KD86XFxzb25lKT8pW1xcc1xcKTtdL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBYYm94XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNaWNyb3NvZnQnXSwgW1RZUEUsIENPTlNPTEVdXSwgW1xuICAgICAgICAgICAgLyhraW5cXC5bb25ldHddezN9KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWljcm9zb2Z0IEtpblxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgL1xcLi9nLCAnICddLCBbVkVORE9SLCAnTWljcm9zb2Z0J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1vdG9yb2xhXG4gICAgICAgICAgICAvXFxzKG1pbGVzdG9uZXxkcm9pZCg/OlsyLTR4XXxcXHMoPzpiaW9uaWN8eDJ8cHJvfHJhenIpKT86PyhcXHM0Zyk/KVtcXHdcXHNdK2J1aWxkXFwvL2ksXG4gICAgICAgICAgICAvbW90W1xccy1dPyhcXHcqKS9pLFxuICAgICAgICAgICAgLyhYVFxcZHszLDR9KSBidWlsZFxcLy9pLFxuICAgICAgICAgICAgLyhuZXh1c1xcczYpL2lcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01vdG9yb2xhJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuK1xccyhtejYwXFxkfHhvb21bXFxzMl17MCwyfSlcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNb3Rvcm9sYSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2hiYnR2XFwvXFxkK1xcLlxcZCtcXC5cXGQrXFxzK1xcKFtcXHdcXHNdKjtcXHMqKFxcd1teO10qKTsoW147XSopL2kgICAgICAgICAgICAvLyBIYmJUViBkZXZpY2VzXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgdXRpbC50cmltXSwgW01PREVMLCB1dGlsLnRyaW1dLCBbVFlQRSwgU01BUlRUVl1dLCBbXG5cbiAgICAgICAgICAgIC9oYmJ0di4rbWFwbGU7KFxcZCspL2lcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIC9eLywgJ1NtYXJ0VFYnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFNNQVJUVFZdXSwgW1xuXG4gICAgICAgICAgICAvXFwoZHR2W1xcKTtdLisoYXF1b3MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2hhcnBcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1NoYXJwJ10sIFtUWVBFLCBTTUFSVFRWXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKygoc2NoLWlbODldMFxcZHxzaHctbTM4MHN8Z3QtcFxcZHs0fXxndC1uXFxkK3xzZ2gtdDhbNTZdOXxuZXh1cyAxMCkpL2ksXG4gICAgICAgICAgICAvKChTTS1UXFx3KykpL2lcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnU2Ftc3VuZyddLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZ1xuICAgICAgICAgICAgL3NtYXJ0LXR2Lisoc2Ftc3VuZykvaVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgW1RZUEUsIFNNQVJUVFZdLCBNT0RFTF0sIFtcbiAgICAgICAgICAgIC8oKHNbY2dwXWgtXFx3K3xndC1cXHcrfGdhbGF4eVxcc25leHVzfHNtLVxcd1tcXHdcXGRdKykpL2ksXG4gICAgICAgICAgICAvKHNhbVtzdW5nXSopW1xccy1dKihcXHcrLT9bXFx3LV0qKS9pLFxuICAgICAgICAgICAgL3NlYy0oKHNnaFxcdyspKS9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvc2llLShcXHcqKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaWVtZW5zXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTaWVtZW5zJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKG1hZW1vfG5va2lhKS4qKG45MDB8bHVtaWFcXHNcXGQrKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIC8obm9raWEpW1xcc18tXT8oW1xcdy1dKikvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdOb2tpYSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkXFxzM1xcLltcXHNcXHc7LV17MTB9KGFcXGR7M30pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBY2VyXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBY2VyJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKFt2bF1rXFwtP1xcZHszfSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTEcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZFxcczNcXC5bXFxzXFx3Oy1dezEwfShsZz8pLShbMDZjdjldezMsNH0pL2kgICAgICAgICAgICAgICAgICAgICAvLyBMRyBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnTEcnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhsZykgbmV0Y2FzdFxcLnR2L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTEcgU21hcnRUVlxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBTTUFSVFRWXV0sIFtcbiAgICAgICAgICAgIC8obmV4dXNcXHNbNDVdKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHXG4gICAgICAgICAgICAvbGdbZTtcXHNcXC8tXSsoXFx3KikvaSxcbiAgICAgICAgICAgIC9hbmRyb2lkLitsZyhcXC0/W1xcZFxcd10rKVxccytidWlsZC9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdMRyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKyhpZGVhdGFiW2EtejAtOVxcLVxcc10rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92b1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTGVub3ZvJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvbGludXg7LisoKGpvbGxhKSk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEpvbGxhXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8oKHBlYmJsZSkpYXBwXFwvW1xcZFxcLl0rXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBlYmJsZVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBXRUFSQUJMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKG9wcG8pXFxzPyhbXFx3XFxzXSspXFxzYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPUFBPXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9jcmtleS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIENocm9tZWNhc3RcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdDaHJvbWVjYXN0J10sIFtWRU5ET1IsICdHb29nbGUnXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMoZ2xhc3MpXFxzXFxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHb29nbGUgR2xhc3NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dvb2dsZSddLCBbVFlQRSwgV0VBUkFCTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhwaXhlbCBjKVxccy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIFBpeGVsIENcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dvb2dsZSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMocGl4ZWwgeGx8cGl4ZWwpXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdvb2dsZSBQaXhlbFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnR29vZ2xlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhcXHcrKVxccytidWlsZFxcL2htXFwxL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWGlhb21pIEhvbmdtaSAnbnVtZXJpYycgbW9kZWxzXG4gICAgICAgICAgICAvYW5kcm9pZC4rKGhtW1xcc1xcLV9dKm5vdGU/W1xcc19dKig/OlxcZFxcdyk/KVxccytidWlsZC9pLCAgICAgICAgICAgICAgIC8vIFhpYW9taSBIb25nbWlcbiAgICAgICAgICAgIC9hbmRyb2lkLisobWlbXFxzXFwtX10qKD86b25lfG9uZVtcXHNfXXBsdXN8bm90ZSBsdGUpP1tcXHNfXSooPzpcXGQ/XFx3PylbXFxzX10qKD86cGx1cyk/KVxccytidWlsZC9pLCAgICAvLyBYaWFvbWkgTWlcbiAgICAgICAgICAgIC9hbmRyb2lkLisocmVkbWlbXFxzXFwtX10qKD86bm90ZSk/KD86W1xcc19dKltcXHdcXHNdKykpXFxzK2J1aWxkL2kgICAgICAgLy8gUmVkbWkgUGhvbmVzXG4gICAgICAgICAgICBdLCBbW01PREVMLCAvXy9nLCAnICddLCBbVkVORE9SLCAnWGlhb21pJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuKyhtaVtcXHNcXC1fXSooPzpwYWQpKD86W1xcc19dKltcXHdcXHNdKykpXFxzK2J1aWxkL2kgICAgICAgICAgICAvLyBNaSBQYWQgdGFibGV0c1xuICAgICAgICAgICAgXSxbW01PREVMLCAvXy9nLCAnICddLCBbVkVORE9SLCAnWGlhb21pJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMobVsxLTVdXFxzbm90ZSlcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNZWl6dSBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01laXp1J10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rYTAwMCgxKVxccytidWlsZC9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmVQbHVzXG4gICAgICAgICAgICAvYW5kcm9pZC4rb25lcGx1c1xccyhhXFxkezR9KVxccytidWlsZC9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdPbmVQbHVzJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihSQ1RbXFxkXFx3XSspXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUkNBIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1JDQSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXFxzXSsoVmVudWVbXFxkXFxzXXsyLDd9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGwgVmVudWUgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnRGVsbCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooUVtUfE1dW1xcZFxcd10rKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFZlcml6b24gVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdWZXJpem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhCYXJuZXNbJlxcc10rTm9ibGVcXHMrfEJOW1JUXSkoVj8uKilcXHMrYnVpbGQvaSAgICAgLy8gQmFybmVzICYgTm9ibGUgVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0Jhcm5lcyAmIE5vYmxlJ10sIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccysoVE1cXGR7M30uKlxcYilcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJhcm5lcyAmIE5vYmxlIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTnVWaXNpb24nXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKGs4OClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBaVEUgSyBTZXJpZXMgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdaVEUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKGdlblxcZHszfSlcXHMrYnVpbGQuKjQ5aC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN3aXNzIEdFTiBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1N3aXNzJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKih6dXJcXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTd2lzcyBaVVIgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTd2lzcyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooKFpla2kpP1RCLipcXGIpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWmVraSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdaZWtpJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKGFuZHJvaWQpLitbO1xcL11cXHMrKFtZUl1cXGR7Mn0pXFxzK2J1aWxkL2ksXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhEcmFnb25bXFwtXFxzXStUb3VjaFxccyt8RFQpKFxcd3s1fSlcXHNidWlsZC9pICAgICAgICAvLyBEcmFnb24gVG91Y2ggVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0RyYWdvbiBUb3VjaCddLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKE5TLT9cXHd7MCw5fSlcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluc2lnbmlhIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0luc2lnbmlhJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKigoTlh8TmV4dCktP1xcd3swLDl9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAvLyBOZXh0Qm9vayBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdOZXh0Qm9vayddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooWHRyZW1lXFxfKT8oVigxWzA0NV18MlswMTVdfDMwfDQwfDYwfDdbMDVdfDkwKSlcXHMrYnVpbGQvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdWb2ljZSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbICAgICAgICAgICAgICAgICAgICAvLyBWb2ljZSBYdHJlbWUgUGhvbmVzXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKExWVEVMXFwtKT8oVjFbMTJdKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgLy8gTHZUZWwgUGhvbmVzXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0x2VGVsJ10sIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooVigxMDBNRHw3MDBOQXw3MDExfDkxN0cpLipcXGIpXFxzK2J1aWxkL2kgICAgICAgICAgLy8gRW52aXplbiBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdFbnZpemVuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihMZVtcXHNcXC1dK1BhbilbXFxzXFwtXSsoXFx3ezEsOX0pXFxzK2J1aWxkL2kgICAgICAgICAgLy8gTGUgUGFuIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooVHJpb1tcXHNcXC1dKi4qKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hY2hTcGVlZCBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNYWNoU3BlZWQnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFRyaW5pdHkpW1xcLVxcc10qKFRcXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgLy8gVHJpbml0eSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqVFVfKDE0OTEpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUm90b3IgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnUm90b3InXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLisoS1MoLispKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFtYXpvbiBLaW5kbGUgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKEdpZ2FzZXQpW1xcc1xcLV0rKFFcXHd7MSw5fSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAvLyBHaWdhc2V0IFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL1xccyh0YWJsZXR8dGFiKVs7XFwvXS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVuaWRlbnRpZmlhYmxlIFRhYmxldFxuICAgICAgICAgICAgL1xccyhtb2JpbGUpKD86WztcXC9dfFxcc3NhZmFyaSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVbmlkZW50aWZpYWJsZSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtbVFlQRSwgdXRpbC5sb3dlcml6ZV0sIFZFTkRPUiwgTU9ERUxdLCBbXG5cbiAgICAgICAgICAgIC8oYW5kcm9pZFtcXHdcXC5cXHNcXC1dezAsOX0pOy4rYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQW5kcm9pZCBEZXZpY2VcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dlbmVyaWMnXV1cblxuXG4gICAgICAgIC8qLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgICAgICAgIC8vIFRPRE86IG1vdmUgdG8gc3RyaW5nIG1hcFxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAgICAgICAvKEM2NjAzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbnkgWHBlcmlhIFogQzY2MDNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdYcGVyaWEgWiBDNjYwMyddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oQzY5MDMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueSBYcGVyaWEgWiAxXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnWHBlcmlhIFogMSddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhTTS1HOTAwW0Z8SF0pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBTNVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBTNSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzcxMDIpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgR3JhbmQgMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCAyJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1HNTMwSCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBHcmFuZCBQcmltZVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCBQcmltZSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzMxM0haKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBWJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1UODA1KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBUYWIgUyAxMC41XG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiBTIDEwLjUnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvKFNNLUc4MDBGKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhbXN1bmcgR2FsYXh5IFM1IE1pbmlcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdHYWxheHkgUzUgTWluaSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tVDMxMSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVGFiIDMgOC4wXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiAzIDguMCddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhUM0MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBUM0NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBUMUpcXCspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWR2YW4gVmFuZHJvaWQgVDFKK1xuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1ZhbmRyb2lkIFQxSisnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBTNEEpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBTNEFcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdWYW5kcm9pZCBTNEEnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKFY5NzJNKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURSBWOTcyTVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnWlRFJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKGktbW9iaWxlKVxccyhJUVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhJUTYuMykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUSBJUSA2LjNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdJUSA2LjMnXSwgW1ZFTkRPUiwgJ2ktbW9iaWxlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLW1vYmlsZSlcXHMoaS1zdHlsZVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaS1tb2JpbGUgaS1TVFlMRVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLVNUWUxFMi4xKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBpLVNUWUxFIDIuMVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ2ktU1RZTEUgMi4xJ10sIFtWRU5ET1IsICdpLW1vYmlsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1RvdWNoIExBSSA1MTInXSwgW1ZFTkRPUiwgJ21vYmlpc3RhciddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gRU5EIFRPRE9cbiAgICAgICAgICAgIC8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGVuZ2luZSA6IFtbXG5cbiAgICAgICAgICAgIC93aW5kb3dzLitcXHNlZGdlXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVkZ2VIVE1MXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdFZGdlSFRNTCddXSwgW1xuXG4gICAgICAgICAgICAvKHByZXN0bylcXC8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZXN0b1xuICAgICAgICAgICAgLyh3ZWJraXR8dHJpZGVudHxuZXRmcm9udHxuZXRzdXJmfGFtYXlhfGx5bnh8dzNtKVxcLyhbXFx3XFwuXSspL2ksICAgICAvLyBXZWJLaXQvVHJpZGVudC9OZXRGcm9udC9OZXRTdXJmL0FtYXlhL0x5bngvdzNtXG4gICAgICAgICAgICAvKGtodG1sfHRhc21hbnxsaW5rcylbXFwvXFxzXVxcKD8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS0hUTUwvVGFzbWFuL0xpbmtzXG4gICAgICAgICAgICAvKGljYWIpW1xcL1xcc10oWzIzXVxcLltcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaUNhYlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9ydlxcOihbXFx3XFwuXXsxLDl9KS4rKGdlY2tvKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2Vja29cbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXVxuICAgICAgICBdLFxuXG4gICAgICAgIG9zIDogW1tcblxuICAgICAgICAgICAgLy8gV2luZG93cyBiYXNlZFxuICAgICAgICAgICAgL21pY3Jvc29mdFxccyh3aW5kb3dzKVxccyh2aXN0YXx4cCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgKGlUdW5lcylcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyh3aW5kb3dzKVxcc250XFxzNlxcLjI7XFxzKGFybSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBSVFxuICAgICAgICAgICAgLyh3aW5kb3dzXFxzcGhvbmUoPzpcXHNvcykqKVtcXHNcXC9dPyhbXFxkXFwuXFxzXFx3XSopL2ksICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgUGhvbmVcbiAgICAgICAgICAgIC8od2luZG93c1xcc21vYmlsZXx3aW5kb3dzKVtcXHNcXC9dPyhbbnRjZVxcZFxcLlxcc10rXFx3KS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgW1ZFUlNJT04sIG1hcHBlci5zdHIsIG1hcHMub3Mud2luZG93cy52ZXJzaW9uXV0sIFtcbiAgICAgICAgICAgIC8od2luKD89M3w5fG4pfHdpblxcczl4XFxzKShbbnRcXGRcXC5dKykvaVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnV2luZG93cyddLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5vcy53aW5kb3dzLnZlcnNpb25dXSwgW1xuXG4gICAgICAgICAgICAvLyBNb2JpbGUvRW1iZWRkZWQgT1NcbiAgICAgICAgICAgIC9cXCgoYmIpKDEwKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnkgMTBcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0JsYWNrQmVycnknXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeSlcXHcqXFwvPyhbXFx3XFwuXSopL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrYmVycnlcbiAgICAgICAgICAgIC8odGl6ZW4pW1xcL1xcc10oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRpemVuXG4gICAgICAgICAgICAvKGFuZHJvaWR8d2Vib3N8cGFsbVxcc29zfHFueHxiYWRhfHJpbVxcc3RhYmxldFxcc29zfG1lZWdvfGNvbnRpa2kpW1xcL1xccy1dPyhbXFx3XFwuXSopL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFuZHJvaWQvV2ViT1MvUGFsbS9RTlgvQmFkYS9SSU0vTWVlR28vQ29udGlraVxuICAgICAgICAgICAgL2xpbnV4Oy4rKHNhaWxmaXNoKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYWlsZmlzaCBPU1xuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKHN5bWJpYW5cXHM/b3N8c3ltYm9zfHM2MCg/PTspKVtcXC9cXHMtXT8oW1xcd1xcLl0qKS9pICAgICAgICAgICAgICAgICAgLy8gU3ltYmlhblxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU3ltYmlhbiddLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgL1xcKChzZXJpZXM0MCk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2VyaWVzIDQwXG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcbiAgICAgICAgICAgIC9tb3ppbGxhLitcXChtb2JpbGU7LitnZWNrby4rZmlyZWZveC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0ZpcmVmb3ggT1MnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gQ29uc29sZVxuICAgICAgICAgICAgLyhuaW50ZW5kb3xwbGF5c3RhdGlvbilcXHMoW3dpZHMzNHBvcnRhYmxldnVdKykvaSwgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG8vUGxheXN0YXRpb25cblxuICAgICAgICAgICAgLy8gR05VL0xpbnV4IGJhc2VkXG4gICAgICAgICAgICAvKG1pbnQpW1xcL1xcc1xcKF0/KFxcdyopL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaW50XG4gICAgICAgICAgICAvKG1hZ2VpYXx2ZWN0b3JsaW51eClbO1xcc10vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWdlaWEvVmVjdG9yTGludXhcbiAgICAgICAgICAgIC8oam9saXxba3hsbl0/dWJ1bnR1fGRlYmlhbnxzdXNlfG9wZW5zdXNlfGdlbnRvb3woPz1cXHMpYXJjaHxzbGFja3dhcmV8ZmVkb3JhfG1hbmRyaXZhfGNlbnRvc3xwY2xpbnV4b3N8cmVkaGF0fHplbndhbGt8bGlucHVzKVtcXC9cXHMtXT8oPyFjaHJvbSkoW1xcd1xcLi1dKikvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSm9saS9VYnVudHUvRGViaWFuL1NVU0UvR2VudG9vL0FyY2gvU2xhY2t3YXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZlZG9yYS9NYW5kcml2YS9DZW50T1MvUENMaW51eE9TL1JlZEhhdC9aZW53YWxrL0xpbnB1c1xuICAgICAgICAgICAgLyhodXJkfGxpbnV4KVxccz8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdXJkL0xpbnV4XG4gICAgICAgICAgICAvKGdudSlcXHM/KFtcXHdcXC5dKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdOVVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oY3JvcylcXHNbXFx3XStcXHMoW1xcd1xcLl0rXFx3KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21pdW0gT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0Nocm9taXVtIE9TJ10sIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgLyhzdW5vcylcXHM/KFtcXHdcXC5cXGRdKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU29sYXJpcyddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBCU0QgYmFzZWRcbiAgICAgICAgICAgIC9cXHMoW2ZyZW50b3BjLV17MCw0fWJzZHxkcmFnb25mbHkpXFxzPyhbXFx3XFwuXSopL2kgICAgICAgICAgICAgICAgICAgIC8vIEZyZWVCU0QvTmV0QlNEL09wZW5CU0QvUEMtQlNEL0RyYWdvbkZseVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLyhoYWlrdSlcXHMoXFx3KykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhhaWt1XG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sW1xuXG4gICAgICAgICAgICAvY2ZuZXR3b3JrXFwvLitkYXJ3aW4vaSxcbiAgICAgICAgICAgIC9pcFtob25lYWRdezIsNH0oPzouKm9zXFxzKFtcXHddKylcXHNsaWtlXFxzbWFjfDtcXHNvcGVyYSkvaSAgICAgICAgICAgICAvLyBpT1NcbiAgICAgICAgICAgIF0sIFtbVkVSU0lPTiwgL18vZywgJy4nXSwgW05BTUUsICdpT1MnXV0sIFtcblxuICAgICAgICAgICAgLyhtYWNcXHNvc1xcc3gpXFxzPyhbXFx3XFxzXFwuXSopL2ksXG4gICAgICAgICAgICAvKG1hY2ludG9zaHxtYWMoPz1fcG93ZXJwYylcXHMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWMgT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ01hYyBPUyddLCBbVkVSU0lPTiwgL18vZywgJy4nXV0sIFtcblxuICAgICAgICAgICAgLy8gT3RoZXJcbiAgICAgICAgICAgIC8oKD86b3Blbik/c29sYXJpcylbXFwvXFxzLV0/KFtcXHdcXC5dKikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbGFyaXNcbiAgICAgICAgICAgIC8oYWl4KVxccygoXFxkKSg/PVxcLnxcXCl8XFxzKVtcXHdcXC5dKSovaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFJWFxuICAgICAgICAgICAgLyhwbGFuXFxzOXxtaW5peHxiZW9zfG9zXFwvMnxhbWlnYW9zfG1vcnBob3N8cmlzY1xcc29zfG9wZW52bXMpL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYW45L01pbml4L0JlT1MvT1MyL0FtaWdhT1MvTW9ycGhPUy9SSVNDT1MvT3BlblZNU1xuICAgICAgICAgICAgLyh1bml4KVxccz8oW1xcd1xcLl0qKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVTklYXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cbiAgICAgICAgXVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQ29uc3RydWN0b3JcbiAgICAvLy8vLy8vLy8vLy8vLy8vXG4gICAgLypcbiAgICB2YXIgQnJvd3NlciA9IGZ1bmN0aW9uIChuYW1lLCB2ZXJzaW9uKSB7XG4gICAgICAgIHRoaXNbTkFNRV0gPSBuYW1lO1xuICAgICAgICB0aGlzW1ZFUlNJT05dID0gdmVyc2lvbjtcbiAgICB9O1xuICAgIHZhciBDUFUgPSBmdW5jdGlvbiAoYXJjaCkge1xuICAgICAgICB0aGlzW0FSQ0hJVEVDVFVSRV0gPSBhcmNoO1xuICAgIH07XG4gICAgdmFyIERldmljZSA9IGZ1bmN0aW9uICh2ZW5kb3IsIG1vZGVsLCB0eXBlKSB7XG4gICAgICAgIHRoaXNbVkVORE9SXSA9IHZlbmRvcjtcbiAgICAgICAgdGhpc1tNT0RFTF0gPSBtb2RlbDtcbiAgICAgICAgdGhpc1tUWVBFXSA9IHR5cGU7XG4gICAgfTtcbiAgICB2YXIgRW5naW5lID0gQnJvd3NlcjtcbiAgICB2YXIgT1MgPSBCcm93c2VyO1xuICAgICovXG4gICAgdmFyIFVBUGFyc2VyID0gZnVuY3Rpb24gKHVhc3RyaW5nLCBleHRlbnNpb25zKSB7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB1YXN0cmluZyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGV4dGVuc2lvbnMgPSB1YXN0cmluZztcbiAgICAgICAgICAgIHVhc3RyaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFVBUGFyc2VyKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBVQVBhcnNlcih1YXN0cmluZywgZXh0ZW5zaW9ucykuZ2V0UmVzdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdWEgPSB1YXN0cmluZyB8fCAoKHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yICYmIHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50KSA/IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50IDogRU1QVFkpO1xuICAgICAgICB2YXIgcmd4bWFwID0gZXh0ZW5zaW9ucyA/IHV0aWwuZXh0ZW5kKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIDogcmVnZXhlcztcbiAgICAgICAgLy92YXIgYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgIC8vdmFyIGNwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgLy92YXIgZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAvL3ZhciBlbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgIC8vdmFyIG9zID0gbmV3IE9TKCk7XG5cbiAgICAgICAgdGhpcy5nZXRCcm93c2VyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGJyb3dzZXIgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoYnJvd3NlciwgdWEsIHJneG1hcC5icm93c2VyKTtcbiAgICAgICAgICAgIGJyb3dzZXIubWFqb3IgPSB1dGlsLm1ham9yKGJyb3dzZXIudmVyc2lvbik7IC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgICAgIHJldHVybiBicm93c2VyO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENQVSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjcHUgPSB7IGFyY2hpdGVjdHVyZTogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoY3B1LCB1YSwgcmd4bWFwLmNwdSk7XG4gICAgICAgICAgICByZXR1cm4gY3B1O1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldERldmljZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBkZXZpY2UgPSB7IHZlbmRvcjogdW5kZWZpbmVkLCBtb2RlbDogdW5kZWZpbmVkLCB0eXBlOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChkZXZpY2UsIHVhLCByZ3htYXAuZGV2aWNlKTtcbiAgICAgICAgICAgIHJldHVybiBkZXZpY2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0RW5naW5lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVuZ2luZSA9IHsgbmFtZTogdW5kZWZpbmVkLCB2ZXJzaW9uOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChlbmdpbmUsIHVhLCByZ3htYXAuZW5naW5lKTtcbiAgICAgICAgICAgIHJldHVybiBlbmdpbmU7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0T1MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgb3MgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwob3MsIHVhLCByZ3htYXAub3MpO1xuICAgICAgICAgICAgcmV0dXJuIG9zO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldFJlc3VsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdWEgICAgICA6IHRoaXMuZ2V0VUEoKSxcbiAgICAgICAgICAgICAgICBicm93c2VyIDogdGhpcy5nZXRCcm93c2VyKCksXG4gICAgICAgICAgICAgICAgZW5naW5lICA6IHRoaXMuZ2V0RW5naW5lKCksXG4gICAgICAgICAgICAgICAgb3MgICAgICA6IHRoaXMuZ2V0T1MoKSxcbiAgICAgICAgICAgICAgICBkZXZpY2UgIDogdGhpcy5nZXREZXZpY2UoKSxcbiAgICAgICAgICAgICAgICBjcHUgICAgIDogdGhpcy5nZXRDUFUoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRVQSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB1YTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZXRVQSA9IGZ1bmN0aW9uICh1YXN0cmluZykge1xuICAgICAgICAgICAgdWEgPSB1YXN0cmluZztcbiAgICAgICAgICAgIC8vYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgICAgICAvL2NwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgICAgIC8vZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAgICAgLy9lbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgICAgICAvL29zID0gbmV3IE9TKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIFVBUGFyc2VyLlZFUlNJT04gPSBMSUJWRVJTSU9OO1xuICAgIFVBUGFyc2VyLkJST1dTRVIgPSB7XG4gICAgICAgIE5BTUUgICAgOiBOQU1FLFxuICAgICAgICBNQUpPUiAgIDogTUFKT1IsIC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgVkVSU0lPTiA6IFZFUlNJT05cbiAgICB9O1xuICAgIFVBUGFyc2VyLkNQVSA9IHtcbiAgICAgICAgQVJDSElURUNUVVJFIDogQVJDSElURUNUVVJFXG4gICAgfTtcbiAgICBVQVBhcnNlci5ERVZJQ0UgPSB7XG4gICAgICAgIE1PREVMICAgOiBNT0RFTCxcbiAgICAgICAgVkVORE9SICA6IFZFTkRPUixcbiAgICAgICAgVFlQRSAgICA6IFRZUEUsXG4gICAgICAgIENPTlNPTEUgOiBDT05TT0xFLFxuICAgICAgICBNT0JJTEUgIDogTU9CSUxFLFxuICAgICAgICBTTUFSVFRWIDogU01BUlRUVixcbiAgICAgICAgVEFCTEVUICA6IFRBQkxFVCxcbiAgICAgICAgV0VBUkFCTEU6IFdFQVJBQkxFLFxuICAgICAgICBFTUJFRERFRDogRU1CRURERURcbiAgICB9O1xuICAgIFVBUGFyc2VyLkVOR0lORSA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICBVQVBhcnNlci5PUyA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICAvL1VBUGFyc2VyLlV0aWxzID0gdXRpbDtcblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gRXhwb3J0XG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICAvLyBjaGVjayBqcyBlbnZpcm9ubWVudFxuICAgIGlmICh0eXBlb2YoZXhwb3J0cykgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgLy8gbm9kZWpzIGVudlxuICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gVU5ERUZfVFlQRSAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogdGVzdCEhISEhISEhXG4gICAgICAgIC8qXG4gICAgICAgIGlmIChyZXF1aXJlICYmIHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlICYmIHByb2Nlc3MpIHtcbiAgICAgICAgICAgIC8vIGNsaVxuICAgICAgICAgICAgdmFyIGpzb25pemUgPSBmdW5jdGlvbiAoYXJyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gYXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wdXNoKG5ldyBVQVBhcnNlcihhcnJbaV0pLmdldFJlc3VsdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoSlNPTi5zdHJpbmdpZnkocmVzLCBudWxsLCAyKSArICdcXG4nKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAocHJvY2Vzcy5zdGRpbi5pc1RUWSkge1xuICAgICAgICAgICAgICAgIC8vIHZpYSBhcmdzXG4gICAgICAgICAgICAgICAganNvbml6ZShwcm9jZXNzLmFyZ3Yuc2xpY2UoMikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB2aWEgcGlwZVxuICAgICAgICAgICAgICAgIHZhciBzdHIgPSAnJztcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdyZWFkYWJsZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVhZCA9IHByb2Nlc3Muc3RkaW4ucmVhZCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVhZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyICs9IHJlYWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGpzb25pemUoc3RyLnJlcGxhY2UoL1xcbiQvLCAnJykuc3BsaXQoJ1xcbicpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICBleHBvcnRzLlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVxdWlyZWpzIGVudiAob3B0aW9uYWwpXG4gICAgICAgIGlmICh0eXBlb2YoZGVmaW5lKSA9PT0gRlVOQ19UWVBFICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFVBUGFyc2VyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAod2luZG93KSB7XG4gICAgICAgICAgICAvLyBicm93c2VyIGVudlxuICAgICAgICAgICAgd2luZG93LlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBqUXVlcnkvWmVwdG8gc3BlY2lmaWMgKG9wdGlvbmFsKVxuICAgIC8vIE5vdGU6XG4gICAgLy8gICBJbiBBTUQgZW52IHRoZSBnbG9iYWwgc2NvcGUgc2hvdWxkIGJlIGtlcHQgY2xlYW4sIGJ1dCBqUXVlcnkgaXMgYW4gZXhjZXB0aW9uLlxuICAgIC8vICAgalF1ZXJ5IGFsd2F5cyBleHBvcnRzIHRvIGdsb2JhbCBzY29wZSwgdW5sZXNzIGpRdWVyeS5ub0NvbmZsaWN0KHRydWUpIGlzIHVzZWQsXG4gICAgLy8gICBhbmQgd2Ugc2hvdWxkIGNhdGNoIHRoYXQuXG4gICAgdmFyICQgPSB3aW5kb3cgJiYgKHdpbmRvdy5qUXVlcnkgfHwgd2luZG93LlplcHRvKTtcbiAgICBpZiAodHlwZW9mICQgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgdmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcigpO1xuICAgICAgICAkLnVhID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAkLnVhLmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZXIuZ2V0VUEoKTtcbiAgICAgICAgfTtcbiAgICAgICAgJC51YS5zZXQgPSBmdW5jdGlvbiAodWFzdHJpbmcpIHtcbiAgICAgICAgICAgIHBhcnNlci5zZXRVQSh1YXN0cmluZyk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAkLnVhW3Byb3BdID0gcmVzdWx0W3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxufSkodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgPyB3aW5kb3cgOiB0aGlzKTtcbiIsInZhciB2MSA9IHJlcXVpcmUoJy4vdjEnKTtcbnZhciB2NCA9IHJlcXVpcmUoJy4vdjQnKTtcblxudmFyIHV1aWQgPSB2NDtcbnV1aWQudjEgPSB2MTtcbnV1aWQudjQgPSB2NDtcblxubW9kdWxlLmV4cG9ydHMgPSB1dWlkO1xuIiwiLyoqXG4gKiBDb252ZXJ0IGFycmF5IG9mIDE2IGJ5dGUgdmFsdWVzIHRvIFVVSUQgc3RyaW5nIGZvcm1hdCBvZiB0aGUgZm9ybTpcbiAqIFhYWFhYWFhYLVhYWFgtWFhYWC1YWFhYLVhYWFhYWFhYWFhYWFxuICovXG52YXIgYnl0ZVRvSGV4ID0gW107XG5mb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgKytpKSB7XG4gIGJ5dGVUb0hleFtpXSA9IChpICsgMHgxMDApLnRvU3RyaW5nKDE2KS5zdWJzdHIoMSk7XG59XG5cbmZ1bmN0aW9uIGJ5dGVzVG9VdWlkKGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gb2Zmc2V0IHx8IDA7XG4gIHZhciBidGggPSBieXRlVG9IZXg7XG4gIHJldHVybiBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxuXG4vLyBnZXRSYW5kb21WYWx1ZXMgbmVlZHMgdG8gYmUgaW52b2tlZCBpbiBhIGNvbnRleHQgd2hlcmUgXCJ0aGlzXCIgaXMgYSBDcnlwdG8gaW1wbGVtZW50YXRpb24uXG52YXIgZ2V0UmFuZG9tVmFsdWVzID0gKHR5cGVvZihjcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChjcnlwdG8pKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICh0eXBlb2YobXNDcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIG1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKG1zQ3J5cHRvKSk7XG5pZiAoZ2V0UmFuZG9tVmFsdWVzKSB7XG4gIC8vIFdIQVRXRyBjcnlwdG8gUk5HIC0gaHR0cDovL3dpa2kud2hhdHdnLm9yZy93aWtpL0NyeXB0b1xuICB2YXIgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBnZXRSYW5kb21WYWx1ZXMocm5kczgpO1xuICAgIHJldHVybiBybmRzODtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWF0aFJORygpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbi8vICoqYHYxKClgIC0gR2VuZXJhdGUgdGltZS1iYXNlZCBVVUlEKipcbi8vXG4vLyBJbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vTGlvc0svVVVJRC5qc1xuLy8gYW5kIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS91dWlkLmh0bWxcblxudmFyIF9ub2RlSWQ7XG52YXIgX2Nsb2Nrc2VxO1xuXG4vLyBQcmV2aW91cyB1dWlkIGNyZWF0aW9uIHRpbWVcbnZhciBfbGFzdE1TZWNzID0gMDtcbnZhciBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB2YXIgbm9kZSA9IG9wdGlvbnMubm9kZSB8fCBfbm9kZUlkO1xuICB2YXIgY2xvY2tzZXEgPSBvcHRpb25zLmNsb2Nrc2VxICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb2Nrc2VxIDogX2Nsb2Nrc2VxO1xuXG4gIC8vIG5vZGUgYW5kIGNsb2Nrc2VxIG5lZWQgdG8gYmUgaW5pdGlhbGl6ZWQgdG8gcmFuZG9tIHZhbHVlcyBpZiB0aGV5J3JlIG5vdFxuICAvLyBzcGVjaWZpZWQuICBXZSBkbyB0aGlzIGxhemlseSB0byBtaW5pbWl6ZSBpc3N1ZXMgcmVsYXRlZCB0byBpbnN1ZmZpY2llbnRcbiAgLy8gc3lzdGVtIGVudHJvcHkuICBTZWUgIzE4OVxuICBpZiAobm9kZSA9PSBudWxsIHx8IGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICB2YXIgc2VlZEJ5dGVzID0gcm5nKCk7XG4gICAgaWYgKG5vZGUgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuNSwgY3JlYXRlIGFuZCA0OC1iaXQgbm9kZSBpZCwgKDQ3IHJhbmRvbSBiaXRzICsgbXVsdGljYXN0IGJpdCA9IDEpXG4gICAgICBub2RlID0gX25vZGVJZCA9IFtcbiAgICAgICAgc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgICAgICAgc2VlZEJ5dGVzWzFdLCBzZWVkQnl0ZXNbMl0sIHNlZWRCeXRlc1szXSwgc2VlZEJ5dGVzWzRdLCBzZWVkQnl0ZXNbNV1cbiAgICAgIF07XG4gICAgfVxuICAgIGlmIChjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC4yLjIsIHJhbmRvbWl6ZSAoMTQgYml0KSBjbG9ja3NlcVxuICAgICAgY2xvY2tzZXEgPSBfY2xvY2tzZXEgPSAoc2VlZEJ5dGVzWzZdIDw8IDggfCBzZWVkQnl0ZXNbN10pICYgMHgzZmZmO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVVSUQgdGltZXN0YW1wcyBhcmUgMTAwIG5hbm8tc2Vjb25kIHVuaXRzIHNpbmNlIHRoZSBHcmVnb3JpYW4gZXBvY2gsXG4gIC8vICgxNTgyLTEwLTE1IDAwOjAwKS4gIEpTTnVtYmVycyBhcmVuJ3QgcHJlY2lzZSBlbm91Z2ggZm9yIHRoaXMsIHNvXG4gIC8vIHRpbWUgaXMgaGFuZGxlZCBpbnRlcm5hbGx5IGFzICdtc2VjcycgKGludGVnZXIgbWlsbGlzZWNvbmRzKSBhbmQgJ25zZWNzJ1xuICAvLyAoMTAwLW5hbm9zZWNvbmRzIG9mZnNldCBmcm9tIG1zZWNzKSBzaW5jZSB1bml4IGVwb2NoLCAxOTcwLTAxLTAxIDAwOjAwLlxuICB2YXIgbXNlY3MgPSBvcHRpb25zLm1zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1zZWNzIDogbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIHVzZSBjb3VudCBvZiB1dWlkJ3MgZ2VuZXJhdGVkIGR1cmluZyB0aGUgY3VycmVudCBjbG9ja1xuICAvLyBjeWNsZSB0byBzaW11bGF0ZSBoaWdoZXIgcmVzb2x1dGlvbiBjbG9ja1xuICB2YXIgbnNlY3MgPSBvcHRpb25zLm5zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5zZWNzIDogX2xhc3ROU2VjcyArIDE7XG5cbiAgLy8gVGltZSBzaW5jZSBsYXN0IHV1aWQgY3JlYXRpb24gKGluIG1zZWNzKVxuICB2YXIgZHQgPSAobXNlY3MgLSBfbGFzdE1TZWNzKSArIChuc2VjcyAtIF9sYXN0TlNlY3MpLzEwMDAwO1xuXG4gIC8vIFBlciA0LjIuMS4yLCBCdW1wIGNsb2Nrc2VxIG9uIGNsb2NrIHJlZ3Jlc3Npb25cbiAgaWYgKGR0IDwgMCAmJiBvcHRpb25zLmNsb2Nrc2VxID09PSB1bmRlZmluZWQpIHtcbiAgICBjbG9ja3NlcSA9IGNsb2Nrc2VxICsgMSAmIDB4M2ZmZjtcbiAgfVxuXG4gIC8vIFJlc2V0IG5zZWNzIGlmIGNsb2NrIHJlZ3Jlc3NlcyAobmV3IGNsb2Nrc2VxKSBvciB3ZSd2ZSBtb3ZlZCBvbnRvIGEgbmV3XG4gIC8vIHRpbWUgaW50ZXJ2YWxcbiAgaWYgKChkdCA8IDAgfHwgbXNlY3MgPiBfbGFzdE1TZWNzKSAmJiBvcHRpb25zLm5zZWNzID09PSB1bmRlZmluZWQpIHtcbiAgICBuc2VjcyA9IDA7XG4gIH1cblxuICAvLyBQZXIgNC4yLjEuMiBUaHJvdyBlcnJvciBpZiB0b28gbWFueSB1dWlkcyBhcmUgcmVxdWVzdGVkXG4gIGlmIChuc2VjcyA+PSAxMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXVpZC52MSgpOiBDYW5cXCd0IGNyZWF0ZSBtb3JlIHRoYW4gMTBNIHV1aWRzL3NlYycpO1xuICB9XG5cbiAgX2xhc3RNU2VjcyA9IG1zZWNzO1xuICBfbGFzdE5TZWNzID0gbnNlY3M7XG4gIF9jbG9ja3NlcSA9IGNsb2Nrc2VxO1xuXG4gIC8vIFBlciA0LjEuNCAtIENvbnZlcnQgZnJvbSB1bml4IGVwb2NoIHRvIEdyZWdvcmlhbiBlcG9jaFxuICBtc2VjcyArPSAxMjIxOTI5MjgwMDAwMDtcblxuICAvLyBgdGltZV9sb3dgXG4gIHZhciB0bCA9ICgobXNlY3MgJiAweGZmZmZmZmYpICogMTAwMDAgKyBuc2VjcykgJSAweDEwMDAwMDAwMDtcbiAgYltpKytdID0gdGwgPj4+IDI0ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDE2ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfbWlkYFxuICB2YXIgdG1oID0gKG1zZWNzIC8gMHgxMDAwMDAwMDAgKiAxMDAwMCkgJiAweGZmZmZmZmY7XG4gIGJbaSsrXSA9IHRtaCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRtaCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfaGlnaF9hbmRfdmVyc2lvbmBcbiAgYltpKytdID0gdG1oID4+PiAyNCAmIDB4ZiB8IDB4MTA7IC8vIGluY2x1ZGUgdmVyc2lvblxuICBiW2krK10gPSB0bWggPj4+IDE2ICYgMHhmZjtcblxuICAvLyBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGAgKFBlciA0LjIuMiAtIGluY2x1ZGUgdmFyaWFudClcbiAgYltpKytdID0gY2xvY2tzZXEgPj4+IDggfCAweDgwO1xuXG4gIC8vIGBjbG9ja19zZXFfbG93YFxuICBiW2krK10gPSBjbG9ja3NlcSAmIDB4ZmY7XG5cbiAgLy8gYG5vZGVgXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgNjsgKytuKSB7XG4gICAgYltpICsgbl0gPSBub2RlW25dO1xuICB9XG5cbiAgcmV0dXJuIGJ1ZiA/IGJ1ZiA6IGJ5dGVzVG9VdWlkKGIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHYxO1xuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuZnVuY3Rpb24gdjQob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG5cbiAgaWYgKHR5cGVvZihvcHRpb25zKSA9PSAnc3RyaW5nJykge1xuICAgIGJ1ZiA9IG9wdGlvbnMgPT09ICdiaW5hcnknID8gbmV3IEFycmF5KDE2KSA6IG51bGw7XG4gICAgb3B0aW9ucyA9IG51bGw7XG4gIH1cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgdmFyIHJuZHMgPSBvcHRpb25zLnJhbmRvbSB8fCAob3B0aW9ucy5ybmcgfHwgcm5nKSgpO1xuXG4gIC8vIFBlciA0LjQsIHNldCBiaXRzIGZvciB2ZXJzaW9uIGFuZCBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGBcbiAgcm5kc1s2XSA9IChybmRzWzZdICYgMHgwZikgfCAweDQwO1xuICBybmRzWzhdID0gKHJuZHNbOF0gJiAweDNmKSB8IDB4ODA7XG5cbiAgLy8gQ29weSBieXRlcyB0byBidWZmZXIsIGlmIHByb3ZpZGVkXG4gIGlmIChidWYpIHtcbiAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgMTY7ICsraWkpIHtcbiAgICAgIGJ1ZltpICsgaWldID0gcm5kc1tpaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZiB8fCBieXRlc1RvVXVpZChybmRzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2NDtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi40IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odGhpcyB8fCB7fSkpO1xuIiwiaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1L09wZW5WaWR1JztcblxuaWYgKHdpbmRvdykge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zdHJpbmctbGl0ZXJhbFxuICAgIHdpbmRvd1snT3BlblZpZHUnXSA9IE9wZW5WaWR1O1xufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0Nvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwnIDogJ1JlbW90ZScpLCAnY2FuZGlkYXRlIGZvcicsXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCwgSlNPTi5zdHJpbmdpZnkoY2FuZGlkYXRlKSk7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdvbkljZUNhbmRpZGF0ZScsIHtcbiAgICAgICAgICAgIGVuZHBvaW50TmFtZTogdGhpcy5jb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IGNhbmRpZGF0ZS5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBjYW5kaWRhdGUuc2RwTUxpbmVJbmRleFxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzZW5kaW5nIElDRSBjYW5kaWRhdGU6ICdcbiAgICAgICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdFJlbW90ZVN0cmVhbXMob3B0aW9uczogU3RyZWFtT3B0aW9uc1NlcnZlcltdKTogdm9pZCB7XG5cbiAgICAgICAgLy8gVGhpcyBpcyByZWFkeSBmb3Igc3VwcG9ydGluZyBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uIG9iamVjdC4gUmlnaHQgbm93IHRoZSBsb29wIHdpbGwgYWx3YXlzIHJ1biBqdXN0IG9uY2VcbiAgICAgICAgLy8gdGhpcy5zdHJlYW0gc2hvdWxkIGFsc28gYmUgcmVwbGFjZWQgYnkgYSBjb2xsZWN0aW9uIG9mIHN0cmVhbXMgdG8gc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uXG4gICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgZnJhbWVSYXRlOiBvcHRzLmZyYW1lUmF0ZSxcbiAgICAgICAgICAgICAgICByZWN2QXVkaW86IG9wdHMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgcmVjdlZpZGVvOiBvcHRzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiBvcHRzLnR5cGVPZlZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLnNlc3Npb24sIHN0cmVhbU9wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJSZW1vdGUgJ0Nvbm5lY3Rpb24nIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiAnLCB0aGlzLnN0cmVhbS5pbmJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFkZFN0cmVhbShzdHJlYW06IFN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uY29ubmVjdGlvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVTdHJlYW0oc3RyZWFtSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3RyZWFtKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyU3RhdGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL0xvY2FsUmVjb3JkZXJTdGF0ZSc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuXG4gKlxuICogPiBXQVJOSU5HOiBQZXJmb3JtaW5nIGJyb3dzZXIgbG9jYWwgcmVjb3JkaW5nIG9mICoqcmVtb3RlIHN0cmVhbXMqKiBtYXkgY2F1c2Ugc29tZSB0cm91Ymxlcy4gQSBsb25nIHdhaXRpbmcgdGltZSBtYXkgYmUgcmVxdWlyZWQgYWZ0ZXIgY2FsbGluZyBfTG9jYWxSZWNvcmRlci5zdG9wKClfIGluIHRoaXMgY2FzZVxuICovXG5leHBvcnQgY2xhc3MgTG9jYWxSZWNvcmRlciB7XG5cbiAgICBzdGF0ZTogTG9jYWxSZWNvcmRlclN0YXRlO1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uSWQ6IHN0cmluZztcbiAgICBwcml2YXRlIG1lZGlhUmVjb3JkZXI6IGFueTtcbiAgICBwcml2YXRlIGNodW5rczogYW55W10gPSBbXTtcbiAgICBwcml2YXRlIGJsb2I6IEJsb2I7XG4gICAgcHJpdmF0ZSBjb3VudCA9IDA7XG4gICAgcHJpdmF0ZSBpZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3U3JjOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBodG1sUGFyZW50RWxlbWVudElkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXc6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzdHJlYW06IFN0cmVhbSkge1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9ICghIXRoaXMuc3RyZWFtLmNvbm5lY3Rpb24pID8gdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgOiAnZGVmYXVsdC1jb25uZWN0aW9uJztcbiAgICAgICAgdGhpcy5pZCA9IHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnX2xvY2FscmVjb3JkJztcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFN0YXJ0cyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUFEWWAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RhcnRlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVjb3JkKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRyeSB7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZWNvcmQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUFEWVxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLmNsZWFuKClcXCcgb3IgaW5pdCBhIG5ldyBMb2NhbFJlY29yZGVyIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJTdGFydGluZyBsb2NhbCByZWNvcmRpbmcgb2Ygc3RyZWFtICdcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgXCInIG9mIGNvbm5lY3Rpb24gJ1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyBcIidcIik7XG5cblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9wdGlvbnM7XG4gICAgICAgICAgICAgICAgICAgIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA5JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA5JyB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA4JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA4JyB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdVc2luZyBtaW1lVHlwZSAnICsgb3B0aW9ucy5taW1lVHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCksIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignaXNUeXBlU3VwcG9ydGVkIGlzIG5vdCBzdXBwb3J0ZWQsIHVzaW5nIGRlZmF1bHQgY29kZWNzIGZvciBicm93c2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdGFydCgxMCk7XG5cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25kYXRhYXZhaWxhYmxlID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUuZGF0YSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25lcnJvciA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBlcnJvcjogJywgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdGFydCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdGFydGVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25wYXVzZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBwYXVzZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucmVzdW1lID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHJlc3VtZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ud2FybmluZyA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgd2FybmluZzogJyArIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBFbmRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2Agb3IgYFBBVVNFRGAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYEZJTklTSEVEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdG9wcGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBzdG9wKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyBvciBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdG9wKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFBhdXNlcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBQQVVTRURgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSBwYXVzZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHBhdXNlKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQucGF1c2UoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIG9yIFxcJ0xvY2FsUmVjb3JkZXIucmVzdW1lKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucGF1c2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzdW1lcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSByZXN1bWVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZXN1bWUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZXN1bWUoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5wYXVzZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnJlc3VtZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByZXZpZXdzIHRoZSByZWNvcmRpbmcsIGFwcGVuZGluZyBhIG5ldyBIVE1MVmlkZW9FbGVtZW50IHRvIGVsZW1lbnQgd2l0aCBpZCBgcGFyZW50SWRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgcHJldmlldyhwYXJlbnRFbGVtZW50KTogSFRNTFZpZGVvRWxlbWVudCB7XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5wcmV2aWV3KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmlkID0gdGhpcy5pZDtcbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuYXV0b3BsYXkgPSB0cnVlO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcGFyZW50RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhcmVudEVsZW1lbnREb20gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRFbGVtZW50KTtcbiAgICAgICAgICAgIGlmIChwYXJlbnRFbGVtZW50RG9tKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50RG9tLmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQuaWQ7XG4gICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuc3JjID0gdGhpcy52aWRlb1ByZXZpZXdTcmM7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9QcmV2aWV3O1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogR3JhY2VmdWxseSBzdG9wcyBhbmQgY2xlYW5zIHRoZSBjdXJyZW50IHJlY29yZGluZyAoV0FSTklORzogaXQgaXMgY29tcGxldGVseSBkaXNtaXNzZWQpLiBTZXRzIFtbc3RhdGVdXSB0byBgUkVBRFlgIHNvIHRoZSByZWNvcmRpbmcgY2FuIHN0YXJ0IGFnYWluXG4gICAgICovXG4gICAgY2xlYW4oKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGYgPSAoKSA9PiB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5ibG9iO1xuICAgICAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubWVkaWFSZWNvcmRlcjtcbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcCgpLnRoZW4oKCkgPT4gZigpKS5jYXRjaCgoKSA9PiBmKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBEb3dubG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIHRocm91Z2ggdGhlIGJyb3dzZXIuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBkb3dubG9hZCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5kb3dubG9hZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGE6IEhUTUxBbmNob3JFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICAgICAgYS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgICAgIGEuZG93bmxvYWQgPSB0aGlzLmlkICsgJy53ZWJtJztcbiAgICAgICAgICAgIGEuY2xpY2soKTtcbiAgICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSByYXcgQmxvYiBmaWxlLiBNZXRob2RzIHByZXZpZXcsIGRvd25sb2FkLCB1cGxvYWRBc0JpbmFyeSBhbmQgdXBsb2FkQXNNdWx0aXBhcnRmaWxlIHVzZSB0aGlzIHNhbWUgZmlsZSB0byBwZXJmb3JtIHRoZWlyIHNwZWNpZmljIGFjdGlvbnMuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBnZXRCbG9iKCk6IEJsb2Ige1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ0NhbGwgXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIGJlZm9yZSBnZXR0aW5nIEJsb2IgZmlsZScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJsb2I7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgYmluYXJ5IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3RcbiAgICAgKi9cbiAgICB1cGxvYWRBc0JpbmFyeShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzQmluYXJ5KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGh0dHAuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHRoaXMuYmxvYik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBsb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gYXMgYSBtdWx0aXBhcnQgZmlsZSBwZXJmb3JtaW5nIGFuIEhUVFAvUE9TVCBvcGVyYXRpb24gdG8gVVJMIGBlbmRwb2ludGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGAuIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBjYW4gYmUgcGFzc2VkIGFzIHNlY29uZCBwYXJhbWV0ZXIuIEZvciBleGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHZhciBoZWFkZXJzID0ge1xuICAgICAqICBcIkNvb2tpZVwiOiBcIiRWZXJzaW9uPTE7IFNraW49bmV3O1wiLFxuICAgICAqICBcIkF1dGhvcml6YXRpb25cIjpcIkJhc2ljIFFXeGhaR3BianB1SUhObGN0WlE9PVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB3aXRoIHRoZSBgaHR0cC5yZXNwb25zZVRleHRgIGZyb20gc2VydmVyIGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggdGhlIGZhaWxlZCBgaHR0cC5zdGF0dXNgIGlmIG5vdDpcbiAgICAgKi9cbiAgICB1cGxvYWRBc011bHRpcGFydGZpbGUoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc011bHRpcGFydGZpbGUoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3Qgc2VuZGFibGUgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgICAgICAgICBzZW5kYWJsZS5hcHBlbmQoJ2ZpbGUnLCB0aGlzLmJsb2IsIHRoaXMuaWQgKyAnLndlYm0nKTtcblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGh0dHAuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBodHRwLnNlbmQoc2VuZGFibGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBvblN0b3BEZWZhdWx0KCk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdG9wcGVkICAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG5cbiAgICAgICAgdGhpcy5ibG9iID0gbmV3IEJsb2IodGhpcy5jaHVua3MsIHsgdHlwZTogJ3ZpZGVvL3dlYm0nIH0pO1xuICAgICAgICB0aGlzLmNodW5rcyA9IFtdO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3U3JjID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEO1xuICAgIH1cblxufVxuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyIH0gZnJvbSAnLi9Mb2NhbFJlY29yZGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4vUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBScGNCdWlsZGVyIGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYyc7XG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbi8qKlxuICogRW50cnlwb2ludCBvZiBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKiBVc2UgaXQgdG8gaW5pdGlhbGl6ZSBvYmplY3RzIG9mIHR5cGUgW1tTZXNzaW9uXV0sIFtbUHVibGlzaGVyXV0gYW5kIFtbTG9jYWxSZWNvcmRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgcHJpdmF0ZSBqc29uUnBjQ2xpZW50OiBhbnk7XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlc3Npb246IFNlc3Npb247XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICB3c1VyaTogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VjcmV0ID0gJyc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByZWNvcmRlciA9IGZhbHNlO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgYWR2YW5jZWRDb25maWd1cmF0aW9uOiBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGNvbnNvbGUuaW5mbyhcIidPcGVuVmlkdScgaW5pdGlhbGl6ZWRcIik7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIG5ldyBzZXNzaW9uXG4gICAqL1xuICBpbml0U2Vzc2lvbigpOiBTZXNzaW9uIHtcbiAgICB0aGlzLnNlc3Npb24gPSBuZXcgU2Vzc2lvbih0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uO1xuICB9XG5cblxuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgcHVibGlzaGVyXG4gICAqXG4gICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0RpYWxvZ09wZW5lZGAgZXZlbnQsIG9ubHkgaWYgdGhlIHBvcC11cCBzaG93biBieSB0aGUgYnJvd3NlciB0byByZXF1ZXN0IHBlcm1pc3Npb25zIGZvciB0aGUgY2FtZXJhIGlzIG9wZW5lZC4gWW91IGNhbiB1c2UgdGhpcyBldmVudCB0byBhbGVydCB0aGUgdXNlciBhYm91dCBncmFudGluZyBwZXJtaXNzaW9uc1xuICAgKiBmb3IgeW91ciB3ZWJzaXRlLiBBbiBgYWNjZXNzRGlhbG9nQ2xvc2VkYCBldmVudCB3aWxsIGFsc28gYmUgZGlzcGF0Y2hlZCBhZnRlciB1c2VyIGNsaWNrcyBvbiBcIkFsbG93XCIgb3IgXCJCbG9ja1wiIGluIHRoZSBwb3AtdXAuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NBbGxvd2VkYCBvciBgYWNjZXNzRGVuaWVkYCBldmVudCBvbmNlIGl0IGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3QuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgYSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIGxvY2FsIHN0cmVhbXMgc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50ICBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgUHVibGlzaGVyLlxuICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1B1Ymxpc2hlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1B1Ymxpc2hlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgaW5pdFB1Ymxpc2hlcmAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgYGNvbXBsZXRpb25IYW5kbGVyYCBmdW5jdGlvbiBpcyBjYWxsZWQgYmVmb3JlIHRoZSBQdWJsaXNoZXIgZGlzcGF0Y2hlcyBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYW4gYGFjY2Vzc0RlbmllZGAgZXZlbnRcbiAgICovXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMj8sIHBhcmFtMz8pOiBQdWJsaXNoZXIge1xuXG4gICAgbGV0IHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXM7XG5cbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgIT09ICdmdW5jdGlvbicpKSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9ICg8UHVibGlzaGVyUHJvcGVydGllcz5wYXJhbTIpO1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBhdWRpb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlIDogdW5kZWZpbmVkLFxuICAgICAgICBmcmFtZVJhdGU6IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5mcmFtZVJhdGUgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuZnJhbWVSYXRlIDogdW5kZWZpbmVkKSxcbiAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3Byb3BlcnRpZXMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiAodHlwZW9mIHByb3BlcnRpZXMubWlycm9yICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLm1pcnJvciA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaFZpZGVvIDogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogdGhpcy5pc01lZGlhU3RyZWFtVHJhY2socHJvcGVydGllcy52aWRlb1NvdXJjZSkgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLnJlc29sdXRpb24gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucmVzb2x1dGlvbiA6ICc2NDB4NDgwJyksXG4gICAgICAgIHZpZGVvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgOiB1bmRlZmluZWRcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50KScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiAnNjQweDQ4MCdcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgcHVibGlzaGVyOiBQdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIHRoaXMpO1xuXG4gICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0yO1xuICAgIH0gZWxzZSBpZiAoISFwYXJhbTMpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgIH1cblxuICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgfSk7XG5cbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lICE9PSAnRmlyZWZveCcpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVELCAnWW91IGNhbiBvbmx5IHNjcmVlbiBzaGFyZSBpbiBkZXNrdG9wIENocm9tZSBhbmQgRmlyZWZveC4gRGV0ZWN0ZWQgYnJvd3NlcjogJyArIHBsYXRmb3JtLm5hbWUpO1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24pIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbi5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbklkLCAoc3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWVuYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0U2NyZWVuQ29uc3RyYWludHMoKGVycm9yLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yICYmIGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICg8c3RyaW5nPnRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uKSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9zY3JlZW4tY2FwdHVyaW5nL2FqaGlmZGRpbWthcGdjaWZnY29kbW1mZGxrbmFoZmZrJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQsICdZb3UgbXVzdCBhbGxvdyBhY2Nlc3MgdG8gb25lIHdpbmRvdyBvZiB5b3VyIGRlc2t0b3AnKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHMudmlkZW87XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID0gJ3NjcmVlbic7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLXN0cmluZy1saXRlcmFsXG4gICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvWydkZXZpY2VJZCddID0geyBleGFjdDogcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSB9O1xuICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzdGFydFdzKG9uQ29ubmVjdFN1Y2NlczogKGVycm9yOiBFcnJvcikgPT4gdm9pZCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIGhlYXJ0YmVhdDogNTAwMCxcbiAgICAgIHNlbmRDbG9zZU1lc3NhZ2U6IGZhbHNlLFxuICAgICAgd3M6IHtcbiAgICAgICAgdXJpOiB0aGlzLndzVXJpLFxuICAgICAgICB1c2VTb2NrSlM6IGZhbHNlLFxuICAgICAgICBvbmNvbm5lY3RlZDogb25Db25uZWN0U3VjY2VzLFxuICAgICAgICBvbmRpc2Nvbm5lY3Q6IHRoaXMuZGlzY29ubmVjdENhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0aW5nOiB0aGlzLnJlY29ubmVjdGluZ0NhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0ZWQ6IHRoaXMucmVjb25uZWN0ZWRDYWxsYmFjay5iaW5kKHRoaXMpXG4gICAgICB9LFxuICAgICAgcnBjOiB7XG4gICAgICAgIHJlcXVlc3RUaW1lb3V0OiAxNTAwMCxcbiAgICAgICAgcGFydGljaXBhbnRKb2luZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50Sm9pbmVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRQdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50UHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRVbnB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50TGVmdDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRMZWZ0LmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRFdmljdGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEV2aWN0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdGFydGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdGFydGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RvcHBlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RvcHBlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHNlbmRNZXNzYWdlOiB0aGlzLnNlc3Npb24ub25OZXdNZXNzYWdlLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgaWNlQ2FuZGlkYXRlOiB0aGlzLnNlc3Npb24ucmVjdkljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIG1lZGlhRXJyb3I6IHRoaXMuc2Vzc2lvbi5vbk1lZGlhRXJyb3IuYmluZCh0aGlzLnNlc3Npb24pXG4gICAgICB9XG4gICAgfTtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQgPSBuZXcgUnBjQnVpbGRlci5jbGllbnRzLkpzb25ScGNDbGllbnQoY29uZmlnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBjbG9zZVdzKCk6IHZvaWQge1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5jbG9zZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlbmRSZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCBwYXJhbXM6IGFueSwgY2FsbGJhY2s/KTogdm9pZCB7XG4gICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgY2FsbGJhY2sgPSBwYXJhbXM7XG4gICAgICBwYXJhbXMgPSB7fTtcbiAgICB9XG4gICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyByZXF1ZXN0OiB7bWV0aG9kOlwiJyArIG1ldGhvZCArICdcIiwgcGFyYW1zOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSArICd9Jyk7XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50LnNlbmQobWV0aG9kLCBwYXJhbXMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpc01lZGlhU3RyZWFtVHJhY2sobWVkaWFTb3VyY2U6IGFueSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGlzID0gKCEhbWVkaWFTb3VyY2UgJiZcbiAgICAgIG1lZGlhU291cmNlLmVuYWJsZWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuZW5hYmxlZCA9PT0gJ2Jvb2xlYW4nICYmXG4gICAgICBtZWRpYVNvdXJjZS5pZCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5pZCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLmtpbmQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2Uua2luZCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLmxhYmVsICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmxhYmVsID09PSAnc3RyaW5nJyAmJlxuICAgICAgbWVkaWFTb3VyY2UubXV0ZWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UubXV0ZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5yZWFkeVN0YXRlID09PSAnc3RyaW5nJyk7XG4gICAgcmV0dXJuIGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFdzVXJpKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMud3NVcmk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2V0U2VjcmV0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc2VjcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFJlY29yZGVyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnJlY29yZGVyO1xuICB9XG5cblxuICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICBwcml2YXRlIGRpc2Nvbm5lY3RDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGluZ0NhbGxiYWNrKCk6IHZvaWQge1xuICAgIGNvbnNvbGUud2FybignV2Vic29ja2V0IGNvbm5lY3Rpb24gbG9zdCAocmVjb25uZWN0aW5nKScpO1xuICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICB0aGlzLnNlc3Npb24ub25Mb3N0Q29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVjb25uZWN0ZWRDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCByZWNvbm5lY3RlZCcpO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1Jvb21BdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuc2Vzc2lvbiAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc2Vzc2lvbiBpbnN0YW5jZW9mIFNlc3Npb24pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gaW5zdGFuY2Ugbm90IGZvdW5kJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgRXZlbnREaXNwYXRjaGVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9FdmVudERpc3BhdGNoZXInO1xuaW1wb3J0IHsgUHVibGlzaGVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvUHVibGlzaGVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbUV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBwcml2YXRlIG9wZW52aWR1OiBPcGVuVmlkdSkge1xuICAgICAgICBzdXBlcihuZXcgU3RyZWFtKCghIW9wZW52aWR1LnNlc3Npb24pID8gb3BlbnZpZHUuc2Vzc2lvbiA6IG5ldyBTZXNzaW9uKG9wZW52aWR1KSwgeyBwdWJsaXNoZXJQcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLCBtZWRpYUNvbnN0cmFpbnRzOiB7fSB9KSwgdGFyZ0VsKTtcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZC1ieS1kaXNjb25uZWN0JywgKHJlYXNvbjogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgdGhpcy5zdHJlYW0sIHJlYXNvbik7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIGF1ZGlvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoQXVkaW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmF1ZGlvRW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBoYXMgXCIgKyAodmFsdWUgPyAncHVibGlzaGVkJyA6ICd1bnB1Ymxpc2hlZCcpICsgJyBpdHMgYXVkaW8gc3RyZWFtJyk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaFZpZGVvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS52aWRlb0VuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogQ2FsbCB0aGlzIG1ldGhvZCBiZWZvcmUgW1tTZXNzaW9uLnB1Ymxpc2hdXSB0byBzdWJzY3JpYmUgdG8geW91ciBQdWJsaXNoZXIncyByZW1vdGUgc3RyZWFtIGluc3RlYWQgb2YgdXNpbmcgdGhlIGxvY2FsIHN0cmVhbSwgYXMgYW55IG90aGVyIHVzZXIgd291bGQgZG8uXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9SZW1vdGUodmFsdWU/OiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHZhbHVlID0gKHZhbHVlICE9PSB1bmRlZmluZWQpID8gdmFsdWUgOiB0cnVlO1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlZFRvUmVtb3RlID0gdmFsdWU7XG4gICAgICAgIHRoaXMuc3RyZWFtLnN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWUpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICBzdXBlci5vbih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1DcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLm9uKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBlcnJvckNhbGxiYWNrID0gKG9wZW5WaWR1RXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc0NhbGxiYWNrID0gKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmlzTWVkaWFTdHJlYW1UcmFjayh0aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjaygoPE1lZGlhU3RyZWFtVHJhY2s+dGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBBcHBseSBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyBhbmQgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW9cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZW5hYmxlZCA9ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuXG4gICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5maXJzdFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZVZpZGVvRWxlbWVudCh0aGlzLmZpcnN0VmlkZW9FbGVtZW50LnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+dGhpcy5wcm9wZXJ0aWVzLmluc2VydE1vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbjogU2Vzc2lvbik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lZS5nZXRMaXN0ZW5lcnMoJ3N0cmVhbVBsYXlpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ09wZW5lZCcsIFtdKTtcbiAgICAgICAgfSwgd2FpdFRpbWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lOiBudW1iZXIsIHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQpO1xuICAgICAgICBpZiAoKERhdGUubm93KCkgLSBzdGFydFRpbWUpID4gd2FpdFRpbWUpIHtcbiAgICAgICAgICAgIC8vIFBlcm1pc3Npb24gZGlhbG9nIHdhcyBzaG93biBhbmQgbm93IGlzIGNsb3NlZFxuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ0Nsb3NlZCcsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgT2JqTWFwIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT2JqTWFwJztcbmltcG9ydCB7IFNlc3Npb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU2Vzc2lvbk9wdGlvbnMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbkV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvbkV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFJlY29yZGluZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFNpZ25hbEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSB2aWRlbyBjYWxsLiBJdCBjYW4gYWxzbyBiZSBzZWVuIGFzIGEgdmlkZW9jb25mZXJlbmNlIHJvb20gd2hlcmUgbXVsdGlwbGUgdXNlcnMgY2FuIGNvbm5lY3QuXG4gKiBQYXJ0aWNpcGFudHMgd2hvIHB1Ymxpc2ggdGhlaXIgdmlkZW9zIHRvIGEgc2Vzc2lvbiBjYW4gYmUgc2VlbiBieSB0aGUgcmVzdCBvZiB1c2VycyBjb25uZWN0ZWQgdG8gdGhhdCBzcGVjaWZpYyBzZXNzaW9uLlxuICogSW5pdGlhbGl6ZWQgd2l0aCBbW09wZW5WaWR1LmluaXRTZXNzaW9uXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXNzaW9uIGltcGxlbWVudHMgRXZlbnREaXNwYXRjaGVyIHtcblxuICAgIC8qKlxuICAgICAqIExvY2FsIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24uIFRoaXMgb2JqZWN0IGlzIGRlZmluZWQgb25seSBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBleGVjdXRlZCwgYW5kIGNhbiBiZSByZXRyaWV2ZWQgc3Vic2NyaWJpbmcgdG8gYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgU2Vzc2lvblxuICAgICAqL1xuICAgIHNlc3Npb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ29sbGVjdGlvbiBvZiBhbGwgU3RyZWFtTWFuYWdlcnMgb2YgdGhpcyBTZXNzaW9uIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSlcbiAgICAgKi9cbiAgICBzdHJlYW1NYW5hZ2VyczogU3RyZWFtTWFuYWdlcltdID0gW107XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBPYmpNYXA8Ym9vbGVhbj4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVDb25uZWN0aW9uczogT2JqTWFwPENvbm5lY3Rpb24+ID0ge307XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PjtcbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnkpOiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0cyB0byB0aGUgc2Vzc2lvbiB1c2luZyBgdG9rZW5gLiBQYXJhbWV0ZXIgYG1ldGFkYXRhYCBhbGxvd3MgeW91IHRvIHBhc3MgZXh0cmEgZGF0YSB0byBzaGFyZSB3aXRoIG90aGVyIHVzZXJzIHdoZW5cbiAgICAgKiB0aGV5IHJlY2VpdmUgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LiBUaGUgc3RydWN0dXJlIG9mIGBtZXRhZGF0YWAgc3RyaW5nIGlzIHVwIHRvIHlvdSAobWF5YmUgc29tZSBzdGFuZGFyaXplZCBmb3JtYXRcbiAgICAgKiBhcyBKU09OIG9yIFhNTCBpcyBhIGdvb2QgaWRlYSksIHRoZSBvbmx5IHJlc3RyaWN0aW9uIGlzIGEgbWF4aW11bSBsZW5ndGggb2YgMTAwMDAgY2hhcnMuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGFkYXRhIGlzIG5vdCBjb25zaWRlcmVkIHNlY3VyZSwgYXMgaXQgaXMgZ2VuZXJhdGVkIGluIHRoZSBjbGllbnQgc2lkZS4gVG8gcGFzcyBzZWN1cml6ZWQgZGF0YSwgYWRkIGl0IGFzIGEgcGFyYW1ldGVyIGluIHRoZVxuICAgICAqIHRva2VuIGdlbmVyYXRpb24gb3BlcmF0aW9uICh0aHJvdWdoIHRoZSBBUEkgUkVTVCwgb3BlbnZpZHUtamF2YS1jbGllbnQgb3Igb3BlbnZpZHUtbm9kZS1jbGllbnQpLlxuICAgICAqXG4gICAgICogT25seSBhZnRlciB0aGUgcmV0dXJuZWQgUHJvbWlzZSBpcyBzdWNjZXNzZnVsbHkgcmVzb2x2ZWQgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBvYmplY3Qgd2lsbCBiZSBhdmFpbGFibGUgYW5kIHByb3Blcmx5IGRlZmluZWQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGZpcnN0IGRpc3BhdGNoIG9uZSBvciBtb3JlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzIHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZDpcbiAgICAgKiAtIEZpcnN0IG9uZSBmb3IgeW91ciBvd24gbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QsIHNvIHlvdSBjYW4gcmV0cmlldmUgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBwcm9wZXJ0eS5cbiAgICAgKiAtIFRoZW4gb25lIGZvciBlYWNoIHJlbW90ZSBDb25uZWN0aW9uIHByZXZpb3VzbHkgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uLCBpZiBhbnkuIEFueSBvdGhlciByZW1vdGUgdXNlciBjb25uZWN0aW5nIHRvIHRoZSBTZXNzaW9uIGFmdGVyIHlvdSBoYXZlXG4gICAgICogc3VjY2Vzc2Z1bGx5IGNvbm5lY3RlZCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50IHdoZW4gdGhleSBkbyBzby5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBmb3IgZWFjaCByZW1vdGUgYWN0aXZlIFtbUHVibGlzaGVyXV0gdGhhdCB3YXMgYWxyZWFkeSBzdHJlYW1pbmdcbiAgICAgKiB3aGVuIGNvbm5lY3RpbmcsIGp1c3QgYWZ0ZXIgZGlzcGF0Y2hpbmcgYWxsIHJlbW90ZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gYW5kIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIHRvIHdoaWNoIHlvdSBtdXN0IHN1YnNjcmliZSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSB0aGUgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICpcbiAgICAgKi9cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIW1ldGFkYXRhID8gdGhpcy5zdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YSkgOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0QXV4KHRva2VuKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIHBsYXRmb3JtLm5hbWUgKyAnICcgKyBwbGF0Zm9ybS52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCB0byBhdm9pZCB0aGlzIGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgYWxsIHRoZSBTdWJzY3JpYmVyIG9iamVjdHMgeW91cnNlbGYuXG4gICAgICogU2VlIFtbU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGVyZSBpcyBhIFtbUHVibGlzaGVyXV0gb2JqZWN0IHB1Ymxpc2hpbmcgdG8gdGhlIHNlc3Npb24uXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgc3RvcCBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIGlmIHlvdSB3YW50IHRvIGNsZWFuIHRoZSBQdWJsaXNoZXIgb2JqZWN0IG9uIHlvdXIgb3duIG9yIHJlLXB1Ymxpc2ggaXQgaW4gYSBkaWZmZXJlbnQgU2Vzc2lvbiAodG8gZG8gc28gaXQgaXMgYSBtYW5kYXRvcnkgcmVxdWlyZW1lbnQgdG8gY2FsbCBgU2Vzc2lvbi51bnB1Ymxpc2goKWBcbiAgICAgKiBvci9hbmQgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBpbiB0aGUgcHJldmlvdXMgc2Vzc2lvbikuIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBkaXNjb25uZWN0ZWQgcGFydGljaXBhbnQgd2FzIHB1Ymxpc2hpbmcuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBpbiBhbnkgY2FzZS4gU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKi9cbiAgICBkaXNjb25uZWN0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxlYXZlKGZhbHNlLCAnZGlzY29ubmVjdCcpO1xuICAgIH1cblxuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZXMgdG8gYSBgc3RyZWFtYCwgYWRkaW5nIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCB0byBET00gd2l0aCBgc3Vic2NyaWJlclByb3BlcnRpZXNgIHNldHRpbmdzLiBUaGlzIG1ldGhvZCBpcyB1c3VhbGx5IGNhbGxlZCBpbiB0aGUgY2FsbGJhY2sgb2YgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIHJlbW90ZSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc3RyZWFtIFN0cmVhbSBvYmplY3QgdG8gc3Vic2NyaWJlIHRvXG4gICAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tTdWJzY3JpYmVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgU3Vic2NyaWJlci5cbiAgICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1N1YnNjcmliZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24pXG4gICAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYHN1YnNjcmliZWAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgICAqL1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMz86ICgoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSB8IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBwYXJhbTQ/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkpOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgbGV0IHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzID0ge307XG4gICAgICAgIGlmICghIXBhcmFtMyAmJiB0eXBlb2YgcGFyYW0zICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcGFyYW0zLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlID09PSAnc3RyaW5nJykgPyBWaWRlb0luc2VydE1vZGVbcGFyYW0zLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogKHR5cGVvZiBwYXJhbTMuc3Vic2NyaWJlVG9BdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gOiB0cnVlLFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvVmlkZW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvIDogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb0F1ZGlvOiB0cnVlLFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvVmlkZW86IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gICAgICAgIGlmICghIXBhcmFtMyAmJiAodHlwZW9mIHBhcmFtMyA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgICAgICB9IGVsc2UgaWYgKCEhcGFyYW00KSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtNDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJpbmcgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgc3RyZWFtLnN1YnNjcmliZSgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdTdWJzY3JpYmVkIGNvcnJlY3RseSB0byAnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgc3Vic2NyaWJlciA9IG5ldyBTdWJzY3JpYmVyKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyk7XG4gICAgICAgIGlmICghIXN1YnNjcmliZXIudGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgc3RyZWFtLnN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KHN1YnNjcmliZXIudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT5wcm9wZXJ0aWVzLmluc2VydE1vZGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdWJzY3JpYmVyO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW1Nlc3Npb24uc3Vic2NyaWJlXV1cbiAgICAgKi9cbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFN1YnNjcmliZXI+O1xuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBQcm9taXNlPFN1YnNjcmliZXI+O1xuXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzPzogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBQcm9taXNlPFN1YnNjcmliZXI+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPFN1YnNjcmliZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgbGV0IHN1YnNjcmliZXI6IFN1YnNjcmliZXI7XG5cbiAgICAgICAgICAgIGNvbnN0IGNhbGxiYWNrID0gKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShzdWJzY3JpYmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAoISFwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyID0gdGhpcy5zdWJzY3JpYmUoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVbnN1YnNjcmliZXMgZnJvbSBgc3Vic2NyaWJlcmAsIGF1dG9tYXRpY2FsbHkgcmVtb3ZpbmcgaXRzIGFzc29jaWF0ZWQgSFRNTCB2aWRlbyBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50IGZvciBlYWNoIHZpZGVvIGFzc29jaWF0ZWQgdG8gaXQgdGhhdCB3YXMgcmVtb3ZlZCBmcm9tIERPTS5cbiAgICAgKiBPbmx5IHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IHJlbW92ZWRcbiAgICAgKlxuICAgICAqIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZVxuICAgICAqL1xuICAgIHVuc3Vic2NyaWJlKHN1YnNjcmliZXI6IFN1YnNjcmliZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbklkID0gc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQ7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliaW5nIGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICd1bnN1YnNjcmliZUZyb21WaWRlbycsXG4gICAgICAgICAgICB7IHNlbmRlcjogc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgfSxcbiAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgdW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1Vuc3Vic2NyaWJlZCBjb3JyZWN0bHkgZnJvbSAnICsgY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2hlcyB0byB0aGUgU2Vzc2lvbiB0aGUgUHVibGlzaGVyIG9iamVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgdXBvbiBzdWNjZXNzZnVsIHRlcm1pbmF0aW9uIG9mIHRoaXMgbWV0aG9kLiBTZWUgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgbG9jYWwgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBvbmNlIHRoZSBtZWRpYSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHNvIHRoZXkgY2FuIHN1YnNjcmliZSB0byBpdC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHB1Ymxpc2hlciB3YXMgc3VjY2Vzc2Z1bGx5IHB1Ymxpc2hlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcik6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBwdWJsaXNoZXIuc2Vzc2lvbiA9IHRoaXM7XG4gICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnNlc3Npb24gPSB0aGlzO1xuXG4gICAgICAgICAgICBpZiAoIXB1Ymxpc2hlci5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgTk9UIGJlZW4gY2FsbGVkXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZFN0cmVhbShwdWJsaXNoZXIuc3RyZWFtKTtcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gJ1Nlc3Npb24udW5wdWJsaXNoKFB1Ymxpc2hlciknIGhhcyBiZWVuIGNhbGxlZC4gTXVzdCBpbml0aWFsaXplIGFnYWluIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZFN0cmVhbShwdWJsaXNoZXIuc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5yZWVzdGFibGlzaFN0cmVhbVBsYXlpbmdFdmVudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5wdWJsaXNoZXMgZnJvbSB0aGUgU2Vzc2lvbiB0aGUgUHVibGlzaGVyIG9iamVjdC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGlzIFB1Ymxpc2hlclxuICAgICAqIChvbmx5IHRob3NlIHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3VyIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyB0aGUgU3Vic2NyaWJlciBvYmplY3Qgb24geW91ciBvd24uXG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKi9cbiAgICB1bnB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzdHJlYW0gPSBwdWJsaXNoZXIuc3RyZWFtO1xuXG4gICAgICAgIGlmICghc3RyZWFtLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG51bGwnLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHN0cmVhbS5jb25uZWN0aW9uICE9PSB0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG5vdCB5b3VyIGxvY2FsIENvbm5lY3Rpb24uJyArXG4gICAgICAgICAgICAgICAgXCJPbmx5IG1vZGVyYXRvcnMgY2FuIGZvcmNlIHVucHVibGlzaCBvbiByZW1vdGUgU3RyZWFtcyB2aWEgJ2ZvcmNlVW5wdWJsaXNoJyBtZXRob2RcIiwgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnB1Ymxpc2hpbmcgbG9jYWwgbWVkaWEgKCcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgKyAnKScpO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCd1bnB1Ymxpc2hWaWRlbycsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdNZWRpYSB1bnB1Ymxpc2hlZCBjb3JyZWN0bHknKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBkZWxldGUgc3RyZWFtLmNvbm5lY3Rpb24uc3RyZWFtO1xuXG4gICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCBwdWJsaXNoZXIsICdzdHJlYW1EZXN0cm95ZWQnLCBwdWJsaXNoZXIuc3RyZWFtLCAndW5wdWJsaXNoJyk7XG4gICAgICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlbmRzIG9uZSBzaWduYWwuIGBzaWduYWxgIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBvcHRpb25hbCBwcm9wZXJ0aWVzOlxuICAgICAqIGBgYGpzb25cbiAgICAgKiB7ZGF0YTpzdHJpbmcsIHRvOkNvbm5lY3Rpb25bXSwgdHlwZTpzdHJpbmd9XG4gICAgICogYGBgXG4gICAgICogQWxsIHVzZXJzIHN1YnNjcmliZWQgdG8gdGhhdCBzaWduYWwgKGBzZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIC4uLilgIG9yIGBzZXNzaW9uLm9uKCdzaWduYWwnLCAuLi4pYCBmb3IgYWxsIHNpZ25hbHMpIGFuZCB3aG9zZSBDb25uZWN0aW9uIG9iamVjdHMgYXJlIGluIGB0b2AgYXJyYXkgd2lsbCByZWNlaXZlIGl0LiBUaGVpciBsb2NhbFxuICAgICAqIFNlc3Npb24gb2JqZWN0cyB3aWxsIGRpc3BhdGNoIGEgYHNpZ25hbGAgb3IgYHNpZ25hbDp0eXBlYCBldmVudC4gU2VlIFtbU2lnbmFsRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSBtZXNzYWdlIHN1Y2Nlc3NmdWxseSByZWFjaGVkIG9wZW52aWR1LXNlcnZlciBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90LiBfVGhpcyBkb2Vzbid0XG4gICAgICogbWVhbiB0aGF0IG9wZW52aWR1LXNlcnZlciBjb3VsZCByZXNlbmQgdGhlIG1lc3NhZ2UgdG8gYWxsIHRoZSBsaXN0ZWQgcmVjZWl2ZXJzLl9cbiAgICAgKi9cbiAgICAvKiB0c2xpbnQ6ZGlzYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuICAgIHNpZ25hbChzaWduYWw6IFNpZ25hbE9wdGlvbnMpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBzaWduYWxNZXNzYWdlID0ge307XG5cbiAgICAgICAgICAgIGlmIChzaWduYWwudG8gJiYgc2lnbmFsLnRvLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uSWRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgICAgICAgICAgc2lnbmFsLnRvLmZvckVhY2goY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25JZHMucHVzaChjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IGNvbm5lY3Rpb25JZHM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsnZGF0YSddID0gc2lnbmFsLmRhdGEgPyBzaWduYWwuZGF0YSA6ICcnO1xuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndHlwZSddID0gc2lnbmFsLnR5cGUgPyBzaWduYWwudHlwZSA6ICcnO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdzZW5kTWVzc2FnZScsIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBKU09OLnN0cmluZ2lmeShzaWduYWxNZXNzYWdlKVxuICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyogdHNsaW50OmVuYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcblxuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGVuYWJsZSBoYXJrICdzcGVha2luZycgZXZlbnQgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhc3RyLnNwZWVjaEV2ZW50ICYmIHN0ci5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZW5hYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGVuYWJsZSBoYXJrIGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuXG4gICAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnModHlwZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVlLm9mZih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZGlzYWJsYWUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICEhc3RyLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRKb2luZWQocmVzcG9uc2U6IENvbm5lY3Rpb25PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIC8vIENvbm5lY3Rpb24gc2hvdWxkbid0IGV4aXN0XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihyZXNwb25zZS5pZCwgJycpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQ29ubmVjdGlvbiAnICsgcmVzcG9uc2UuaWQgKyAnIGFscmVhZHkgZXhpc3RzIGluIGNvbm5lY3Rpb25zIGxpc3QnKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW3Jlc3BvbnNlLmlkXSA9IGNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRMZWZ0KG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLm5hbWUgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW0uc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBjb25uZWN0aW9uLCBtc2cucmVhc29uKV0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRQdWJsaXNoZWQocmVzcG9uc2U6IENvbm5lY3Rpb25PcHRpb25zKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgYWZ0ZXJDb25uZWN0aW9uRm91bmQgPSAoY29ubmVjdGlvbikgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdKSB7XG4gICAgICAgICAgICAgICAgLy8gQXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiBzdHJlYW0uc3Vic2NyaWJlKCkgaW4gXCJvblBhcnRpY2lwYW50UHVibGlzaGVkXCIgYW5kIGluIFwiam9pblJvb21cIiBycGMgY2FsbGJhY2tcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGNvbmRpdGlvbiBpcyBmYWxzZSBpZiBvcGVudmlkdS1zZXJ2ZXIgc2VuZHMgXCJwYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGV2ZW50IHRvIGEgc3Vic2NyaWJlciBwYXJ0aWNpcGFudCB0aGF0IGhhc1xuICAgICAgICAgICAgICAgIC8vIGFscmVhZHkgc3Vic2NyaWJlZCB0byBjZXJ0YWluIHN0cmVhbSBpbiB0aGUgY2FsbGJhY2sgb2YgXCJqb2luUm9vbVwiIG1ldGhvZFxuXG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIGNvbm5lY3Rpb24uc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEdldCB0aGUgZXhpc3RpbmcgQ29ubmVjdGlvbiBjcmVhdGVkIG9uICdvblBhcnRpY2lwYW50Sm9pbmVkJyBmb3JcbiAgICAgICAgLy8gZXhpc3RpbmcgcGFydGljaXBhbnRzIG9yIGNyZWF0ZSBhIG5ldyBvbmUgZm9yIG5ldyBwYXJ0aWNpcGFudHNcbiAgICAgICAgbGV0IGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG4gICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihyZXNwb25zZS5pZCwgXCJSZW1vdGUgY29ubmVjdGlvbiAnXCIgKyByZXNwb25zZS5pZCArIFwiJyB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb24gPT4ge1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBleGlzdGluZyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IGNvbjtcbiAgICAgICAgICAgICAgICByZXNwb25zZS5tZXRhZGF0YSA9IGNvbi5kYXRhO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ub3B0aW9ucyA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uaW5pdFJlbW90ZVN0cmVhbXMocmVzcG9uc2Uuc3RyZWFtcyk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBuZXcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFVucHVibGlzaGVkKG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgbXNnLm5hbWUgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oc3RyZWFtSWQpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZyk6IHZvaWQge1xuICAgICAgICAvKnRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cubmFtZSwgJ1JlbW90ZSBjb25uZWN0aW9uICcgKyBtc2cubmFtZSArIFwiIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudExlZnQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgc3RyZWFtLCAnZm9yY2VEaXNjb25uZWN0Jyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW0uc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBjb25uZWN0aW9uLCAnZm9yY2VEaXNjb25uZWN0JyldKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pOyovXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTmV3TWVzc2FnZShtc2cpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmZyb20sIFwiQ29ubmVjdGlvbiAnXCIgKyBtc2cuZnJvbSArIFwiJyB1bmtub3cgd2hlbiAnb25OZXdNZXNzYWdlJy4gRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiBcIlxuICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkgKyAnLiBFeGlzdGluZyBsb2NhbCBjb25uZWN0aW9uOiAnICsgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZClcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbCcsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmVuZHBvaW50TmFtZSwgJ0Nvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICcuIEljZSBjYW5kaWRhdGUgd2lsbCBiZSBpZ25vcmVkOiAnICsgY2FuZGlkYXRlKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGFkZGluZyBjYW5kaWRhdGUgZm9yICcgKyBzdHJlYW0uc3RyZWFtSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU2Vzc2lvbkNsb3NlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5pbmZvKCdTZXNzaW9uIGNsb3NlZDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuICAgICAgICBjb25zdCBzID0gbXNnLnJvb207XG4gICAgICAgIGlmIChzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uLWNsb3NlZCcsIFt7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbjogc1xuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIHVuZGVmaW5lZCBvbiBzZXNzaW9uIGNsb3NlZCcsIG1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25Mb3N0Q29ubmVjdGlvbigpOiB2b2lkIHtcblxuICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKHBhcmFtcyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIGNvbnN0IGVyciA9IHBhcmFtcy5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOicsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsZWF2ZShmb3JjZWQ6IGJvb2xlYW4sIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgZm9yY2VkID0gISFmb3JjZWQ7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnTGVhdmluZyBTZXNzaW9uIChmb3JjZWQ9JyArIGZvcmNlZCArICcpJyk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnbGVhdmVSb29tJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgIC8vIERpc3Bvc2UgUHVibGlzaGVyJ3MgIGxvY2FsIHN0cmVhbVxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgUHVibGlzaGVyIG9iamVjdCBkaXNwYXRjaCAnc3RyZWFtRGVzdHJveWVkJyBldmVudCBpZiB0aGUgU3RyZWFtIHdhcyBwdWJsaXNoZWRcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQtYnktZGlzY29ubmVjdCcsIFtyZWFzb25dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBTZXNzaW9uIG9iamVjdCBkaXNwYXRjaCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcgZXZlbnQgKGlmIGl0IGlzIG5vdCBhbHJlYWR5IGRpc3Bvc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMsIHJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICAgICAgICAgIHNlc3Npb25EaXNjb25uZWN0RXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IHdlcmUgbm90IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc3RhcnRXcygoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgam9pblBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiAoISF0b2tlbikgPyB0b2tlbiA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISF0aGlzLm9wdGlvbnMubWV0YWRhdGEgPyB0aGlzLm9wdGlvbnMubWV0YWRhdGEgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVudmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZGVyOiB0aGlzLm9wZW52aWR1LmdldFJlY29yZGVyKCksXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnam9pblJvb20nLCBqb2luUGFyYW1zLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSBsb2NhbCBDb25uZWN0aW9uIG9iamVjdCB3aXRoIHZhbHVlcyByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmRhdGEgPSByZXNwb25zZS5tZXRhZGF0YTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgcmVtb3RlIENvbm5lY3Rpb25zIHdpdGggdmFsdWUgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXZlbnRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uczogbmV3IEFycmF5PENvbm5lY3Rpb24+KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbXM6IG5ldyBBcnJheTxTdHJlYW0+KClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nUGFydGljaXBhbnRzOiBDb25uZWN0aW9uT3B0aW9uc1tdID0gcmVzcG9uc2UudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdQYXJ0aWNpcGFudHMuZm9yRWFjaChwYXJ0aWNpcGFudCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCBwYXJ0aWNpcGFudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLnB1c2goY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5wdXNoKGNvbm5lY3Rpb24uc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3duICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgdGhpcy5jb25uZWN0aW9uLCAnJyldKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGV4aXN0aW5nIGNvbm5lY3Rpb24gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMuZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdzdHJlYW1DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBhY3RpdmUgc3RyZWFtIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMuZm9yRWFjaChzdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGE6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0YWRhdGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPT09IGNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGxvY2FsIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmVtb3RlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZywgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbm5lY3Rpb24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSByZW1vdGUgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgIHJlc29sdmUoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBjb25uZWN0aW9uIG5vdCBmb3VuZC4gUmVqZWN0IHdpdGggT3BlblZpZHVFcnJvclxuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHRva2VuKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSA8c3RyaW5nPnVybC5zZWFyY2hQYXJhbXMuZ2V0KCdzZXNzaW9uSWQnKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0ID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3NlY3JldCcpO1xuICAgICAgICBjb25zdCByZWNvcmRlciA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyZWNvcmRlcicpO1xuXG4gICAgICAgIGlmICghIXNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcmVjb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucmVjb3JkZXIgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS53c1VyaSA9ICd3c3M6Ly8nICsgdXJsLmhvc3QgKyAnL29wZW52aWR1JztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFdlYlJ0Y1N0YXRzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cyc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5pbXBvcnQgKiBhcyBrdXJlbnRvVXRpbHMgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcyc7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBzdHJlYW1cbiAgICAgKi9cbiAgICBzdHJlYW1JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogYFwiQ0FNRVJBXCJgIG9yIGBcIlNDUkVFTlwiYC4gKnVuZGVmaW5lZCogaWYgc3RyZWFtIGlzIGF1ZGlvLW9ubHlcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbU1hbmFnZXIgb2JqZWN0IChbW1B1Ymxpc2hlcl1dIG9yIFtbU3Vic2NyaWJlcl1dKSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGlzIHN0cmVhbSBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcjogU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIHByaXZhdGUgd2ViUnRjUGVlcjogYW55O1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5ib3VuZFN0cmVhbU9wdHM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3BlZWNoRXZlbnQ6IGFueTtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlc3Npb246IFNlc3Npb24sIG9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zIHwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIHwge30pIHtcblxuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCdpZCcpKSB7XG4gICAgICAgICAgICAvLyBJbmJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBTdWJzY3JpYmVyXG4gICAgICAgICAgICB0aGlzLmluYm91bmRTdHJlYW1PcHRzID0gPEluYm91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9ICdTQ1JFRU4nO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ1NDUkVFTic7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NBTUVSQSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSAnTUlDUk8nO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnR5cGVPZlZpZGVvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaXNTZW5kQXVkaW8oKTtcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmlzU2VuZFZpZGVvKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVlLm9uKCdtZWRpYXN0cmVhbS11cGRhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnVwZGF0ZU1lZGlhU3RyZWFtKHRoaXMubWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnVmlkZW8gc3JjT2JqZWN0IFsnICsgdGhpcy5tZWRpYVN0cmVhbSArICddIHVwZGF0ZWQgaW4gc3RyZWFtIFsnICsgdGhpcy5zdHJlYW1JZCArICddJyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRNZWRpYVN0cmVhbSgpOiBNZWRpYVN0cmVhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRXZWJSdGNQZWVyKCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wZWVyQ29ubmVjdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLmhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1BlZXJTZW5kKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgb3B0aW9uczogYW55ID0ge1xuICAgICAgICAgICAgICAgIHZpZGVvU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoZXJyb3IsIHNkcE9mZmVyUGFyYW0sIHdwKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhwdWJsaXNoKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTZW5kaW5nIFNEUCBvZmZlciB0byBwdWJsaXNoIGFzICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncHVibGlzaFZpZGVvJywge1xuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbSxcbiAgICAgICAgICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHRoaXMuaXNTZW5kVmlkZW8oKSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86ICgodGhpcy5pc1NlbmRWaWRlbygpKSA/ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJykgOiAnJyksXG4gICAgICAgICAgICAgICAgICAgIGZyYW1lUmF0ZTogISF0aGlzLmZyYW1lUmF0ZSA/IHRoaXMuZnJhbWVSYXRlIDogLTFcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdFcnJvciBvbiBwdWJsaXNoVmlkZW86ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzU2RwQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiByZW1vdGUgbm93IHdlIGNhbiBzZXQgdGhlIHNyY09iamVjdCB2YWx1ZSBvZiB2aWRlbyBlbGVtZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gJ3N0cmVhbVBsYXlpbmcnIGV2ZW50IHdpbGwgYmUgdHJpZ2dlcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0ga3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIuV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGVyciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKHN1Y2Nlc3NDYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLldlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zLCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcihzdWNjZXNzQ2FsbGJhY2spO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5yZWN2VmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiJ1Nlc3Npb24uc3Vic2NyaWJlKFN0cmVhbSknIGNhbGxlZC4gQ29uc3RyYWludHMgb2YgZ2VuZXJhdGUgU0RQIG9mZmVyXCIsXG4gICAgICAgICAgICAgICAgb2ZmZXJDb25zdHJhaW50cyk7XG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogb2ZmZXJDb25zdHJhaW50c1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc0NhbGxiYWNrID0gKGVycm9yLCBzZHBPZmZlclBhcmFtLCB3cCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTZW5kaW5nIFNEUCBvZmZlciB0byBzdWJzY3JpYmUgdG8gJ1xuICAgICAgICAgICAgICAgICAgICArIHRoaXMuc3RyZWFtSWQsIHNkcE9mZmVyUGFyYW0pO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncmVjZWl2ZVZpZGVvRnJvbScsIHtcbiAgICAgICAgICAgICAgICAgICAgc2VuZGVyOiB0aGlzLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbVxuICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdFcnJvciBvbiByZWN2VmlkZW9Gcm9tOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NTZHBBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBrdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5XZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcihzdWNjZXNzQ2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcHJvY2Vzc1NkcEFuc3dlcihzZHBBbnN3ZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXIsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1Zyh0aGlzLnN0cmVhbUlkICsgJzogc2V0IHBlZXIgY29ubmVjdGlvbiB3aXRoIHJlY3ZkIFNEUCBhbnN3ZXInLCBzZHBBbnN3ZXIpO1xuXG4gICAgICAgICAgICBjb25zdCBzdHJlYW1JZCA9IHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgICAgICBjb25zdCBwZWVyQ29ubmVjdGlvbiA9IHRoaXMud2ViUnRjUGVlci5wZWVyQ29ubmVjdGlvbjtcbiAgICAgICAgICAgIHBlZXJDb25uZWN0aW9uLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlciwgKCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHJlbW90ZSBNZWRpYVN0cmVhbSBvYmplY3QgZXhjZXB0IHdoZW4gbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzTG9jYWwoKSB8fCB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBwZWVyQ29ubmVjdGlvbi5nZXRSZW1vdGVTdHJlYW1zKClbMF07XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1BlZXIgcmVtb3RlIHN0cmVhbScsIHRoaXMubWVkaWFTdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghIXRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0gJiYgdGhpcy5zZXNzaW9uLnNwZWFraW5nRXZlbnRzRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgICAgICB9LCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcih0aGlzLnN0cmVhbUlkICsgJzogRXJyb3Igc2V0dGluZyBTRFAgdG8gdGhlIHBlZXIgY29ubmVjdGlvbjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzID0gbmV3IFdlYlJ0Y1N0YXRzKHRoaXMpO1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RvcFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLndlYlJ0Y1N0YXRzICYmIHRoaXMud2ViUnRjU3RhdHMuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbCgpOiBib29sZWFuIHtcbiAgICAgICAgLy8gaW5ib3VuZCBvcHRpb25zIHVuZGVmaW5lZCBhbmQgb3V0Ym91bmQgb3B0aW9ucyBkZWZpbmVkXG4gICAgICAgIHJldHVybiAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgJiYgISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGB2aWRlb2AgZWxlbWVudCBwYXJhbWV0ZXIgZGlzcGxheSB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IGFyZVxuICAgICAqIFttYW5hZ2luZyB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd25dKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpXG4gICAgICpcbiAgICAgKiBDYWxsaW5nIHRoaXMgbWV0aG9kIHdpdGggYSB2aWRlbyBhbHJlYWR5IGFkZGVkIHRvIG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgY2F1c2UgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYmVcbiAgICAgKiBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBwcmV2aW91cyBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgdG8gYmUgYXNzb2NpYXRlZCB0byB0aGlzIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIDEgaWYgdGhlIHZpZGVvIHdhc24ndCBhc3NvY2lhdGVkIHRvIGFueSBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqIDAgaWYgdGhlIHZpZGVvIHdhcyBhbHJlYWR5IGFkZGVkIHRvIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXIuIC0xIGlmIHRoZSB2aWRlbyB3YXMgcHJldmlvdXNseSBhc3NvY2lhdGVkIHRvIGFueSBvdGhlclxuICAgICAqIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgb25lIGFuZCBwcm9wZXJseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKi9cbiAgICBhZGRWaWRlb0VsZW1lbnQodmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgLy8gSWYgdGhlIHZpZGVvIGVsZW1lbnQgaXMgYWxyZWFkeSBwYXJ0IG9mIHRoaXMgU3RyZWFtTWFuYWdlciBkbyBub3RoaW5nXG4gICAgICAgIGZvciAoY29uc3QgdiBvZiB0aGlzLnZpZGVvcykge1xuICAgICAgICAgICAgaWYgKHYudmlkZW8gPT09IHZpZGVvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmV0dXJuTnVtYmVyID0gMTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3Muc2xpY2UoKS5yZXZlcnNlKCkuZm9yRWFjaCgoc3RyZWFtTWFuYWdlclZpZGVvLCBpbmRleCwgdmlkZW9zKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgb25jYW5wbGF5IGV2ZW50IGxpc3RlbmVyIChvbmx5IE9wZW5WaWR1IGJyb3dzZXIgb25lLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICAgICAgaWYgKCEhc3RyZWFtTWFuYWdlclZpZGVvLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbW92ZSB2aWRlb3MgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyICh0aG9zZSBnZW5lcmF0ZWQgYnkgcGFzc2luZyBhIHZhbGlkIHRhcmdldEVsZW1lbnQgaW4gT3BlblZpZHUuaW5pdFB1Ymxpc2hlciBhbmQgU2Vzc2lvbi5zdWJzY3JpYmVcbiAgICAgICAgICAgICAgICAvLyBvciB0aG9zZSBjcmVhdGVkIGJ5IFN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KS4gVGhlc2UgYXJlIGFsc28gdGhlIHZpZGVvcyB0aGF0IHRyaWdnZXJlZCBhIHZpZGVvRWxlbWVudENyZWF0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucGFyZW50Tm9kZSEucmVtb3ZlQ2hpbGQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50RGVzdHJveWVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZSh2aWRlb3MubGVuZ3RoIC0gMSAtIGluZGV4LCAxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHNyY09iamVjdCBpbiBhbGwgdmlkZW9zIG1hbmFnZWQgYnkgdGhlIHVzZXJcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwcG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gY2FwdHVyZSBzb21lIGRlc2t0b3Agc2NyZWVuIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBoYXMgYmVlbiBjYWxsZWQgd2l0aCBwcm9wZXJ0aWVzIGB2aWRlb1NvdXJjZWAgYW5kIGBhdWRpb1NvdXJjZWAgb2ZcbiAgICAgKiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBwYXJhbWV0ZXIgYm90aCBzZXQgdG8gKmZhbHNlKiBvciAqbnVsbCpcbiAgICAgKi9cbiAgICBOT19JTlBVVF9TT1VSQ0VfU0VUID0gJ05PX0lOUFVUX1NPVVJDRV9TRVQnLFxuXG4gICAgLyoqXG4gICAgICogU29tZSBtZWRpYSBwcm9wZXJ0eSBvZiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBzdWNoIGFzIGBmcmFtZVJhdGVgIG9yIGByZXNvbHV0aW9uYCBpcyBub3Qgc3VwcG9ydGVkXG4gICAgICogYnkgdGhlIGlucHV0IGRldmljZXMgKHdoZW5ldmVyIGl0IGlzIHBvc3NpYmxlIHRoZXkgYXJlIGF1dG9tYXRpY2FsbHkgYWRqdXN0ZWQgdG8gdGhlIG1vc3Qgc2ltaWxhciB2YWx1ZSkuXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEID0gJ09QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuLyoqXG4gKiBTaW1wbGUgb2JqZWN0IHRvIGlkZW50aWZ5IHJ1bnRpbWUgZXJyb3JzIG9uIHRoZSBjbGllbnQgc2lkZVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHVFcnJvciB7XG5cbiAgICBuYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBIb3cgdGhlIHZpZGVvIHdpbGwgYmUgaW5zZXJ0ZWQgaW4gdGhlIERPTSBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuIFNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dIGFuZCBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXVxuICovXG5leHBvcnQgZW51bSBWaWRlb0luc2VydE1vZGUge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHRhcmdldCBlbGVtZW50IChhcyBuZXh0IHNpYmxpbmcpXG4gICAgICovXG4gICAgQUZURVIgPSAnQUZURVInLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGxhc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgQVBQRU5EID0gJ0FQUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYmVmb3JlIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgcHJldmlvdXMgc2libGluZylcbiAgICAgKi9cbiAgICBCRUZPUkUgPSAnQkVGT1JFJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBmaXJzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBQUkVQRU5EID0gJ1BSRVBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIHJlcGxhY2VzIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUkVQTEFDRSA9ICdSRVBMQUNFJ1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYGNvbm5lY3Rpb25DcmVhdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgY29ubmVjdGlvbkRlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgd2FzIGNyZWF0ZWQgb3IgZGVzdHJveWVkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZvciAnY29ubmVjdGlvbkRlc3Ryb3llZCcgZXZlbnQ6XG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3VyIHRoYXQgbWF5IGJlIHByZXZlbnRlZCBieSBjYWxsaW5nIFtbRXZlbnQucHJldmVudERlZmF1bHRdXVxuICAgICAqL1xuICAgIGNhbmNlbGFibGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0IHRoYXQgZGlzcGF0Y2hlZCB0aGUgZXZlbnRcbiAgICAgKi9cbiAgICB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHR5cGUgb2YgZXZlbnQuIFRoaXMgaXMgdGhlIHNhbWUgc3RyaW5nIHlvdSBwYXNzIGFzIGZpcnN0IHBhcmFtZXRlciB3aGVuIGNhbGxpbmcgbWV0aG9kIGBvbigpYCBvZiBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBbW0V2ZW50RGlzcGF0Y2hlcl1dIGludGVyZmFjZVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIHByaXZhdGUgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvdXI6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvdXIgPSAoKSA9PiB7IH07XG4gICAgICAgIHRoaXMuaGFzQmVlblByZXZlbnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHJlY29yZGluZ1N0YXJ0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGByZWNvcmRpbmdTdG9wcGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIElEIGdlbmVyYXRlZCBpbiBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlY29yZGluZyBuYW1lIHlvdSBzdXBwbGllZCB0byBvcGVudmlkdS1zZXJ2ZXIuIEZvciBleGFtcGxlLCB0byBuYW1lIHlvdXIgcmVjb3JkaW5nIGZpbGUgTVlfUkVDT1JESU5HOlxuICAgICAqIC0gV2l0aCAqKkFQSSBSRVNUKio6IFBPU1QgdG8gYC9hcGkvcmVjb3JkaW5ncy9zdGFydGAgcGFzc2luZyBKU09OIGJvZHkgYHtcInNlc3Npb25cIjpcInNlc3Npb25JZFwiLFwibmFtZVwiOlwiTVlfUkVDT1JESU5HXCJ9YFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LWphdmEtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIE1ZX1JFQ09SRElORylgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKE1ZX1JFQ09SRElORykuYnVpbGQoKSlgXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtbm9kZS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgTVlfUkVDT1JESU5HKWAgb3IgYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgbmV3IFJlY29yZGluZ1Byb3BlcnRpZXMuQnVpbGRlcigpLm5hbWUoTVlfUkVDT1JESU5HKS5idWlsZCgpKWBcbiAgICAgKlxuICAgICAqIElmIG5vIG5hbWUgaXMgc3VwcGxpZWQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSB1bmRlZmluZWQgYW5kIHRoZSByZWNvcmRlZCBmaWxlIHdpbGwgYmUgbmFtZWQgYWZ0ZXIgcHJvcGVydHkgW1tpZF1dXG4gICAgICovXG4gICAgbmFtZT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIGlmIChuYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogeW91IGhhdmUgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogeW91ciBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHRydWUsIHRhcmdldCwgJ3Nlc3Npb25EaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkNhbGxpbmcgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvdXIoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEZvciAnc3RyZWFtRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwidW5wdWJsaXNoXCI6IG1ldGhvZCBgU2Vzc2lvbi51bnB1Ymxpc2goKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogbWV0aG9kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcIm5ldHdvcmtEaXNjb25uZWN0XCI6IHRoZSB1c2VyJ3MgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ3N0cmVhbUNyZWF0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFB1Ymxpc2hlciwgdHlwZTogc3RyaW5nLCBzdHJlYW06IFN0cmVhbSwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgUHVibGlzaGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9jYWwgU3RyZWFtXG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW91ciB1cG9uICdcIiArIHRoaXMudHlwZSArIFwiJyBldmVudCBkaXNwYXRjaGVkIGJ5ICdQdWJsaXNoZXInXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHZpZGVvRWxlbWVudENyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuIFNlZVxuICogW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uLlxuICogLSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSB3aGVuZXZlciBhbiBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWRlb0VsZW1lbnRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGVsZW1lbnQgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBlbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQsIHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiZnVuY3Rpb24gTWFwcGVyKClcbntcbiAgdmFyIHNvdXJjZXMgPSB7fTtcblxuXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKVxuICB7XG4gICAgZm9yKHZhciBrZXkgaW4gc291cmNlcylcbiAgICB7XG4gICAgICB2YXIgc291cmNlID0gc291cmNlc1trZXldO1xuXG4gICAgICBmb3IodmFyIGtleTIgaW4gc291cmNlKVxuICAgICAgICBjYWxsYmFjayhzb3VyY2Vba2V5Ml0pO1xuICAgIH07XG4gIH07XG5cbiAgdGhpcy5nZXQgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBpZHNbaWRdO1xuICB9O1xuXG4gIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcblxuICAgIGRlbGV0ZSBpZHNbaWRdO1xuXG4gICAgLy8gQ2hlY2sgaXQncyBlbXB0eVxuICAgIGZvcih2YXIgaSBpbiBpZHMpe3JldHVybiBmYWxzZX1cblxuICAgIGRlbGV0ZSBzb3VyY2VzW3NvdXJjZV07XG4gIH07XG5cbiAgdGhpcy5zZXQgPSBmdW5jdGlvbih2YWx1ZSwgaWQsIHNvdXJjZSlcbiAge1xuICAgIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHNvdXJjZXNbc291cmNlXSA9IGlkcyA9IHt9O1xuXG4gICAgaWRzW2lkXSA9IHZhbHVlO1xuICB9O1xufTtcblxuXG5NYXBwZXIucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG57XG4gIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGlkLCBzb3VyY2UpO1xuICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICByZXR1cm4gdmFsdWU7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gTWFwcGVyO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBKc29uUnBjQ2xpZW50ICA9IHJlcXVpcmUoJy4vanNvbnJwY2NsaWVudCcpO1xuXG5cbmV4cG9ydHMuSnNvblJwY0NsaWVudCAgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uLycpO1xudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5EYXRlLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiArbmV3IERhdGU7XG59O1xuXG52YXIgUElOR19JTlRFUlZBTCA9IDUwMDA7XG5cbnZhciBSRUNPTk5FQ1RJTkcgPSAnUkVDT05ORUNUSU5HJztcbnZhciBDT05ORUNURUQgPSAnQ09OTkVDVEVEJztcbnZhciBESVNDT05ORUNURUQgPSAnRElTQ09OTkVDVEVEJztcblxudmFyIExvZ2dlciA9IGNvbnNvbGU7XG5cbi8qKlxuICpcbiAqIGhlYXJ0YmVhdDogaW50ZXJ2YWwgaW4gbXMgZm9yIGVhY2ggaGVhcnRiZWF0IG1lc3NhZ2UsXG4gKiBzZW5kQ2xvc2VNZXNzYWdlIDogdHJ1ZSAvIGZhbHNlLCBiZWZvcmUgY2xvc2luZyB0aGUgY29ubmVjdGlvbiwgaXQgc2VuZHMgYSBjbG9zZVNlc3Npb24gbWVzc2FnZVxuICogPHByZT5cbiAqIHdzIDoge1xuICogXHR1cmkgOiBVUkkgdG8gY29ubnRlY3QgdG8sXG4gKiAgdXNlU29ja0pTIDogdHJ1ZSAodXNlIFNvY2tKUykgLyBmYWxzZSAodXNlIFdlYlNvY2tldCkgYnkgZGVmYXVsdCxcbiAqIFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuICogXHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcbiAqIFx0b25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG4gKiBcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbiAqIFx0b25lcnJvciA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGVyZSBpcyBhbiBlcnJvclxuICogfSxcbiAqIHJwYyA6IHtcbiAqIFx0cmVxdWVzdFRpbWVvdXQgOiB0aW1lb3V0IGZvciBhIHJlcXVlc3QsXG4gKiBcdHNlc3Npb25TdGF0dXNDaGFuZ2VkOiBjYWxsYmFjayBtZXRob2QgZm9yIGNoYW5nZXMgaW4gc2Vzc2lvbiBzdGF0dXMsXG4gKiBcdG1lZGlhUmVuZWdvdGlhdGlvbjogbWVkaWFSZW5lZ290aWF0aW9uXG4gKiB9XG4gKiA8L3ByZT5cbiAqL1xuZnVuY3Rpb24gSnNvblJwY0NsaWVudChjb25maWd1cmF0aW9uKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgd3NDb25maWcgPSBjb25maWd1cmF0aW9uLndzO1xuXG4gICAgdmFyIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSAtMTtcblxuICAgIHZhciBwaW5nTmV4dE51bSA9IDA7XG4gICAgdmFyIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgdmFyIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgIHZhciBwaW5nSW50ZXJ2YWw7XG5cbiAgICB2YXIgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgdmFyIG9ucmVjb25uZWN0aW5nID0gd3NDb25maWcub25yZWNvbm5lY3Rpbmc7XG4gICAgdmFyIG9ucmVjb25uZWN0ZWQgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGVkO1xuICAgIHZhciBvbmNvbm5lY3RlZCA9IHdzQ29uZmlnLm9uY29ubmVjdGVkO1xuICAgIHZhciBvbmVycm9yID0gd3NDb25maWcub25lcnJvcjtcblxuICAgIGNvbmZpZ3VyYXRpb24ucnBjLnB1bGwgPSBmdW5jdGlvbihwYXJhbXMsIHJlcXVlc3QpIHtcbiAgICAgICAgcmVxdWVzdC5yZXBseShudWxsLCBcInB1c2hcIik7XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNUSU5HIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBSRUNPTk5FQ1RJTkcpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIFJFQ09OTkVDVElORyBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVElORyBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXR1cyA9IFJFQ09OTkVDVElORztcbiAgICAgICAgaWYgKG9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9ucmVjb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uY29ubmVjdGVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05DT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVzZVBpbmcoKTtcblxuICAgICAgICBpZiAob25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9ORVJST1IgLS0tLS0tLS0tLS1cIik7XG5cbiAgICAgICAgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgICAgIGlmIChvbmVycm9yKSB7XG4gICAgICAgICAgICBvbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKHdzQ29uZmlnKTtcblxuICAgIExvZ2dlci5kZWJ1ZygnQ29ubmVjdGluZyB3ZWJzb2NrZXQgdG8gVVJJOiAnICsgd3NDb25maWcudXJpKTtcblxuICAgIHZhciBycGNCdWlsZGVyT3B0aW9ucyA9IHtcbiAgICAgICAgcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5yZXF1ZXN0VGltZW91dCxcbiAgICAgICAgcGluZ19yZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLmhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0XG4gICAgfTtcblxuICAgIHZhciBycGMgPSBuZXcgUnBjQnVpbGRlcihScGNCdWlsZGVyLnBhY2tlcnMuSnNvblJQQywgcnBjQnVpbGRlck9wdGlvbnMsIHdzLFxuICAgICAgICBmdW5jdGlvbihyZXF1ZXN0KSB7XG5cbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVjZWl2ZWQgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IGNvbmZpZ3VyYXRpb24ucnBjW3JlcXVlc3QubWV0aG9kXTtcblxuICAgICAgICAgICAgICAgIGlmIChmdW5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWV0aG9kIFwiICsgcmVxdWVzdC5tZXRob2QgKyBcIiBub3QgcmVnaXN0ZXJlZCBpbiBjbGllbnRcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyhyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKCdFeGNlcHRpb24gcHJvY2Vzc2luZyByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAobWV0aG9kICE9PSAncGluZycpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVxdWVzdDogbWV0aG9kOicgKyBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgcnBjLmVuY29kZShtZXRob2QsIHBhcmFtcywgZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1I6XCIgKyBlcnJvci5tZXNzYWdlICsgXCIgaW4gUmVxdWVzdDogbWV0aG9kOlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyBcIiByZXF1ZXN0OlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1IgREFUQTpcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yLmRhdGEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdFRpbWUgPSByZXF1ZXN0VGltZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT0gdW5kZWZpbmVkICYmIHJlc3VsdC52YWx1ZSAhPT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVzcG9uc2U6ICcgKyBKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIm5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBcIiArIHBpbmdOZXh0TnVtICsgJyAob2xkPScgK1xuICAgICAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiArICcpJyk7XG4gICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBwaW5nTmV4dE51bTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZW5kUGluZygpIHtcbiAgICAgICAgaWYgKGVuYWJsZWRQaW5ncykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG51bGw7XG4gICAgICAgICAgICBpZiAocGluZ05leHROdW0gPT0gMCB8fCBwaW5nTmV4dE51bSA9PSBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbDogY29uZmlndXJhdGlvbi5oZWFydGJlYXQgfHwgUElOR19JTlRFUlZBTFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwaW5nTmV4dE51bSsrO1xuXG4gICAgICAgICAgICBzZWxmLnNlbmQoJ3BpbmcnLCBwYXJhbXMsIChmdW5jdGlvbihwaW5nTnVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJFcnJvciBpbiBwaW5nIHJlcXVlc3QgI1wiICsgcGluZ051bSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubWVzc2FnZSArIFwiKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaW5nTnVtID4gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZXJ2ZXIgZGlkIG5vdCByZXNwb25kIHRvIHBpbmcgbWVzc2FnZSAjXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5nTnVtICsgXCIuIFJlY29ubmVjdGluZy4uLiBcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKHBpbmdOZXh0TnVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUcnlpbmcgdG8gc2VuZCBwaW5nLCBidXQgcGluZyBpcyBub3QgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgKiBJZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0IGhhcyBhbnkgdmFsdWUsIHRoZSBwaW5nLXBvbmcgd2lsbCB3b3JrIHdpdGggdGhlIGludGVydmFsXG4gICAgKiBvZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0XG4gICAgKi9cbiAgICBmdW5jdGlvbiB1c2VQaW5nKCkge1xuICAgICAgICBpZiAoIXBpbmdQb25nU3RhcnRlZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgcGluZyAoaWYgY29uZmlndXJlZClcIilcbiAgICAgICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwaW5nSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzZW5kUGluZywgY29uZmlndXJhdGlvbi5oZWFydGJlYXQpO1xuICAgICAgICAgICAgICAgIHNlbmRQaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NpbmcganNvblJwY0NsaWVudCBleHBsaWNpdGx5IGJ5IGNsaWVudFwiKTtcblxuICAgICAgICBpZiAocGluZ0ludGVydmFsICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xlYXJpbmcgcGluZyBpbnRlcnZhbFwiKTtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGNvbmZpZ3VyYXRpb24uc2VuZENsb3NlTWVzc2FnZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VuZGluZyBjbG9zZSBtZXNzYWdlXCIpXG4gICAgICAgICAgICB0aGlzLnNlbmQoJ2Nsb3NlU2Vzc2lvbicsIG51bGwsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyBjbG9zZSBtZXNzYWdlOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcblx0XHRcdHdzLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIHdzLmZvcmNlQ2xvc2UobWlsbGlzKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlY29ubmVjdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpzb25ScGNDbGllbnQ7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gID0gcmVxdWlyZSgnLi93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cblxuZXhwb3J0cy5XZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb247IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxMy0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIEJyb3dzZXJXZWJTb2NrZXQgPSBnbG9iYWwuV2ViU29ja2V0IHx8IGdsb2JhbC5Nb3pXZWJTb2NrZXQ7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqIEdldCBlaXRoZXIgdGhlIGBXZWJTb2NrZXRgIG9yIGBNb3pXZWJTb2NrZXRgIGdsb2JhbHNcbiAqIGluIHRoZSBicm93c2VyIG9yIHRyeSB0byByZXNvbHZlIFdlYlNvY2tldC1jb21wYXRpYmxlXG4gKiBpbnRlcmZhY2UgZXhwb3NlZCBieSBgd3NgIGZvciBOb2RlLWxpa2UgZW52aXJvbm1lbnQuXG4gKi9cblxuLyp2YXIgV2ViU29ja2V0ID0gQnJvd3NlcldlYlNvY2tldDtcbmlmICghV2ViU29ja2V0ICYmIHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgV2ViU29ja2V0ID0gcmVxdWlyZSgnd3MnKTtcbiAgICB9IGNhdGNoIChlKSB7IH1cbn0qL1xuXG4vL3ZhciBTb2NrSlMgPSByZXF1aXJlKCdzb2NranMtY2xpZW50Jyk7XG5cbnZhciBNQVhfUkVUUklFUyA9IDIwMDA7IC8vIEZvcmV2ZXIuLi5cbnZhciBSRVRSWV9USU1FX01TID0gMzAwMDsgLy8gRklYTUU6IEltcGxlbWVudCBleHBvbmVudGlhbCB3YWl0IHRpbWVzLi4uXG5cbnZhciBDT05ORUNUSU5HID0gMDtcbnZhciBPUEVOID0gMTtcbnZhciBDTE9TSU5HID0gMjtcbnZhciBDTE9TRUQgPSAzO1xuXG4vKlxuY29uZmlnID0ge1xuXHRcdHVyaSA6IHdzVXJpLFxuXHRcdHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG5cdFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuXHRcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuXHRcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuXHRcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNC0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKVxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIFVBUGFyc2VyID0gcmVxdWlyZSgndWEtcGFyc2VyLWpzJylcbnZhciB1dWlkID0gcmVxdWlyZSgndXVpZCcpXG52YXIgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKVxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyXG52YXIgcmVjdXJzaXZlID0gcmVxdWlyZSgnbWVyZ2UnKS5yZWN1cnNpdmUuYmluZCh1bmRlZmluZWQsIHRydWUpXG52YXIgc2RwVHJhbnNsYXRvciA9IHJlcXVpcmUoJ3NkcC10cmFuc2xhdG9yJylcbnZhciBsb2dnZXIgPSB3aW5kb3cuTG9nZ2VyIHx8IGNvbnNvbGVcblxuLy8gdmFyIGdVTSA9IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhIHx8IGZ1bmN0aW9uIChjb25zdHJhaW50cykge1xuLy8gICByZXR1cm4gbmV3IFByb21pc2UobmF2aWdhdG9yLmdldFVzZXJNZWRpYShjb25zdHJhaW50cywgZnVuY3Rpb24gKHN0cmVhbSkge1xuLy8gICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4vLyAgICAgc3RhcnQoKVxuLy8gICB9KS5lcm9yKGNhbGxiYWNrKSk7XG4vLyB9XG5cbi8qdHJ5IHtcbiAgcmVxdWlyZSgna3VyZW50by1icm93c2VyLWV4dGVuc2lvbnMnKVxufSBjYXRjaCAoZXJyb3IpIHtcbiAgaWYgKHR5cGVvZiBnZXRTY3JlZW5Db25zdHJhaW50cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBsb2dnZXIud2Fybignc2NyZWVuIHNoYXJpbmcgaXMgbm90IGF2YWlsYWJsZScpXG5cbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyA9IGZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKHNlbmRTb3VyY2UsIGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoXCJUaGlzIGxpYnJhcnkgaXMgbm90IGVuYWJsZWQgZm9yIHNjcmVlbiBzaGFyaW5nXCIpKVxuICAgIH1cbiAgfVxufSovXG5cbnZhciBNRURJQV9DT05TVFJBSU5UUyA9IHtcbiAgYXVkaW86IHRydWUsXG4gIHZpZGVvOiB7XG4gICAgd2lkdGg6IDY0MCxcbiAgICBmcmFtZXJhdGU6IDE1XG4gIH1cbn1cblxuLy8gU29tZWhvdywgdGhlIFVBUGFyc2VyIGNvbnN0cnVjdG9yIGdldHMgYW4gZW1wdHkgd2luZG93IG9iamVjdC5cbi8vIFdlIG5lZWQgdG8gcGFzcyB0aGUgdXNlciBhZ2VudCBzdHJpbmcgaW4gb3JkZXIgdG8gZ2V0IGluZm9ybWF0aW9uXG52YXIgdWEgPSAod2luZG93ICYmIHdpbmRvdy5uYXZpZ2F0b3IpID8gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQgOiAnJ1xudmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcih1YSlcbnZhciBicm93c2VyID0gcGFyc2VyLmdldEJyb3dzZXIoKVxuXG52YXIgdXNlUGxhbkIgPSBmYWxzZVxuaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gIGxvZ2dlci5kZWJ1Zyhicm93c2VyLm5hbWUgKyBcIjogdXNpbmcgU0RQIFBsYW5CXCIpXG4gIHVzZVBsYW5CID0gdHJ1ZVxufVxuXG5mdW5jdGlvbiBub29wKGVycm9yKSB7XG4gIGlmIChlcnJvcikgbG9nZ2VyLmVycm9yKGVycm9yKVxufVxuXG5mdW5jdGlvbiB0cmFja1N0b3AodHJhY2spIHtcbiAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbn1cblxuZnVuY3Rpb24gc3RyZWFtU3RvcChzdHJlYW0pIHtcbiAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2godHJhY2tTdG9wKVxufVxuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBTZXNzaW9uRGVzY3JpcHRpb24gb2JqZWN0LlxuICovXG52YXIgZHVtcFNEUCA9IGZ1bmN0aW9uIChkZXNjcmlwdGlvbikge1xuICBpZiAodHlwZW9mIGRlc2NyaXB0aW9uID09PSAndW5kZWZpbmVkJyB8fCBkZXNjcmlwdGlvbiA9PT0gbnVsbCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgcmV0dXJuICd0eXBlOiAnICsgZGVzY3JpcHRpb24udHlwZSArICdcXHJcXG4nICsgZGVzY3JpcHRpb24uc2RwXG59XG5cbmZ1bmN0aW9uIGJ1ZmZlcml6ZUNhbmRpZGF0ZXMocGMsIG9uZXJyb3IpIHtcbiAgdmFyIGNhbmRpZGF0ZXNRdWV1ZSA9IFtdXG5cbiAgcGMuYWRkRXZlbnRMaXN0ZW5lcignc2lnbmFsaW5nc3RhdGVjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlLmxlbmd0aCkge1xuICAgICAgICB2YXIgZW50cnkgPSBjYW5kaWRhdGVzUXVldWUuc2hpZnQoKVxuICAgICAgICBwYy5hZGRJY2VDYW5kaWRhdGUoZW50cnkuY2FuZGlkYXRlLCBlbnRyeS5jYWxsYmFjaywgZW50cnkuY2FsbGJhY2spXG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4gIHJldHVybiBmdW5jdGlvbiAoY2FuZGlkYXRlLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgb25lcnJvclxuXG4gICAgc3dpdGNoIChwYy5zaWduYWxpbmdTdGF0ZSkge1xuICAgIGNhc2UgJ2Nsb3NlZCc6XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoJ1BlZXJDb25uZWN0aW9uIG9iamVjdCBpcyBjbG9zZWQnKSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdzdGFibGUnOlxuICAgICAgaWYgKHBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgIHBjLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIGNhbGxiYWNrLCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgY2FuZGlkYXRlc1F1ZXVlLnB1c2goe1xuICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZSxcbiAgICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG4vKiBTaW11bGNhc3QgdXRpbGl0aWVzICovXG5cbmZ1bmN0aW9uIHJlbW92ZUZJREZyb21PZmZlcihzZHApIHtcbiAgdmFyIG4gPSBzZHAuaW5kZXhPZihcImE9c3NyYy1ncm91cDpGSURcIik7XG5cbiAgaWYgKG4gPiAwKSB7XG4gICAgcmV0dXJuIHNkcC5zbGljZSgwLCBuKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc2RwO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFNpbXVsY2FzdEluZm8odmlkZW9TdHJlYW0pIHtcbiAgdmFyIHZpZGVvVHJhY2tzID0gdmlkZW9TdHJlYW0uZ2V0VmlkZW9UcmFja3MoKTtcbiAgaWYgKCF2aWRlb1RyYWNrcy5sZW5ndGgpIHtcbiAgICBsb2dnZXIud2FybignTm8gdmlkZW8gdHJhY2tzIGF2YWlsYWJsZSBpbiB0aGUgdmlkZW8gc3RyZWFtJylcbiAgICByZXR1cm4gJydcbiAgfVxuICB2YXIgbGluZXMgPSBbXG4gICAgJ2E9eC1nb29nbGUtZmxhZzpjb25mZXJlbmNlJyxcbiAgICAnYT1zc3JjLWdyb3VwOlNJTSAxIDIgMycsXG4gICAgJ2E9c3NyYzoxIGNuYW1lOmxvY2FsVmlkZW8nLFxuICAgICdhPXNzcmM6MSBtc2lkOicgKyB2aWRlb1N0cmVhbS5pZCArICcgJyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MSBtc2xhYmVsOicgKyB2aWRlb1N0cmVhbS5pZCxcbiAgICAnYT1zc3JjOjEgbGFiZWw6JyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MiBjbmFtZTpsb2NhbFZpZGVvJyxcbiAgICAnYT1zc3JjOjIgbXNpZDonICsgdmlkZW9TdHJlYW0uaWQgKyAnICcgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjIgbXNsYWJlbDonICsgdmlkZW9TdHJlYW0uaWQsXG4gICAgJ2E9c3NyYzoyIGxhYmVsOicgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjMgY25hbWU6bG9jYWxWaWRlbycsXG4gICAgJ2E9c3NyYzozIG1zaWQ6JyArIHZpZGVvU3RyZWFtLmlkICsgJyAnICsgdmlkZW9UcmFja3NbMF0uaWQsXG4gICAgJ2E9c3NyYzozIG1zbGFiZWw6JyArIHZpZGVvU3RyZWFtLmlkLFxuICAgICdhPXNzcmM6MyBsYWJlbDonICsgdmlkZW9UcmFja3NbMF0uaWRcbiAgXTtcblxuICBsaW5lcy5wdXNoKCcnKTtcblxuICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG59XG5cbi8qKlxuICogV3JhcHBlciBvYmplY3Qgb2YgYW4gUlRDUGVlckNvbm5lY3Rpb24uIFRoaXMgb2JqZWN0IGlzIGFpbWVkIHRvIHNpbXBsaWZ5IHRoZVxuICogZGV2ZWxvcG1lbnQgb2YgV2ViUlRDLWJhc2VkIGFwcGxpY2F0aW9ucy5cbiAqXG4gKiBAY29uc3RydWN0b3IgbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1vZGUgTW9kZSBpbiB3aGljaCB0aGUgUGVlckNvbm5lY3Rpb24gd2lsbCBiZSBjb25maWd1cmVkLlxuICogIFZhbGlkIHZhbHVlcyBhcmU6ICdyZWN2JywgJ3NlbmQnLCBhbmQgJ3NlbmRSZWN2J1xuICogQHBhcmFtIGxvY2FsVmlkZW8gVmlkZW8gdGFnIGZvciB0aGUgbG9jYWwgc3RyZWFtXG4gKiBAcGFyYW0gcmVtb3RlVmlkZW8gVmlkZW8gdGFnIGZvciB0aGUgcmVtb3RlIHN0cmVhbVxuICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gdmlkZW9TdHJlYW0gU3RyZWFtIHRvIGJlIHVzZWQgYXMgcHJpbWFyeSBzb3VyY2VcbiAqICAodHlwaWNhbGx5IHZpZGVvIGFuZCBhdWRpbywgb3Igb25seSB2aWRlbyBpZiBjb21iaW5lZCB3aXRoIGF1ZGlvU3RyZWFtKSBmb3JcbiAqICBsb2NhbFZpZGVvIGFuZCB0byBiZSBhZGRlZCBhcyBzdHJlYW0gdG8gdGhlIFJUQ1BlZXJDb25uZWN0aW9uXG4gKiBAcGFyYW0ge01lZGlhU3RyZWFtfSBhdWRpb1N0cmVhbSBTdHJlYW0gdG8gYmUgdXNlZCBhcyBzZWNvbmQgc291cmNlXG4gKiAgKHR5cGljYWxseSBmb3IgYXVkaW8pIGZvciBsb2NhbFZpZGVvIGFuZCB0byBiZSBhZGRlZCBhcyBzdHJlYW0gdG8gdGhlXG4gKiAgUlRDUGVlckNvbm5lY3Rpb25cbiAqL1xuZnVuY3Rpb24gV2ViUnRjUGVlcihtb2RlLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlcikpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXIobW9kZSwgb3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyLnN1cGVyXy5jYWxsKHRoaXMpXG5cbiAgaWYgKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIGNhbGxiYWNrID0gb3B0aW9uc1xuICAgIG9wdGlvbnMgPSB1bmRlZmluZWRcbiAgfVxuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gIGNhbGxiYWNrID0gKGNhbGxiYWNrIHx8IG5vb3ApLmJpbmQodGhpcylcblxuICB2YXIgc2VsZiA9IHRoaXNcbiAgdmFyIGxvY2FsVmlkZW8gPSBvcHRpb25zLmxvY2FsVmlkZW9cbiAgdmFyIHJlbW90ZVZpZGVvID0gb3B0aW9ucy5yZW1vdGVWaWRlb1xuICB2YXIgdmlkZW9TdHJlYW0gPSBvcHRpb25zLnZpZGVvU3RyZWFtXG4gIHZhciBhdWRpb1N0cmVhbSA9IG9wdGlvbnMuYXVkaW9TdHJlYW1cbiAgdmFyIG1lZGlhQ29uc3RyYWludHMgPSBvcHRpb25zLm1lZGlhQ29uc3RyYWludHNcblxuICB2YXIgY29ubmVjdGlvbkNvbnN0cmFpbnRzID0gb3B0aW9ucy5jb25uZWN0aW9uQ29uc3RyYWludHNcbiAgdmFyIHBjID0gb3B0aW9ucy5wZWVyQ29ubmVjdGlvblxuICB2YXIgc2VuZFNvdXJjZSA9IG9wdGlvbnMuc2VuZFNvdXJjZSB8fCAnd2ViY2FtJ1xuXG4gIC8qdmFyIGRhdGFDaGFubmVsQ29uZmlnID0gb3B0aW9ucy5kYXRhQ2hhbm5lbENvbmZpZ1xuICB2YXIgdXNlRGF0YUNoYW5uZWxzID0gb3B0aW9ucy5kYXRhQ2hhbm5lbHMgfHwgZmFsc2VcbiAgdmFyIGRhdGFDaGFubmVsKi9cblxuICB2YXIgZ3VpZCA9IHV1aWQudjQoKVxuICB2YXIgY29uZmlndXJhdGlvbiA9IHJlY3Vyc2l2ZSh7XG4gICAgICBpY2VTZXJ2ZXJzOiAoISFvcHRpb25zLmljZVNlcnZlcnMgJiYgb3B0aW9ucy5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDApID8gb3B0aW9ucy5pY2VTZXJ2ZXJzIDogZnJlZWljZSgpXG4gICAgfSxcbiAgICBvcHRpb25zLmNvbmZpZ3VyYXRpb24pXG5cbiAgdmFyIG9uaWNlY2FuZGlkYXRlID0gb3B0aW9ucy5vbmljZWNhbmRpZGF0ZVxuICBpZiAob25pY2VjYW5kaWRhdGUpIHRoaXMub24oJ2ljZWNhbmRpZGF0ZScsIG9uaWNlY2FuZGlkYXRlKVxuXG4gIHZhciBvbmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBvcHRpb25zLm9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZVxuICBpZiAob25jYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgdGhpcy5vbignY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScsIG9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSlcbiAgfVxuXG4gIHZhciBzaW11bGNhc3QgPSBvcHRpb25zLnNpbXVsY2FzdFxuICB2YXIgbXVsdGlzdHJlYW0gPSBvcHRpb25zLm11bHRpc3RyZWFtXG4gIHZhciBpbnRlcm9wID0gbmV3IHNkcFRyYW5zbGF0b3IuSW50ZXJvcCgpXG4gIHZhciBjYW5kaWRhdGVzUXVldWVPdXQgPSBbXVxuICB2YXIgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGhpcywge1xuICAgICdwZWVyQ29ubmVjdGlvbic6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcGNcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2lkJzoge1xuICAgICAgdmFsdWU6IG9wdGlvbnMuaWQgfHwgZ3VpZCxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZVxuICAgIH0sXG5cbiAgICAncmVtb3RlVmlkZW8nOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHJlbW90ZVZpZGVvXG4gICAgICB9XG4gICAgfSxcblxuICAgICdsb2NhbFZpZGVvJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBsb2NhbFZpZGVvXG4gICAgICB9XG4gICAgfSxcblxuICAgIC8qJ2RhdGFDaGFubmVsJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkYXRhQ2hhbm5lbFxuICAgICAgfVxuICAgIH0sKi9cblxuICAgIC8qKlxuICAgICAqIEBtZW1iZXIgeyhleHRlcm5hbDpJbWFnZURhdGF8dW5kZWZpbmVkKX0gY3VycmVudEZyYW1lXG4gICAgICovXG4gICAgJ2N1cnJlbnRGcmFtZSc6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBbVG9Eb10gRmluZCBzb2x1dGlvbiB3aGVuIHdlIGhhdmUgYSByZW1vdGUgc3RyZWFtIGJ1dCB3ZSBkaWRuJ3Qgc2V0XG4gICAgICAgIC8vIGEgcmVtb3RlVmlkZW8gdGFnXG4gICAgICAgIGlmICghcmVtb3RlVmlkZW8pIHJldHVybjtcblxuICAgICAgICBpZiAocmVtb3RlVmlkZW8ucmVhZHlTdGF0ZSA8IHJlbW90ZVZpZGVvLkhBVkVfQ1VSUkVOVF9EQVRBKVxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gdmlkZW8gc3RyZWFtIGRhdGEgYXZhaWxhYmxlJylcblxuICAgICAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcbiAgICAgICAgY2FudmFzLndpZHRoID0gcmVtb3RlVmlkZW8udmlkZW9XaWR0aFxuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gcmVtb3RlVmlkZW8udmlkZW9IZWlnaHRcblxuICAgICAgICBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKS5kcmF3SW1hZ2UocmVtb3RlVmlkZW8sIDAsIDApXG5cbiAgICAgICAgcmV0dXJuIGNhbnZhc1xuICAgICAgfVxuICAgIH1cbiAgfSlcblxuICAvLyBJbml0IFBlZXJDb25uZWN0aW9uXG4gIGlmICghcGMpIHtcbiAgICBwYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbihjb25maWd1cmF0aW9uKTtcbiAgICAvKmlmICh1c2VEYXRhQ2hhbm5lbHMgJiYgIWRhdGFDaGFubmVsKSB7XG4gICAgICB2YXIgZGNJZCA9ICdXZWJSdGNQZWVyLScgKyBzZWxmLmlkXG4gICAgICB2YXIgZGNPcHRpb25zID0gdW5kZWZpbmVkXG4gICAgICBpZiAoZGF0YUNoYW5uZWxDb25maWcpIHtcbiAgICAgICAgZGNJZCA9IGRhdGFDaGFubmVsQ29uZmlnLmlkIHx8IGRjSWRcbiAgICAgICAgZGNPcHRpb25zID0gZGF0YUNoYW5uZWxDb25maWcub3B0aW9uc1xuICAgICAgfVxuICAgICAgZGF0YUNoYW5uZWwgPSBwYy5jcmVhdGVEYXRhQ2hhbm5lbChkY0lkLCBkY09wdGlvbnMpO1xuICAgICAgaWYgKGRhdGFDaGFubmVsQ29uZmlnKSB7XG4gICAgICAgIGRhdGFDaGFubmVsLm9ub3BlbiA9IGRhdGFDaGFubmVsQ29uZmlnLm9ub3BlbjtcbiAgICAgICAgZGF0YUNoYW5uZWwub25jbG9zZSA9IGRhdGFDaGFubmVsQ29uZmlnLm9uY2xvc2U7XG4gICAgICAgIGRhdGFDaGFubmVsLm9ubWVzc2FnZSA9IGRhdGFDaGFubmVsQ29uZmlnLm9ubWVzc2FnZTtcbiAgICAgICAgZGF0YUNoYW5uZWwub25idWZmZXJlZGFtb3VudGxvdyA9IGRhdGFDaGFubmVsQ29uZmlnLm9uYnVmZmVyZWRhbW91bnRsb3c7XG4gICAgICAgIGRhdGFDaGFubmVsLm9uZXJyb3IgPSBkYXRhQ2hhbm5lbENvbmZpZy5vbmVycm9yIHx8IG5vb3A7XG4gICAgICB9XG4gICAgfSovXG4gIH1cblxuICBwYy5hZGRFdmVudExpc3RlbmVyKCdpY2VjYW5kaWRhdGUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgY2FuZGlkYXRlID0gZXZlbnQuY2FuZGlkYXRlXG5cbiAgICBpZiAoRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQoc2VsZiwgJ2ljZWNhbmRpZGF0ZScpIHx8XG4gICAgICBFdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudChcbiAgICAgICAgc2VsZiwgJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSkge1xuICAgICAgaWYgKGNhbmRpZGF0ZSkge1xuICAgICAgICB2YXIgY2FuZFxuXG4gICAgICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgICAgIGNhbmQgPSBpbnRlcm9wLmNhbmRpZGF0ZVRvVW5pZmllZFBsYW4oY2FuZGlkYXRlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbmQgPSBjYW5kaWRhdGVcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYuZW1pdCgnaWNlY2FuZGlkYXRlJywgY2FuZClcbiAgICAgICAgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG4gICAgICB9IGVsc2UgaWYgKCFjYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgICAgIHNlbGYuZW1pdCgnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpXG4gICAgICAgIGNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgLy8gTm90IGxpc3RlbmluZyB0byAnaWNlY2FuZGlkYXRlJyBvciAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScgZXZlbnRzLCBxdWV1ZVxuICAgICAgLy8gdGhlIGNhbmRpZGF0ZSB1bnRpbCBvbmUgb2YgdGhlbSBpcyBsaXN0ZW5lZFxuICAgICAgY2FuZGlkYXRlc1F1ZXVlT3V0LnB1c2goY2FuZGlkYXRlKVxuXG4gICAgICBpZiAoIWNhbmRpZGF0ZSkgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWVcbiAgICB9XG4gIH0pXG5cbiAgcGMub25hZGRzdHJlYW0gPSBvcHRpb25zLm9uYWRkc3RyZWFtXG4gIHBjLm9ubmVnb3RpYXRpb25uZWVkZWQgPSBvcHRpb25zLm9ubmVnb3RpYXRpb25uZWVkZWRcbiAgdGhpcy5vbignbmV3TGlzdGVuZXInLCBmdW5jdGlvbiAoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgaWYgKGV2ZW50ID09PSAnaWNlY2FuZGlkYXRlJyB8fCBldmVudCA9PT0gJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlT3V0Lmxlbmd0aCkge1xuICAgICAgICB2YXIgY2FuZGlkYXRlID0gY2FuZGlkYXRlc1F1ZXVlT3V0LnNoaWZ0KClcblxuICAgICAgICBpZiAoIWNhbmRpZGF0ZSA9PT0gKGV2ZW50ID09PSAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpKSB7XG4gICAgICAgICAgbGlzdGVuZXIoY2FuZGlkYXRlKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4gIHZhciBhZGRJY2VDYW5kaWRhdGUgPSBidWZmZXJpemVDYW5kaWRhdGVzKHBjKVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYW4gSUNFIGNhbmRpZGF0ZSBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUuYWRkSWNlQ2FuZGlkYXRlXG4gICAqXG4gICAqIEBwYXJhbSBpY2VDYW5kaWRhdGUgLSBMaXRlcmFsIG9iamVjdCB3aXRoIHRoZSBJQ0UgY2FuZGlkYXRlIGRlc2NyaXB0aW9uXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtIENhbGxlZCB3aGVuIHRoZSBJQ0UgY2FuZGlkYXRlIGhhcyBiZWVuIGFkZGVkLlxuICAgKi9cbiAgdGhpcy5hZGRJY2VDYW5kaWRhdGUgPSBmdW5jdGlvbiAoaWNlQ2FuZGlkYXRlLCBjYWxsYmFjaykge1xuICAgIHZhciBjYW5kaWRhdGVcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgY2FuZGlkYXRlID0gaW50ZXJvcC5jYW5kaWRhdGVUb1BsYW5CKGljZUNhbmRpZGF0ZSlcbiAgICB9IGVsc2Uge1xuICAgICAgY2FuZGlkYXRlID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpXG4gICAgfVxuXG4gICAgbG9nZ2VyLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSlcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSwgY2FsbGJhY2spXG4gIH1cblxuICB0aGlzLmdlbmVyYXRlT2ZmZXIgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrLmJpbmQodGhpcylcblxuICAgIHZhciBvZmZlckF1ZGlvID0gdHJ1ZVxuICAgIHZhciBvZmZlclZpZGVvID0gdHJ1ZVxuICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgIGlmIChtZWRpYUNvbnN0cmFpbnRzKSB7XG4gICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvID09PSAnYm9vbGVhbicpID9cbiAgICAgICAgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA6IHRydWVcbiAgICAgIG9mZmVyVmlkZW8gPSAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZVxuICAgIH1cblxuICAgIHZhciBicm93c2VyRGVwZW5kYW50Q29uc3RyYWludHMgPSB7XG4gICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiAobW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgIG9mZmVyVG9SZWNlaXZlVmlkZW86IChtb2RlICE9PSAnc2VuZG9ubHknICYmIG9mZmVyVmlkZW8pXG4gICAgfVxuXG4gICAgLy9GSVhNRTogY2xhcmlmeSBwb3NzaWJsZSBjb25zdHJhaW50cyBwYXNzZWQgdG8gY3JlYXRlT2ZmZXIoKVxuICAgIC8qdmFyIGNvbnN0cmFpbnRzID0gcmVjdXJzaXZlKGJyb3dzZXJEZXBlbmRhbnRDb25zdHJhaW50cyxcbiAgICAgIGNvbm5lY3Rpb25Db25zdHJhaW50cykqL1xuXG4gICAgdmFyIGNvbnN0cmFpbnRzID0gYnJvd3NlckRlcGVuZGFudENvbnN0cmFpbnRzO1xuXG4gICAgbG9nZ2VyLmRlYnVnKCdjb25zdHJhaW50czogJyArIEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSlcblxuICAgIHBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKGZ1bmN0aW9uIChvZmZlcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpXG4gICAgICBvZmZlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KG9mZmVyKVxuICAgICAgcmV0dXJuIHBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgbG9jYWxEZXNjcmlwdGlvbiA9IHBjLmxvY2FsRGVzY3JpcHRpb25cbiAgICAgIGxvZ2dlci5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApXG4gICAgICBpZiAobXVsdGlzdHJlYW0gJiYgdXNlUGxhbkIpIHtcbiAgICAgICAgbG9jYWxEZXNjcmlwdGlvbiA9IGludGVyb3AudG9VbmlmaWVkUGxhbihsb2NhbERlc2NyaXB0aW9uKVxuICAgICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpvcmlnUGxhbkItPlVuaWZpZWRQbGFuJywgZHVtcFNEUChcbiAgICAgICAgICBsb2NhbERlc2NyaXB0aW9uKSlcbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwLCBzZWxmLnByb2Nlc3NBbnN3ZXIuYmluZChcbiAgICAgICAgc2VsZikpXG4gICAgfSkuY2F0Y2goY2FsbGJhY2spXG4gIH1cblxuICB0aGlzLmdldExvY2FsU2Vzc2lvbkRlc2NyaXB0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHBjLmxvY2FsRGVzY3JpcHRpb25cbiAgfVxuXG4gIHRoaXMuZ2V0UmVtb3RlU2Vzc2lvbkRlc2NyaXB0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHBjLnJlbW90ZURlc2NyaXB0aW9uXG4gIH1cblxuICBmdW5jdGlvbiBzZXRSZW1vdGVWaWRlbygpIHtcbiAgICBpZiAocmVtb3RlVmlkZW8pIHtcbiAgICAgIHJlbW90ZVZpZGVvLnBhdXNlKClcblxuICAgICAgdmFyIHN0cmVhbSA9IHBjLmdldFJlbW90ZVN0cmVhbXMoKVswXVxuICAgICAgcmVtb3RlVmlkZW8uc3JjT2JqZWN0ID0gc3RyZWFtXG4gICAgICBsb2dnZXIuZGVidWcoJ1JlbW90ZSBzdHJlYW06Jywgc3RyZWFtKVxuXG4gICAgICByZW1vdGVWaWRlby5sb2FkKClcbiAgICB9XG4gIH1cblxuICB0aGlzLnNob3dMb2NhbFZpZGVvID0gZnVuY3Rpb24gKCkge1xuICAgIGxvY2FsVmlkZW8uc3JjT2JqZWN0ID0gdmlkZW9TdHJlYW1cbiAgICBsb2NhbFZpZGVvLm11dGVkID0gdHJ1ZVxuICB9XG5cbiAgLyp0aGlzLnNlbmQgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIGlmIChkYXRhQ2hhbm5lbCAmJiBkYXRhQ2hhbm5lbC5yZWFkeVN0YXRlID09PSAnb3BlbicpIHtcbiAgICAgIGRhdGFDaGFubmVsLnNlbmQoZGF0YSlcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICdUcnlpbmcgdG8gc2VuZCBkYXRhIG92ZXIgYSBub24tZXhpc3Rpbmcgb3IgY2xvc2VkIGRhdGEgY2hhbm5lbCcpXG4gICAgfVxuICB9Ki9cblxuICAvKipcbiAgICogQ2FsbGJhY2sgZnVuY3Rpb24gaW52b2tlZCB3aGVuIGEgU0RQIGFuc3dlciBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUucHJvY2Vzc0Fuc3dlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwQW5zd2VyIC0gRGVzY3JpcHRpb24gb2Ygc2RwQW5zd2VyXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtXG4gICAqICAgICAgICAgICAgSW52b2tlZCBhZnRlciB0aGUgU0RQIGFuc3dlciBpcyBwcm9jZXNzZWQsIG9yIHRoZXJlIGlzIGFuIGVycm9yLlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzQW5zd2VyID0gZnVuY3Rpb24gKHNkcEFuc3dlciwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG5cbiAgICB2YXIgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICB0eXBlOiAnYW5zd2VyJyxcbiAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CQW5zd2VyID0gaW50ZXJvcC50b1BsYW5CKGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnYXNud2VyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJBbnN3ZXIpKVxuICAgICAgYW5zd2VyID0gcGxhbkJBbnN3ZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJylcblxuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjaygnUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJylcbiAgICB9XG5cbiAgICBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2V0UmVtb3RlVmlkZW8oKVxuXG4gICAgICAgIGNhbGxiYWNrKClcbiAgICAgIH0sXG4gICAgICBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgb2ZmZXIgaXMgcmVjZWl2ZWQuIERldmVsb3BlcnMgYXJlXG4gICAqIGV4cGVjdGVkIHRvIGludm9rZSB0aGlzIGZ1bmN0aW9uIGluIG9yZGVyIHRvIGNvbXBsZXRlIHRoZSBTRFAgbmVnb3RpYXRpb24uXG4gICAqXG4gICAqIEBmdW5jdGlvbiBtb2R1bGU6a3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIucHJvdG90eXBlLnByb2Nlc3NPZmZlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwT2ZmZXIgLSBEZXNjcmlwdGlvbiBvZiBzZHBPZmZlclxuICAgKiBAcGFyYW0gY2FsbGJhY2sgLSBDYWxsZWQgd2hlbiB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIGhhcyBiZWVuIHNldFxuICAgKiAgc3VjY2Vzc2Z1bGx5LlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzT2ZmZXIgPSBmdW5jdGlvbiAoc2RwT2ZmZXIsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjay5iaW5kKHRoaXMpXG5cbiAgICB2YXIgb2ZmZXIgPSBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICBzZHA6IHNkcE9mZmVyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CT2ZmZXIgPSBpbnRlcm9wLnRvUGxhbkIob2ZmZXIpXG4gICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJPZmZlcikpXG4gICAgICBvZmZlciA9IHBsYW5CT2ZmZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKVxuXG4gICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKVxuICAgIH1cblxuICAgIHBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBzZXRSZW1vdGVWaWRlbygpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcGMuY3JlYXRlQW5zd2VyKClcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChhbnN3ZXIpIHtcbiAgICAgIGFuc3dlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJylcbiAgICAgIHJldHVybiBwYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcilcbiAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBsb2NhbERlc2NyaXB0aW9uID0gcGMubG9jYWxEZXNjcmlwdGlvblxuICAgICAgaWYgKG11bHRpc3RyZWFtICYmIHVzZVBsYW5CKSB7XG4gICAgICAgIGxvY2FsRGVzY3JpcHRpb24gPSBpbnRlcm9wLnRvVW5pZmllZFBsYW4obG9jYWxEZXNjcmlwdGlvbilcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdhbnN3ZXI6Om9yaWdQbGFuQi0+VW5pZmllZFBsYW4nLCBkdW1wU0RQKFxuICAgICAgICAgIGxvY2FsRGVzY3JpcHRpb24pKVxuICAgICAgfVxuICAgICAgbG9nZ2VyLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcClcbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwKVxuICAgIH0pLmNhdGNoKGNhbGxiYWNrKVxuICB9XG5cbiAgZnVuY3Rpb24gbWFuZ2xlU2RwVG9BZGRTaW11bGNhc3QoYW5zd2VyKSB7XG4gICAgaWYgKHNpbXVsY2FzdCkge1xuICAgICAgaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnQWRkaW5nIG11bHRpY2FzdCBpbmZvJylcbiAgICAgICAgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgJ3R5cGUnOiBhbnN3ZXIudHlwZSxcbiAgICAgICAgICAnc2RwJzogcmVtb3ZlRklERnJvbU9mZmVyKGFuc3dlci5zZHApICsgZ2V0U2ltdWxjYXN0SW5mbyhcbiAgICAgICAgICAgIHZpZGVvU3RyZWFtKVxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1NpbXVsY2FzdCBpcyBvbmx5IGF2YWlsYWJsZSBpbiBDaHJvbWUgYnJvd3Nlci4nKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhbnN3ZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdCB0YWtpbmcgaW50byBhY2NvdW50IHRoZVxuICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICogY2FsbGJhY2sgaXMgZXhwZWN0ZWQgdG8gc2VuZCB0aGUgU0RQIG9mZmVyLCBpbiBvcmRlciB0byBvYnRhaW4gYW4gU0RQXG4gICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICovXG4gIGZ1bmN0aW9uIHN0YXJ0KCkge1xuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIGNhbGxiYWNrKFxuICAgICAgICAnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnXG4gICAgICApXG4gICAgfVxuXG4gICAgaWYgKHZpZGVvU3RyZWFtICYmIGxvY2FsVmlkZW8pIHtcbiAgICAgIHNlbGYuc2hvd0xvY2FsVmlkZW8oKVxuICAgIH1cblxuICAgIGlmICh2aWRlb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKHZpZGVvU3RyZWFtKVxuICAgIH1cblxuICAgIGlmIChhdWRpb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKGF1ZGlvU3RyZWFtKVxuICAgIH1cblxuICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgdmFyIGJyb3dzZXIgPSBwYXJzZXIuZ2V0QnJvd3NlcigpXG4gICAgaWYgKG1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgIChicm93c2VyLm5hbWUgPT09ICdDaHJvbWUnIHx8IGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9taXVtJykgJiZcbiAgICAgIGJyb3dzZXIubWFqb3IgPT09IDM5KSB7XG4gICAgICBtb2RlID0gJ3NlbmRyZWN2J1xuICAgIH1cblxuICAgIGNhbGxiYWNrKClcbiAgfVxuXG4gIGlmIChtb2RlICE9PSAncmVjdm9ubHknICYmICF2aWRlb1N0cmVhbSAmJiAhYXVkaW9TdHJlYW0pIHtcbiAgICBmdW5jdGlvbiBnZXRNZWRpYShjb25zdHJhaW50cykge1xuICAgICAgaWYgKGNvbnN0cmFpbnRzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3RyYWludHMgPSBNRURJQV9DT05TVFJBSU5UU1xuICAgICAgfVxuXG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cykudGhlbihmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4gICAgICAgIHN0YXJ0KClcbiAgICAgIH0pLmNhdGNoKGNhbGxiYWNrKTtcbiAgICB9XG4gICAgaWYgKHNlbmRTb3VyY2UgPT09ICd3ZWJjYW0nKSB7XG4gICAgICBnZXRNZWRpYShtZWRpYUNvbnN0cmFpbnRzKVxuICAgIH0gZWxzZSB7XG4gICAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhzZW5kU291cmNlLCBmdW5jdGlvbiAoZXJyb3IsIGNvbnN0cmFpbnRzXykge1xuICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycm9yKVxuXG4gICAgICAgIGNvbnN0cmFpbnRzID0gW21lZGlhQ29uc3RyYWludHNdXG4gICAgICAgIGNvbnN0cmFpbnRzLnVuc2hpZnQoY29uc3RyYWludHNfKVxuICAgICAgICBnZXRNZWRpYShyZWN1cnNpdmUuYXBwbHkodW5kZWZpbmVkLCBjb25zdHJhaW50cykpXG4gICAgICB9LCBndWlkKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBzZXRUaW1lb3V0KHN0YXJ0LCAwKVxuICB9XG5cbiAgdGhpcy5vbignX2Rpc3Bvc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGxvY2FsVmlkZW8pIHtcbiAgICAgIGxvY2FsVmlkZW8ucGF1c2UoKVxuICAgICAgbG9jYWxWaWRlby5zcmNPYmplY3QgPSBudWxsXG4gICAgICBsb2NhbFZpZGVvLmxvYWQoKVxuICAgICAgLy9Vbm11dGUgbG9jYWwgdmlkZW8gaW4gY2FzZSB0aGUgdmlkZW8gdGFnIGlzIGxhdGVyIHVzZWQgZm9yIHJlbW90ZSB2aWRlb1xuICAgICAgbG9jYWxWaWRlby5tdXRlZCA9IGZhbHNlXG4gICAgfVxuICAgIGlmIChyZW1vdGVWaWRlbykge1xuICAgICAgcmVtb3RlVmlkZW8ucGF1c2UoKVxuICAgICAgcmVtb3RlVmlkZW8uc3JjT2JqZWN0ID0gbnVsbFxuICAgICAgcmVtb3RlVmlkZW8ubG9hZCgpXG4gICAgfVxuICAgIHNlbGYucmVtb3ZlQWxsTGlzdGVuZXJzKClcblxuICAgIGlmICh3aW5kb3cuY2FuY2VsQ2hvb3NlRGVza3RvcE1lZGlhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHdpbmRvdy5jYW5jZWxDaG9vc2VEZXNrdG9wTWVkaWEoZ3VpZClcbiAgICB9XG4gIH0pXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyLCBFdmVudEVtaXR0ZXIpXG5cbmZ1bmN0aW9uIGNyZWF0ZUVuYWJsZURlc2NyaXB0b3IodHlwZSkge1xuICB2YXIgbWV0aG9kID0gJ2dldCcgKyB0eXBlICsgJ1RyYWNrcydcblxuICByZXR1cm4ge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBbVG9Eb10gU2hvdWxkIHJldHVybiB1bmRlZmluZWQgaWYgbm90IGFsbCB0cmFja3MgaGF2ZSB0aGUgc2FtZSB2YWx1ZT9cblxuICAgICAgaWYgKCF0aGlzLnBlZXJDb25uZWN0aW9uKSByZXR1cm5cblxuICAgICAgdmFyIHN0cmVhbXMgPSB0aGlzLnBlZXJDb25uZWN0aW9uLmdldExvY2FsU3RyZWFtcygpXG4gICAgICBpZiAoIXN0cmVhbXMubGVuZ3RoKSByZXR1cm5cblxuICAgICAgZm9yICh2YXIgaSA9IDAsIHN0cmVhbTsgc3RyZWFtID0gc3RyZWFtc1tpXTsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFja3MgPSBzdHJlYW1bbWV0aG9kXSgpXG4gICAgICAgIGZvciAodmFyIGogPSAwLCB0cmFjazsgdHJhY2sgPSB0cmFja3Nbal07IGorKylcbiAgICAgICAgICBpZiAoIXRyYWNrLmVuYWJsZWQpIHJldHVybiBmYWxzZVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgIGZ1bmN0aW9uIHRyYWNrU2V0RW5hYmxlKHRyYWNrKSB7XG4gICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZVxuICAgICAgfVxuXG4gICAgICB0aGlzLnBlZXJDb25uZWN0aW9uLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goZnVuY3Rpb24gKHN0cmVhbSkge1xuICAgICAgICBzdHJlYW1bbWV0aG9kXSgpLmZvckVhY2godHJhY2tTZXRFbmFibGUpXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydGllcyhXZWJSdGNQZWVyLnByb3RvdHlwZSwge1xuICAnZW5hYmxlZCc6IHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuYXVkaW9FbmFibGVkICYmIHRoaXMudmlkZW9FbmFibGVkXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgdGhpcy5hdWRpb0VuYWJsZWQgPSB0aGlzLnZpZGVvRW5hYmxlZCA9IHZhbHVlXG4gICAgfVxuICB9LFxuICAnYXVkaW9FbmFibGVkJzogY3JlYXRlRW5hYmxlRGVzY3JpcHRvcignQXVkaW8nKSxcbiAgJ3ZpZGVvRW5hYmxlZCc6IGNyZWF0ZUVuYWJsZURlc2NyaXB0b3IoJ1ZpZGVvJylcbn0pXG5cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmdldExvY2FsU3RyZWFtID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gIGlmICh0aGlzLnBlZXJDb25uZWN0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMucGVlckNvbm5lY3Rpb24uZ2V0TG9jYWxTdHJlYW1zKClbaW5kZXggfHwgMF1cbiAgfVxufVxuXG5XZWJSdGNQZWVyLnByb3RvdHlwZS5nZXRSZW1vdGVTdHJlYW0gPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgaWYgKHRoaXMucGVlckNvbm5lY3Rpb24pIHtcbiAgICByZXR1cm4gdGhpcy5wZWVyQ29ubmVjdGlvbi5nZXRSZW1vdGVTdHJlYW1zKClbaW5kZXggfHwgMF1cbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUaGlzIG1ldGhvZCBmcmVlcyB0aGUgcmVzb3VyY2VzIHVzZWQgYnkgV2ViUnRjUGVlci5cbiAqXG4gKiBAZnVuY3Rpb24gbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyLnByb3RvdHlwZS5kaXNwb3NlXG4gKi9cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmRpc3Bvc2UgPSBmdW5jdGlvbiAoKSB7XG4gIGxvZ2dlci5kZWJ1ZygnRGlzcG9zaW5nIFdlYlJ0Y1BlZXInKVxuXG4gIHZhciBwYyA9IHRoaXMucGVlckNvbm5lY3Rpb25cbiAgLy92YXIgZGMgPSB0aGlzLmRhdGFDaGFubmVsXG4gIHRyeSB7XG4gICAgLyppZiAoZGMpIHtcbiAgICAgIGlmIChkYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHJldHVyblxuXG4gICAgICBkYy5jbG9zZSgpXG4gICAgfSovXG5cbiAgICBpZiAocGMpIHtcbiAgICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHJldHVyblxuXG4gICAgICBwYy5nZXRMb2NhbFN0cmVhbXMoKS5mb3JFYWNoKHN0cmVhbVN0b3ApXG5cbiAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAvLyBpZih2aWRlb1N0cmVhbSkgcGMucmVtb3ZlU3RyZWFtKHZpZGVvU3RyZWFtKTtcbiAgICAgIC8vIGlmKGF1ZGlvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0oYXVkaW9TdHJlYW0pO1xuXG4gICAgICBwYy5jbG9zZSgpXG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIud2FybignRXhjZXB0aW9uIGRpc3Bvc2luZyB3ZWJydGMgcGVlciAnICsgZXJyKVxuICB9XG5cbiAgdGhpcy5lbWl0KCdfZGlzcG9zZScpXG59XG5cbi8vXG4vLyBTcGVjaWFsaXplZCBjaGlsZCBjbGFzc2VzXG4vL1xuXG5mdW5jdGlvbiBXZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgY2FsbGJhY2spIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFdlYlJ0Y1BlZXJSZWN2b25seSkpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zLCBjYWxsYmFjaylcbiAgfVxuXG4gIFdlYlJ0Y1BlZXJSZWN2b25seS5zdXBlcl8uY2FsbCh0aGlzLCAncmVjdm9ubHknLCBvcHRpb25zLCBjYWxsYmFjaylcbn1cbmluaGVyaXRzKFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlcilcblxuZnVuY3Rpb24gV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBXZWJSdGNQZWVyU2VuZG9ubHkpKSB7XG4gICAgcmV0dXJuIG5ldyBXZWJSdGNQZWVyU2VuZG9ubHkob3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyU2VuZG9ubHkuc3VwZXJfLmNhbGwodGhpcywgJ3NlbmRvbmx5Jywgb3B0aW9ucywgY2FsbGJhY2spXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXIpXG5cbmZ1bmN0aW9uIFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlclNlbmRyZWN2KSkge1xuICAgIHJldHVybiBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGNhbGxiYWNrKVxuICB9XG5cbiAgV2ViUnRjUGVlclNlbmRyZWN2LnN1cGVyXy5jYWxsKHRoaXMsICdzZW5kcmVjdicsIG9wdGlvbnMsIGNhbGxiYWNrKVxufVxuaW5oZXJpdHMoV2ViUnRjUGVlclNlbmRyZWN2LCBXZWJSdGNQZWVyKVxuXG5mdW5jdGlvbiBoYXJrVXRpbHMoc3RyZWFtLCBvcHRpb25zKSB7XG4gIHJldHVybiBoYXJrKHN0cmVhbSwgb3B0aW9ucyk7XG59XG5cbmV4cG9ydHMuYnVmZmVyaXplQ2FuZGlkYXRlcyA9IGJ1ZmZlcml6ZUNhbmRpZGF0ZXNcblxuZXhwb3J0cy5XZWJSdGNQZWVyUmVjdm9ubHkgPSBXZWJSdGNQZWVyUmVjdm9ubHlcbmV4cG9ydHMuV2ViUnRjUGVlclNlbmRvbmx5ID0gV2ViUnRjUGVlclNlbmRvbmx5XG5leHBvcnRzLldlYlJ0Y1BlZXJTZW5kcmVjdiA9IFdlYlJ0Y1BlZXJTZW5kcmVjdlxuZXhwb3J0cy5oYXJrID0gaGFya1V0aWxzXG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBUaGlzIG1vZHVsZSBjb250YWlucyBhIHNldCBvZiByZXVzYWJsZSBjb21wb25lbnRzIHRoYXQgaGF2ZSBiZWVuIGZvdW5kIHVzZWZ1bFxuICogZHVyaW5nIHRoZSBkZXZlbG9wbWVudCBvZiB0aGUgV2ViUlRDIGFwcGxpY2F0aW9ucyB3aXRoIEt1cmVudG8uXG4gKiBcbiAqIEBtb2R1bGUga3VyZW50b1V0aWxzXG4gKiBcbiAqIEBjb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICogQGxpY2Vuc2UgQUx2MlxuICovXG5cbnZhciBXZWJSdGNQZWVyID0gcmVxdWlyZSgnLi9XZWJSdGNQZWVyJyk7XG5cbmV4cG9ydHMuV2ViUnRjUGVlciA9IFdlYlJ0Y1BlZXI7XG4iLCIvLyBMYXN0IHRpbWUgdXBkYXRlZCBvbiBEZWNlbWJlciAxMywgMjAxN1xuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYoc291cmNlSWQgPT0gJ2ZpcmVmb3gnKSB7XG4gICAgICAgIG5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzLCBvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2UgbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMsIG9uU3VjY2Vzcywgb25GYWlsdXJlKTtcbn0pO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhlcnJvciwgc291cmNlSWQpIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmIChzb3VyY2VJZCkge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMudmlkZW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2NyZWVuX2NvbnN0cmFpbnRzO1xufVxuXG52YXIgaWZyYW1lO1xuXG5mdW5jdGlvbiBwb3N0R2V0U291cmNlSWRNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldFNvdXJjZUlkTWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGNhcHR1cmVTb3VyY2VJZDogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmZ1bmN0aW9uIGxvYWRJRnJhbWUobG9hZENhbGxiYWNrKSB7XG4gICAgaWYgKGlmcmFtZSkge1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO1xuICAgIGlmcmFtZS5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmcmFtZS5pc0xvYWRlZCA9IHRydWU7XG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgIH07XG4gICAgaWZyYW1lLnNyYyA9ICdodHRwczovL3d3dy53ZWJydGMtZXhwZXJpbWVudC5jb20vZ2V0U291cmNlSWQvJztcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbn07XG5cbmZ1bmN0aW9uIHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzOiB0cnVlXG4gICAgfSwgJyonKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5JZCA9IGdldFNjcmVlbklkOyIsIi8vIGdsb2JhbCB2YXJpYWJsZXNcbnZhciBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xudmFyIHNjcmVlbkNhbGxiYWNrO1xudmFyIGlzRmlyZWZveCA9IHR5cGVvZiB3aW5kb3cuSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnO1xudmFyIGlzT3BlcmEgPSAhIXdpbmRvdy5vcGVyYSB8fCBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJyBPUFIvJykgPj0gMDtcbnZhciBpc0Nocm9tZSA9ICEhd2luZG93LmNocm9tZSAmJiAhaXNPcGVyYTtcblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBpZiAoZXZlbnQub3JpZ2luICE9IHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBvbk1lc3NhZ2VDYWxsYmFjayhldmVudC5kYXRhKTtcbn0pO1xuXG4vLyBhbmQgdGhlIGZ1bmN0aW9uIHRoYXQgaGFuZGxlcyByZWNlaXZlZCBtZXNzYWdlc1xuZnVuY3Rpb24gb25NZXNzYWdlQ2FsbGJhY2soZGF0YSkge1xuICAgIC8vIFwiY2FuY2VsXCIgYnV0dG9uIGlzIGNsaWNrZWRcbiAgICBpZiAoZGF0YSA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJykge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InO1xuICAgICAgICBpZiAoc2NyZWVuQ2FsbGJhY2spXG4gICAgICAgICAgICByZXR1cm4gc2NyZWVuQ2FsbGJhY2soJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gbm90aWZpZWQgaGlzIHByZXNlbmNlXG4gICAgaWYgKGRhdGEgPT0gJ3J0Y211bHRpY29ubmVjdGlvbi1leHRlbnNpb24tbG9hZGVkJykge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdkZXNrdG9wJztcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIHNoYXJlZCB0ZW1wIHNvdXJjZUlkXG4gICAgaWYgKGRhdGEuc291cmNlSWQgJiYgc2NyZWVuQ2FsbGJhY2spIHtcbiAgICAgICAgc2NyZWVuQ2FsbGJhY2soc291cmNlSWQgPSBkYXRhLnNvdXJjZUlkKTtcbiAgICB9XG59XG5cbi8vIHRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGNoZWNrIGlmIGNocm9tZSBleHRlbnNpb24gaXMgaW5zdGFsbGVkICYgZW5hYmxlZC5cbmZ1bmN0aW9uIGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlKGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGZhbHNlKTtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKVxuICAgICAgICByZXR1cm4gY2FsbGJhY2soJ2lzRmlyZWZveCcpO1xuICAgIC8vIGFzayBleHRlbnNpb24gaWYgaXQgaXMgYXZhaWxhYmxlXG4gICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICBjYWxsYmFjaygndW5hdmFpbGFibGUnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBjYWxsYmFjaygnYXZhaWxhYmxlJyk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnYWpoaWZkZGlta2FwZ2NpZmdjb2RtbWZkbGtuYWhmZmsnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhleHRlbnNpb25pZCA9PSBleHRlbnNpb25pZCA/ICdpbnN0YWxsZWQtZW5hYmxlZCcgOiAnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIH0sIDIwMDApO1xuICAgIH07XG4gICAgaW1hZ2Uub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2FsbGJhY2soJ25vdC1pbnN0YWxsZWQnKTtcbiAgICB9O1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaykge1xuICAgIHNvdXJjZUlkID0gJyc7XG4gICAgdmFyIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyA9IHtcbiAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICBtZWRpYVNvdXJjZTogJ3dpbmRvdydcbiAgICB9O1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMpO1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IGRlZmluZXMgZ2V0VXNlck1lZGlhIGNvbnN0cmFpbnRzXG4gICAgLy8gdGhhdCB3aWxsIGJlIHVzZWQgdG8gY2FwdHVyZSBjb250ZW50IG9mIHNjcmVlblxuICAgIHZhciBzY3JlZW5fY29uc3RyYWludHMgPSB7XG4gICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGNocm9tZU1lZGlhU291cmNlLFxuICAgICAgICAgICAgbWF4V2lkdGg6IHNjcmVlbi53aWR0aCA+IDE5MjAgPyBzY3JlZW4ud2lkdGggOiAxOTIwLFxuICAgICAgICAgICAgbWF4SGVpZ2h0OiBzY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHNjcmVlbi5oZWlnaHQgOiAxMDgwXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbmFsOiBbXVxuICAgIH07XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgdmVyaWZpZXMgY2hyb21lIGV4dGVuc2lvbiBhdmFpbGFiaWxpdHlcbiAgICAvLyBpZiBpbnN0YWxsZWQgYW5kIGF2YWlsYWJsZSB0aGVuIGl0IHdpbGwgaW52b2tlIGV4dGVuc2lvbiBBUElcbiAgICAvLyBvdGhlcndpc2UgaXQgd2lsbCBmYWxsYmFjayB0byBjb21tYW5kLWxpbmUgYmFzZWQgc2NyZWVuIGNhcHR1cmluZyBBUElcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnICYmICFzb3VyY2VJZCkge1xuICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG4gICAgLy8gbm93IGludm9raW5nIG5hdGl2ZSBnZXRVc2VyTWVkaWEgQVBJXG4gICAgY2FsbGJhY2sobnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50cyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzO1xuZXhwb3J0cy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSA9IGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG5leHBvcnRzLmdldFNvdXJjZUlkID0gZ2V0U291cmNlSWQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vLyB0c2xpbnQ6ZGlzYWJsZTpuby1zdHJpbmctbGl0ZXJhbFxuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0ICogYXMgYWRhcHRlciBmcm9tICd3ZWJydGMtYWRhcHRlcic7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5leHBvcnQgY2xhc3MgV2ViUnRjU3RhdHMge1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0VuYWJsZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzSW50ZXJ2YWxJZDogTm9kZUpTLlRpbWVyO1xuICAgIHByaXZhdGUgc3RhdHNJbnRlcnZhbCA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBpbmJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvdXRib3VuZDoge1xuICAgICAgICAgICAgYXVkaW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogMCxcbiAgICAgICAgICAgICAgICBuYWNrQ291bnQ6IDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7IH1cblxuICAgIHB1YmxpYyBpc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2VsYXN0ZXN0LWluc3RydW1lbnRhdGlvbicpO1xuXG4gICAgICAgIGlmIChlbGFzdGVzdEluc3RydW1lbnRhdGlvbikge1xuICAgICAgICAgICAgLy8gRWxhc1Rlc3QgaW5zdHJ1bWVudGF0aW9uIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnN0cnVtZW50YXRpb24gPSBKU09OLnBhcnNlKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHNJbnRlcnZhbCA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaW50ZXJ2YWw7ICAvLyBJbnRlcnZhbCBpbiBzZWNvbmRzXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignbG9jYWxTdG9yYWdlIGl0ZW06ICcgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1dlYlJ0YyBzdGF0cyBub3QgZW5hYmxlZCcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wV2ViUnRjU3RhdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHNlbmRQb3N0ID0gKGpzb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGh0dHA6IFhNTEh0dHBSZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICBjb25zdCB1cmw6IHN0cmluZyA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaHR0cEVuZHBvaW50O1xuICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgdXJsLCB0cnVlKTtcblxuICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKCdDb250ZW50LXR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuXG4gICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHsgLy8gQ2FsbCBhIGZ1bmN0aW9uIHdoZW4gdGhlIHN0YXRlIGNoYW5nZXMuXG4gICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCAmJiBodHRwLnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdXZWJSdGMgc3RhdHMgc3VjY2Vzc2Z1bGx5IHNlbnQgdG8gJyArIHVybCArICcgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaHR0cC5zZW5kKGpzb24pO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGYgPSAoc3RhdHMpID0+IHtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBzdGF0cy5mb3JFYWNoKChzdGF0KSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGpzb24gPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoKHN0YXQudHlwZSA9PT0gJ2luYm91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IG91dGJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5uYWNrQ291bnQgIT09IG51bGwgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5yZW1vdGVJZC5zdGFydHNXaXRoKCdpbmJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgaml0ID0gc3RhdC5qaXR0ZXIgKiAxMDAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IChzdGF0LmJ5dGVzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogaml0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6ICdtcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snbmFja0NvdW50J10gPSAoc3RhdC5uYWNrQ291bnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ25hY2tDb3VudCddID0gJ3BhY2tldHMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQubmFja0NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCA9IHN0YXQucGFja2V0c1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKHN0YXQudHlwZSA9PT0gJ291dGJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBpbmJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ291dGJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX291dGJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IChzdGF0LnBhY2tldHNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQgPSBzdGF0LmZyYW1lc0VuY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQgPSBzdGF0LnBhY2tldHNTZW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhzdGF0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogc3RhdC5nb29nSml0dGVyQnVmZmVyTXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lmdvb2dOYWNrc1NlbnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lmdvb2dOYWNrc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCdieXRlc1NlbnQnIGluIHN0YXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdXRib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5nZXRTdGF0c0Fnbm9zdGljKHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCksIGYsIChlcnJvcikgPT4geyBjb25zb2xlLmxvZyhlcnJvcik7IH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2goKHJlcG9ydCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RhbmRhcmRTdGF0cyA9IHtcbiAgICAgICAgICAgICAgICBpZDogcmVwb3J0LmlkLFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogcmVwb3J0LnRpbWVzdGFtcCxcbiAgICAgICAgICAgICAgICB0eXBlOiByZXBvcnQudHlwZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcG9ydC5uYW1lcygpLmZvckVhY2goKG5hbWUpID0+IHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFN0YXRzW25hbWVdID0gcmVwb3J0LnN0YXQobmFtZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHN0YW5kYXJkUmVwb3J0W3N0YW5kYXJkU3RhdHMuaWRdID0gc3RhbmRhcmRTdGF0cztcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHN0YW5kYXJkUmVwb3J0O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0U3RhdHNBZ25vc3RpYyhwYywgc3VjY2Vzc0NiLCBmYWlsdXJlQ2IpIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIGdldFN0YXRzIHRha2VzIGFyZ3MgaW4gZGlmZmVyZW50IG9yZGVyIGluIENocm9tZSBhbmQgRmlyZWZveFxuICAgICAgICAgICAgcmV0dXJuIHBjLmdldFN0YXRzKG51bGwsIChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcG9ydCA9IHRoaXMuc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYihyZXBvcnQpO1xuICAgICAgICAgICAgfSwgZmFpbHVyZUNiKTtcbiAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIEluIENocm9tZSwgdGhlIGZpcnN0IHR3byBhcmd1bWVudHMgYXJlIHJldmVyc2VkXG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBudWxsLCBmYWlsdXJlQ2IpO1xuICAgICAgICB9XG4gICAgfVxuXG59Il19 diff --git a/openvidu-getaroom/web/openvidu-browser-2.2.0.js b/openvidu-getaroom/web/openvidu-browser-2.2.0.js new file mode 100644 index 00000000..e57248f3 --- /dev/null +++ b/openvidu-getaroom/web/openvidu-browser-2.2.0.js @@ -0,0 +1,7371 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Unhandled "error" event. (' + er + ')'); + err.context = er; + throw err; + } + return false; + } + + handler = events[type]; + + if (!handler) + return false; + + var isFn = typeof handler === 'function'; + len = arguments.length; + switch (len) { + // fast cases + case 1: + emitNone(handler, isFn, this); + break; + case 2: + emitOne(handler, isFn, this, arguments[1]); + break; + case 3: + emitTwo(handler, isFn, this, arguments[1], arguments[2]); + break; + case 4: + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + emitMany(handler, isFn, this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = target._events; + if (!events) { + events = target._events = objectCreate(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (!existing) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + } else { + // If we've already got an array, just append. + if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + } + + // Check for listener leak + if (!existing.warned) { + m = $getMaxListeners(target); + if (m && m > 0 && existing.length > m) { + existing.warned = true; + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' "' + String(type) + '" listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit.'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + if (typeof console === 'object' && console.warn) { + console.warn('%s: %s', w.name, w.message); + } + } + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + switch (arguments.length) { + case 0: + return this.listener.call(this.target); + case 1: + return this.listener.call(this.target, arguments[0]); + case 2: + return this.listener.call(this.target, arguments[0], arguments[1]); + case 3: + return this.listener.call(this.target, arguments[0], arguments[1], + arguments[2]); + default: + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) + args[i] = arguments[i]; + this.listener.apply(this.target, args); + } + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = bind.call(onceWrapper, state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = this._events; + if (!events) + return this; + + list = events[type]; + if (!list) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else + spliceOne(list, position); + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (!events) + return this; + + // not listening for removeListener, no need to emit + if (!events.removeListener) { + if (arguments.length === 0) { + this._events = objectCreate(null); + this._eventsCount = 0; + } else if (events[type]) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = objectKeys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = objectCreate(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (!events) + return []; + + var evlistener = events[type]; + if (!evlistener) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function objectCreatePolyfill(proto) { + var F = function() {}; + F.prototype = proto; + return new F; +} +function objectKeysPolyfill(obj) { + var keys = []; + for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { + keys.push(k); + } + return k; +} +function functionBindPolyfill(context) { + var fn = this; + return function () { + return fn.apply(context, arguments); + }; +} + +},{}],2:[function(require,module,exports){ +/* jshint node: true */ +'use strict'; + +var normalice = require('normalice'); + +/** + # freeice + + The `freeice` module is a simple way of getting random STUN or TURN server + for your WebRTC application. The list of servers (just STUN at this stage) + were sourced from this [gist](https://gist.github.com/zziuni/3741933). + + ## Example Use + + The following demonstrates how you can use `freeice` with + [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): + + <<< examples/quickconnect.js + + As the `freeice` module generates ice servers in a list compliant with the + WebRTC spec you will be able to use it with raw `RTCPeerConnection` + constructors and other WebRTC libraries. + + ## Hey, don't use my STUN/TURN server! + + If for some reason your free STUN or TURN server ends up in the + list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or + [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) + that is used in this module, you can feel + free to open an issue on this repository and those servers will be removed + within 24 hours (or sooner). This is the quickest and probably the most + polite way to have something removed (and provides us some visibility + if someone opens a pull request requesting that a server is added). + + ## Please add my server! + + If you have a server that you wish to add to the list, that's awesome! I'm + sure I speak on behalf of a whole pile of WebRTC developers who say thanks. + To get it into the list, feel free to either open a pull request or if you + find that process a bit daunting then just create an issue requesting + the addition of the server (make sure you provide all the details, and if + you have a Terms of Service then including that in the PR/issue would be + awesome). + + ## I know of a free server, can I add it? + + Sure, if you do your homework and make sure it is ok to use (I'm currently + in the process of reviewing the terms of those STUN servers included from + the original list). If it's ok to go, then please see the previous entry + for how to add it. + + ## Current List of Servers + + * current as at the time of last `README.md` file generation + + ### STUN + + <<< stun.json + + ### TURN + + <<< turn.json + +**/ + +var freeice = module.exports = function(opts) { + // if a list of servers has been provided, then use it instead of defaults + var servers = { + stun: (opts || {}).stun || require('./stun.json'), + turn: (opts || {}).turn || require('./turn.json') + }; + + var stunCount = (opts || {}).stunCount || 2; + var turnCount = (opts || {}).turnCount || 0; + var selected; + + function getServers(type, count) { + var out = []; + var input = [].concat(servers[type]); + var idx; + + while (input.length && out.length < count) { + idx = (Math.random() * input.length) | 0; + out = out.concat(input.splice(idx, 1)); + } + + return out.map(function(url) { + //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up + if ((typeof url !== 'string') && (! (url instanceof String))) { + return url; + } else { + return normalice(type + ':' + url); + } + }); + } + + // add stun servers + selected = [].concat(getServers('stun', stunCount)); + + if (turnCount) { + selected = selected.concat(getServers('turn', turnCount)); + } + + return selected; +}; + +},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){ +module.exports=[ + "stun.l.google.com:19302", + "stun1.l.google.com:19302", + "stun2.l.google.com:19302", + "stun3.l.google.com:19302", + "stun4.l.google.com:19302", + "stun.ekiga.net", + "stun.ideasip.com", + "stun.schlund.de", + "stun.stunprotocol.org:3478", + "stun.voiparound.com", + "stun.voipbuster.com", + "stun.voipstunt.com", + "stun.voxgratia.org", + "stun.services.mozilla.com" +] + +},{}],4:[function(require,module,exports){ +module.exports=[] + +},{}],5:[function(require,module,exports){ +var WildEmitter = require('wildemitter'); + +function getMaxVolume (analyser, fftBins) { + var maxVolume = -Infinity; + analyser.getFloatFrequencyData(fftBins); + + for(var i=4, ii=fftBins.length; i < ii; i++) { + if (fftBins[i] > maxVolume && fftBins[i] < 0) { + maxVolume = fftBins[i]; + } + }; + + return maxVolume; +} + + +var audioContextType; +if (typeof window !== 'undefined') { + audioContextType = window.AudioContext || window.webkitAudioContext; +} +// use a single audio context due to hardware limits +var audioContext = null; +module.exports = function(stream, options) { + var harker = new WildEmitter(); + + + // make it not break in non-supported browsers + if (!audioContextType) return harker; + + //Config + var options = options || {}, + smoothing = (options.smoothing || 0.1), + interval = (options.interval || 50), + threshold = options.threshold, + play = options.play, + history = options.history || 10, + running = true; + + //Setup Audio Context + if (!audioContext) { + audioContext = new audioContextType(); + } + var sourceNode, fftBins, analyser; + + analyser = audioContext.createAnalyser(); + analyser.fftSize = 512; + analyser.smoothingTimeConstant = smoothing; + fftBins = new Float32Array(analyser.frequencyBinCount); + + if (stream.jquery) stream = stream[0]; + if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { + //Audio Tag + sourceNode = audioContext.createMediaElementSource(stream); + if (typeof play === 'undefined') play = true; + threshold = threshold || -50; + } else { + //WebRTC Stream + sourceNode = audioContext.createMediaStreamSource(stream); + threshold = threshold || -50; + } + + sourceNode.connect(analyser); + if (play) analyser.connect(audioContext.destination); + + harker.speaking = false; + + harker.suspend = function() { + audioContext.suspend(); + } + harker.resume = function() { + audioContext.resume(); + } + Object.defineProperty(harker, 'state', { get: function() { + return audioContext.state; + }}); + audioContext.onstatechange = function() { + harker.emit('state_change', audioContext.state); + } + + harker.setThreshold = function(t) { + threshold = t; + }; + + harker.setInterval = function(i) { + interval = i; + }; + + harker.stop = function() { + running = false; + harker.emit('volume_change', -100, threshold); + if (harker.speaking) { + harker.speaking = false; + harker.emit('stopped_speaking'); + } + analyser.disconnect(); + sourceNode.disconnect(); + }; + harker.speakingHistory = []; + for (var i = 0; i < history; i++) { + harker.speakingHistory.push(0); + } + + // Poll the analyser node to determine if speaking + // and emit events if changed + var looper = function() { + setTimeout(function() { + + //check if stop has been called + if(!running) { + return; + } + + var currentVolume = getMaxVolume(analyser, fftBins); + + harker.emit('volume_change', currentVolume, threshold); + + var history = 0; + if (currentVolume > threshold && !harker.speaking) { + // trigger quickly, short history + for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { + history += harker.speakingHistory[i]; + } + if (history >= 2) { + harker.speaking = true; + harker.emit('speaking'); + } + } else if (currentVolume < threshold && harker.speaking) { + for (var i = 0; i < harker.speakingHistory.length; i++) { + history += harker.speakingHistory[i]; + } + if (history == 0) { + harker.speaking = false; + harker.emit('stopped_speaking'); + } + } + harker.speakingHistory.shift(); + harker.speakingHistory.push(0 + (currentVolume > threshold)); + + looper(); + }, interval); + }; + looper(); + + + return harker; +} + +},{"wildemitter":14}],6:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],7:[function(require,module,exports){ +/** + # normalice + + Normalize an ice server configuration object (or plain old string) into a format + that is usable in all browsers supporting WebRTC. Primarily this module is designed + to help with the transition of the `url` attribute of the configuration object to + the `urls` attribute. + + ## Example Usage + + <<< examples/simple.js + +**/ + +var protocols = [ + 'stun:', + 'turn:' +]; + +module.exports = function(input) { + var url = (input || {}).url || input; + var protocol; + var parts; + var output = {}; + + // if we don't have a string url, then allow the input to passthrough + if (typeof url != 'string' && (! (url instanceof String))) { + return input; + } + + // trim the url string, and convert to an array + url = url.trim(); + + // if the protocol is not known, then passthrough + protocol = protocols[protocols.indexOf(url.slice(0, 5))]; + if (! protocol) { + return input; + } + + // now let's attack the remaining url parts + url = url.slice(5); + parts = url.split('@'); + + output.username = input.username; + output.credential = input.credential; + // if we have an authentication part, then set the credentials + if (parts.length > 1) { + url = parts[1]; + parts = parts[0].split(':'); + + // add the output credential and username + output.username = parts[0]; + output.credential = (input || {}).credential || parts[1] || ''; + } + + output.url = protocol + url; + output.urls = [ output.url ]; + + return output; +}; + +},{}],8:[function(require,module,exports){ +(function (global){ +/*! + * Platform.js + * Copyright 2014-2018 Benjamin Tan + * Copyright 2011-2013 John-David Dalton + * Available under MIT license + */ +;(function() { + 'use strict'; + + /** Used to determine if values are of the language type `Object`. */ + var objectTypes = { + 'function': true, + 'object': true + }; + + /** Used as a reference to the global object. */ + var root = (objectTypes[typeof window] && window) || this; + + /** Backup possible global object. */ + var oldRoot = root; + + /** Detect free variable `exports`. */ + var freeExports = objectTypes[typeof exports] && exports; + + /** Detect free variable `module`. */ + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + + /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ + var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; + if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { + root = freeGlobal; + } + + /** + * Used as the maximum length of an array-like object. + * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) + * for more details. + */ + var maxSafeInteger = Math.pow(2, 53) - 1; + + /** Regular expression to detect Opera. */ + var reOpera = /\bOpera/; + + /** Possible global object. */ + var thisBinding = this; + + /** Used for native method references. */ + var objectProto = Object.prototype; + + /** Used to check for own properties of an object. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to resolve the internal `[[Class]]` of values. */ + var toString = objectProto.toString; + + /*--------------------------------------------------------------------------*/ + + /** + * Capitalizes a string value. + * + * @private + * @param {string} string The string to capitalize. + * @returns {string} The capitalized string. + */ + function capitalize(string) { + string = String(string); + return string.charAt(0).toUpperCase() + string.slice(1); + } + + /** + * A utility function to clean up the OS name. + * + * @private + * @param {string} os The OS name to clean up. + * @param {string} [pattern] A `RegExp` pattern matching the OS name. + * @param {string} [label] A label for the OS. + */ + function cleanupOS(os, pattern, label) { + // Platform tokens are defined at: + // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + var data = { + '10.0': '10', + '6.4': '10 Technical Preview', + '6.3': '8.1', + '6.2': '8', + '6.1': 'Server 2008 R2 / 7', + '6.0': 'Server 2008 / Vista', + '5.2': 'Server 2003 / XP 64-bit', + '5.1': 'XP', + '5.01': '2000 SP1', + '5.0': '2000', + '4.0': 'NT', + '4.90': 'ME' + }; + // Detect Windows version from platform tokens. + if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && + (data = data[/[\d.]+$/.exec(os)])) { + os = 'Windows ' + data; + } + // Correct character case and cleanup string. + os = String(os); + + if (pattern && label) { + os = os.replace(RegExp(pattern, 'i'), label); + } + + os = format( + os.replace(/ ce$/i, ' CE') + .replace(/\bhpw/i, 'web') + .replace(/\bMacintosh\b/, 'Mac OS') + .replace(/_PowerPC\b/i, ' OS') + .replace(/\b(OS X) [^ \d]+/i, '$1') + .replace(/\bMac (OS X)\b/, '$1') + .replace(/\/(\d)/, ' $1') + .replace(/_/g, '.') + .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') + .replace(/\bx86\.64\b/gi, 'x86_64') + .replace(/\b(Windows Phone) OS\b/, '$1') + .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') + .split(' on ')[0] + ); + + return os; + } + + /** + * An iteration utility for arrays and objects. + * + * @private + * @param {Array|Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + */ + function each(object, callback) { + var index = -1, + length = object ? object.length : 0; + + if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { + while (++index < length) { + callback(object[index], index, object); + } + } else { + forOwn(object, callback); + } + } + + /** + * Trim and conditionally capitalize string values. + * + * @private + * @param {string} string The string to format. + * @returns {string} The formatted string. + */ + function format(string) { + string = trim(string); + return /^(?:webOS|i(?:OS|P))/.test(string) + ? string + : capitalize(string); + } + + /** + * Iterates over an object's own properties, executing the `callback` for each. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function executed per own property. + */ + function forOwn(object, callback) { + for (var key in object) { + if (hasOwnProperty.call(object, key)) { + callback(object[key], key, object); + } + } + } + + /** + * Gets the internal `[[Class]]` of a value. + * + * @private + * @param {*} value The value. + * @returns {string} The `[[Class]]`. + */ + function getClassOf(value) { + return value == null + ? capitalize(value) + : toString.call(value).slice(8, -1); + } + + /** + * Host objects can return type values that are different from their actual + * data type. The objects we are concerned with usually return non-primitive + * types of "object", "function", or "unknown". + * + * @private + * @param {*} object The owner of the property. + * @param {string} property The property to check. + * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. + */ + function isHostType(object, property) { + var type = object != null ? typeof object[property] : 'number'; + return !/^(?:boolean|number|string|undefined)$/.test(type) && + (type == 'object' ? !!object[property] : true); + } + + /** + * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. + * + * @private + * @param {string} string The string to qualify. + * @returns {string} The qualified string. + */ + function qualify(string) { + return String(string).replace(/([ -])(?!$)/g, '$1?'); + } + + /** + * A bare-bones `Array#reduce` like utility function. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {*} The accumulated result. + */ + function reduce(array, callback) { + var accumulator = null; + each(array, function(value, index) { + accumulator = callback(accumulator, value, index, array); + }); + return accumulator; + } + + /** + * Removes leading and trailing whitespace from a string. + * + * @private + * @param {string} string The string to trim. + * @returns {string} The trimmed string. + */ + function trim(string) { + return String(string).replace(/^ +| +$/g, ''); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a new platform object. + * + * @memberOf platform + * @param {Object|string} [ua=navigator.userAgent] The user agent string or + * context object. + * @returns {Object} A platform object. + */ + function parse(ua) { + + /** The environment context object. */ + var context = root; + + /** Used to flag when a custom context is provided. */ + var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; + + // Juggle arguments. + if (isCustomContext) { + context = ua; + ua = null; + } + + /** Browser navigator object. */ + var nav = context.navigator || {}; + + /** Browser user agent string. */ + var userAgent = nav.userAgent || ''; + + ua || (ua = userAgent); + + /** Used to flag when `thisBinding` is the [ModuleScope]. */ + var isModuleScope = isCustomContext || thisBinding == oldRoot; + + /** Used to detect if browser is like Chrome. */ + var likeChrome = isCustomContext + ? !!nav.likeChrome + : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); + + /** Internal `[[Class]]` value shortcuts. */ + var objectClass = 'Object', + airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', + enviroClass = isCustomContext ? objectClass : 'Environment', + javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), + phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; + + /** Detect Java environments. */ + var java = /\bJava/.test(javaClass) && context.java; + + /** Detect Rhino. */ + var rhino = java && getClassOf(context.environment) == enviroClass; + + /** A character to represent alpha. */ + var alpha = java ? 'a' : '\u03b1'; + + /** A character to represent beta. */ + var beta = java ? 'b' : '\u03b2'; + + /** Browser document object. */ + var doc = context.document || {}; + + /** + * Detect Opera browser (Presto-based). + * http://www.howtocreate.co.uk/operaStuff/operaObject.html + * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini + */ + var opera = context.operamini || context.opera; + + /** Opera `[[Class]]`. */ + var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) + ? operaClass + : (opera = null); + + /*------------------------------------------------------------------------*/ + + /** Temporary variable used over the script's lifetime. */ + var data; + + /** The CPU architecture. */ + var arch = ua; + + /** Platform description array. */ + var description = []; + + /** Platform alpha/beta indicator. */ + var prerelease = null; + + /** A flag to indicate that environment features should be used to resolve the platform. */ + var useFeatures = ua == userAgent; + + /** The browser/environment version. */ + var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); + + /** A flag to indicate if the OS ends with "/ Version" */ + var isSpecialCasedOS; + + /* Detectable layout engines (order is important). */ + var layout = getLayout([ + { 'label': 'EdgeHTML', 'pattern': 'Edge' }, + 'Trident', + { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, + 'iCab', + 'Presto', + 'NetFront', + 'Tasman', + 'KHTML', + 'Gecko' + ]); + + /* Detectable browser names (order is important). */ + var name = getName([ + 'Adobe AIR', + 'Arora', + 'Avant Browser', + 'Breach', + 'Camino', + 'Electron', + 'Epiphany', + 'Fennec', + 'Flock', + 'Galeon', + 'GreenBrowser', + 'iCab', + 'Iceweasel', + 'K-Meleon', + 'Konqueror', + 'Lunascape', + 'Maxthon', + { 'label': 'Microsoft Edge', 'pattern': 'Edge' }, + 'Midori', + 'Nook Browser', + 'PaleMoon', + 'PhantomJS', + 'Raven', + 'Rekonq', + 'RockMelt', + { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' }, + 'SeaMonkey', + { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Sleipnir', + 'SlimBrowser', + { 'label': 'SRWare Iron', 'pattern': 'Iron' }, + 'Sunrise', + 'Swiftfox', + 'Waterfox', + 'WebPositive', + 'Opera Mini', + { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, + 'Opera', + { 'label': 'Opera', 'pattern': 'OPR' }, + 'Chrome', + { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, + { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, + { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' }, + { 'label': 'IE', 'pattern': 'IEMobile' }, + { 'label': 'IE', 'pattern': 'MSIE' }, + 'Safari' + ]); + + /* Detectable products (order is important). */ + var product = getProduct([ + { 'label': 'BlackBerry', 'pattern': 'BB10' }, + 'BlackBerry', + { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, + { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, + { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, + { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, + { 'label': 'Galaxy S5', 'pattern': 'SM-G900' }, + { 'label': 'Galaxy S6', 'pattern': 'SM-G920' }, + { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' }, + { 'label': 'Galaxy S7', 'pattern': 'SM-G930' }, + { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' }, + 'Google TV', + 'Lumia', + 'iPad', + 'iPod', + 'iPhone', + 'Kindle', + { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Nexus', + 'Nook', + 'PlayBook', + 'PlayStation Vita', + 'PlayStation', + 'TouchPad', + 'Transformer', + { 'label': 'Wii U', 'pattern': 'WiiU' }, + 'Wii', + 'Xbox One', + { 'label': 'Xbox 360', 'pattern': 'Xbox' }, + 'Xoom' + ]); + + /* Detectable manufacturers. */ + var manufacturer = getManufacturer({ + 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, + 'Archos': {}, + 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, + 'Asus': { 'Transformer': 1 }, + 'Barnes & Noble': { 'Nook': 1 }, + 'BlackBerry': { 'PlayBook': 1 }, + 'Google': { 'Google TV': 1, 'Nexus': 1 }, + 'HP': { 'TouchPad': 1 }, + 'HTC': {}, + 'LG': {}, + 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, + 'Motorola': { 'Xoom': 1 }, + 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, + 'Nokia': { 'Lumia': 1 }, + 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, + 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 } + }); + + /* Detectable operating systems (order is important). */ + var os = getOS([ + 'Windows Phone', + 'Android', + 'CentOS', + { 'label': 'Chrome OS', 'pattern': 'CrOS' }, + 'Debian', + 'Fedora', + 'FreeBSD', + 'Gentoo', + 'Haiku', + 'Kubuntu', + 'Linux Mint', + 'OpenBSD', + 'Red Hat', + 'SuSE', + 'Ubuntu', + 'Xubuntu', + 'Cygwin', + 'Symbian OS', + 'hpwOS', + 'webOS ', + 'webOS', + 'Tablet OS', + 'Tizen', + 'Linux', + 'Mac OS X', + 'Macintosh', + 'Mac', + 'Windows 98;', + 'Windows ' + ]); + + /*------------------------------------------------------------------------*/ + + /** + * Picks the layout engine from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected layout engine. + */ + function getLayout(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the manufacturer from an array of guesses. + * + * @private + * @param {Array} guesses An object of guesses. + * @returns {null|string} The detected manufacturer. + */ + function getManufacturer(guesses) { + return reduce(guesses, function(result, value, key) { + // Lookup the manufacturer by product or scan the UA for the manufacturer. + return result || ( + value[product] || + value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || + RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) + ) && key; + }); + } + + /** + * Picks the browser name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected browser name. + */ + function getName(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the OS name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected OS name. + */ + function getOS(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) + )) { + result = cleanupOS(result, pattern, guess.label || guess); + } + return result; + }); + } + + /** + * Picks the product name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected product name. + */ + function getProduct(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || + RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) || + RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) + )) { + // Split by forward slash and append product version if needed. + if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { + result[0] += ' ' + result[1]; + } + // Correct character case and cleanup string. + guess = guess.label || guess; + result = format(result[0] + .replace(RegExp(pattern, 'i'), guess) + .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') + .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); + } + return result; + }); + } + + /** + * Resolves the version using an array of UA patterns. + * + * @private + * @param {Array} patterns An array of UA patterns. + * @returns {null|string} The detected version. + */ + function getVersion(patterns) { + return reduce(patterns, function(result, pattern) { + return result || (RegExp(pattern + + '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; + }); + } + + /** + * Returns `platform.description` when the platform object is coerced to a string. + * + * @name toString + * @memberOf platform + * @returns {string} Returns `platform.description` if available, else an empty string. + */ + function toStringPlatform() { + return this.description || ''; + } + + /*------------------------------------------------------------------------*/ + + // Convert layout to an array so we can add extra details. + layout && (layout = [layout]); + + // Detect product names that contain their manufacturer's name. + if (manufacturer && !product) { + product = getProduct([manufacturer]); + } + // Clean up Google TV. + if ((data = /\bGoogle TV\b/.exec(product))) { + product = data[0]; + } + // Detect simulators. + if (/\bSimulator\b/i.test(ua)) { + product = (product ? product + ' ' : '') + 'Simulator'; + } + // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. + if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { + description.push('running in Turbo/Uncompressed mode'); + } + // Detect IE Mobile 11. + if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) { + data = parse(ua.replace(/like iPhone OS/, '')); + manufacturer = data.manufacturer; + product = data.product; + } + // Detect iOS. + else if (/^iP/.test(product)) { + name || (name = 'Safari'); + os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) + ? ' ' + data[1].replace(/_/g, '.') + : ''); + } + // Detect Kubuntu. + else if (name == 'Konqueror' && !/buntu/i.test(os)) { + os = 'Kubuntu'; + } + // Detect Android browsers. + else if ((manufacturer && manufacturer != 'Google' && + ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) || + (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) { + name = 'Android Browser'; + os = /\bAndroid\b/.test(os) ? os : 'Android'; + } + // Detect Silk desktop/accelerated modes. + else if (name == 'Silk') { + if (!/\bMobi/i.test(ua)) { + os = 'Android'; + description.unshift('desktop mode'); + } + if (/Accelerated *= *true/i.test(ua)) { + description.unshift('accelerated'); + } + } + // Detect PaleMoon identifying as Firefox. + else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { + description.push('identifying as Firefox ' + data[1]); + } + // Detect Firefox OS and products running Firefox. + else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { + os || (os = 'Firefox OS'); + product || (product = data[1]); + } + // Detect false positives for Firefox/Safari. + else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { + // Escape the `/` for Firefox 1. + if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { + // Clear name of false positives. + name = null; + } + // Reassign a generic name. + if ((data = product || manufacturer || os) && + (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { + name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; + } + } + // Add Chrome version to description for Electron. + else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) { + description.push('Chromium ' + data); + } + // Detect non-Opera (Presto-based) versions (order is important). + if (!version) { + version = getVersion([ + '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))', + 'Version', + qualify(name), + '(?:Firefox|Minefield|NetFront)' + ]); + } + // Detect stubborn layout engines. + if ((data = + layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || + /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || + /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || + !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || + layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' + )) { + layout = [data]; + } + // Detect Windows Phone 7 desktop mode. + if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { + name += ' Mobile'; + os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); + description.unshift('desktop mode'); + } + // Detect Windows Phone 8.x desktop mode. + else if (/\bWPDesktop\b/i.test(ua)) { + name = 'IE Mobile'; + os = 'Windows Phone 8.x'; + description.unshift('desktop mode'); + version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); + } + // Detect IE 11 identifying as other browsers. + else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { + if (name) { + description.push('identifying as ' + name + (version ? ' ' + version : '')); + } + name = 'IE'; + version = data[1]; + } + // Leverage environment features. + if (useFeatures) { + // Detect server-side environments. + // Rhino has a global function while others have a global object. + if (isHostType(context, 'global')) { + if (java) { + data = java.lang.System; + arch = data.getProperty('os.arch'); + os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); + } + if (rhino) { + try { + version = context.require('ringo/engine').version.join('.'); + name = 'RingoJS'; + } catch(e) { + if ((data = context.system) && data.global.system == context.system) { + name = 'Narwhal'; + os || (os = data[0].os || null); + } + } + if (!name) { + name = 'Rhino'; + } + } + else if ( + typeof context.process == 'object' && !context.process.browser && + (data = context.process) + ) { + if (typeof data.versions == 'object') { + if (typeof data.versions.electron == 'string') { + description.push('Node ' + data.versions.node); + name = 'Electron'; + version = data.versions.electron; + } else if (typeof data.versions.nw == 'string') { + description.push('Chromium ' + version, 'Node ' + data.versions.node); + name = 'NW.js'; + version = data.versions.nw; + } + } + if (!name) { + name = 'Node.js'; + arch = data.arch; + os = data.platform; + version = /[\d.]+/.exec(data.version); + version = version ? version[0] : null; + } + } + } + // Detect Adobe AIR. + else if (getClassOf((data = context.runtime)) == airRuntimeClass) { + name = 'Adobe AIR'; + os = data.flash.system.Capabilities.os; + } + // Detect PhantomJS. + else if (getClassOf((data = context.phantom)) == phantomClass) { + name = 'PhantomJS'; + version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); + } + // Detect IE compatibility modes. + else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { + // We're in compatibility mode when the Trident version + 4 doesn't + // equal the document mode. + version = [version, doc.documentMode]; + if ((data = +data[1] + 4) != version[1]) { + description.push('IE ' + version[1] + ' mode'); + layout && (layout[1] = ''); + version[1] = data; + } + version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; + } + // Detect IE 11 masking as other browsers. + else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) { + description.push('masking as ' + name + ' ' + version); + name = 'IE'; + version = '11.0'; + layout = ['Trident']; + os = 'Windows'; + } + os = os && format(os); + } + // Detect prerelease phases. + if (version && (data = + /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || + /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || + /\bMinefield\b/i.test(ua) && 'a' + )) { + prerelease = /b/i.test(data) ? 'beta' : 'alpha'; + version = version.replace(RegExp(data + '\\+?$'), '') + + (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); + } + // Detect Firefox Mobile. + if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) { + name = 'Firefox Mobile'; + } + // Obscure Maxthon's unreliable version. + else if (name == 'Maxthon' && version) { + version = version.replace(/\.[\d.]+/, '.x'); + } + // Detect Xbox 360 and Xbox One. + else if (/\bXbox\b/i.test(product)) { + if (product == 'Xbox 360') { + os = null; + } + if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { + description.unshift('mobile mode'); + } + } + // Add mobile postfix. + else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && + (os == 'Windows CE' || /Mobi/i.test(ua))) { + name += ' Mobile'; + } + // Detect IE platform preview. + else if (name == 'IE' && useFeatures) { + try { + if (context.external === null) { + description.unshift('platform preview'); + } + } catch(e) { + description.unshift('embedded'); + } + } + // Detect BlackBerry OS version. + // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp + else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = + (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || + version + )) { + data = [data, /BB10/.test(ua)]; + os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; + version = null; + } + // Detect Opera identifying/masking itself as another browser. + // http://www.opera.com/support/kb/view/843/ + else if (this != forOwn && product != 'Wii' && ( + (useFeatures && opera) || + (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || + (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || + (name == 'IE' && ( + (os && !/^Win/.test(os) && version > 5.5) || + /\bWindows XP\b/.test(os) && version > 8 || + version == 8 && !/\bTrident\b/.test(ua) + )) + ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { + // When "identifying", the UA contains both Opera and the other browser's name. + data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); + if (reOpera.test(name)) { + if (/\bIE\b/.test(data) && os == 'Mac OS') { + os = null; + } + data = 'identify' + data; + } + // When "masking", the UA contains only the other browser's name. + else { + data = 'mask' + data; + if (operaClass) { + name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); + } else { + name = 'Opera'; + } + if (/\bIE\b/.test(data)) { + os = null; + } + if (!useFeatures) { + version = null; + } + } + layout = ['Presto']; + description.push(data); + } + // Detect WebKit Nightly and approximate Chrome/Safari versions. + if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { + // Correct build number for numeric comparison. + // (e.g. "532.5" becomes "532.05") + data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; + // Nightly builds are postfixed with a "+". + if (name == 'Safari' && data[1].slice(-1) == '+') { + name = 'WebKit Nightly'; + prerelease = 'alpha'; + version = data[1].slice(0, -1); + } + // Clear incorrect browser versions. + else if (version == data[1] || + version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { + version = null; + } + // Use the full Chrome version when available. + data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]; + // Detect Blink layout engine. + if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { + layout = ['Blink']; + } + // Detect JavaScriptCore. + // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi + if (!useFeatures || (!likeChrome && !data[1])) { + layout && (layout[1] = 'like Safari'); + data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8'); + } else { + layout && (layout[1] = 'like Chrome'); + data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); + } + // Add the postfix of ".x" or "+" for approximate versions. + layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); + // Obscure version for some Safari 1-2 releases. + if (name == 'Safari' && (!version || parseInt(version) > 45)) { + version = data; + } + } + // Detect Opera desktop modes. + if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { + name += ' '; + description.unshift('desktop mode'); + if (data == 'zvav') { + name += 'Mini'; + version = null; + } else { + name += 'Mobile'; + } + os = os.replace(RegExp(' *' + data + '$'), ''); + } + // Detect Chrome desktop mode. + else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { + description.unshift('desktop mode'); + name = 'Chrome Mobile'; + version = null; + + if (/\bOS X\b/.test(os)) { + manufacturer = 'Apple'; + os = 'iOS 4.3+'; + } else { + os = null; + } + } + // Strip incorrect OS versions. + if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && + ua.indexOf('/' + data + '-') > -1) { + os = trim(os.replace(data, '')); + } + // Add layout engine. + if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( + /Browser|Lunascape|Maxthon/.test(name) || + name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || + /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) { + // Don't add layout details to description if they are falsey. + (data = layout[layout.length - 1]) && description.push(data); + } + // Combine contextual information. + if (description.length) { + description = ['(' + description.join('; ') + ')']; + } + // Append manufacturer to description. + if (manufacturer && product && product.indexOf(manufacturer) < 0) { + description.push('on ' + manufacturer); + } + // Append product to description. + if (product) { + description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); + } + // Parse the OS into an object. + if (os) { + data = / ([\d.+]+)$/.exec(os); + isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; + os = { + 'architecture': 32, + 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, + 'version': data ? data[1] : null, + 'toString': function() { + var version = this.version; + return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); + } + }; + } + // Add browser/OS architecture. + if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { + if (os) { + os.architecture = 64; + os.family = os.family.replace(RegExp(' *' + data), ''); + } + if ( + name && (/\bWOW64\b/i.test(ua) || + (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) + ) { + description.unshift('32-bit'); + } + } + // Chrome 39 and above on OS X is always 64-bit. + else if ( + os && /^OS X/.test(os.family) && + name == 'Chrome' && parseFloat(version) >= 39 + ) { + os.architecture = 64; + } + + ua || (ua = null); + + /*------------------------------------------------------------------------*/ + + /** + * The platform object. + * + * @name platform + * @type Object + */ + var platform = {}; + + /** + * The platform description. + * + * @memberOf platform + * @type string|null + */ + platform.description = ua; + + /** + * The name of the browser's layout engine. + * + * The list of common layout engines include: + * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit" + * + * @memberOf platform + * @type string|null + */ + platform.layout = layout && layout[0]; + + /** + * The name of the product's manufacturer. + * + * The list of manufacturers include: + * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry", + * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo", + * "Nokia", "Samsung" and "Sony" + * + * @memberOf platform + * @type string|null + */ + platform.manufacturer = manufacturer; + + /** + * The name of the browser/environment. + * + * The list of common browser names include: + * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE", + * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk", + * "Opera Mini" and "Opera" + * + * Mobile versions of some browsers have "Mobile" appended to their name: + * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile" + * + * @memberOf platform + * @type string|null + */ + platform.name = name; + + /** + * The alpha/beta release indicator. + * + * @memberOf platform + * @type string|null + */ + platform.prerelease = prerelease; + + /** + * The name of the product hosting the browser. + * + * The list of common products include: + * + * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle", + * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer" + * + * @memberOf platform + * @type string|null + */ + platform.product = product; + + /** + * The browser's user agent string. + * + * @memberOf platform + * @type string|null + */ + platform.ua = ua; + + /** + * The browser/environment version. + * + * @memberOf platform + * @type string|null + */ + platform.version = name && version; + + /** + * The name of the operating system. + * + * @memberOf platform + * @type Object + */ + platform.os = os || { + + /** + * The CPU architecture the OS is built for. + * + * @memberOf platform.os + * @type number|null + */ + 'architecture': null, + + /** + * The family of the OS. + * + * Common values include: + * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", + * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", + * "Android", "iOS" and "Windows Phone" + * + * @memberOf platform.os + * @type string|null + */ + 'family': null, + + /** + * The version of the OS. + * + * @memberOf platform.os + * @type string|null + */ + 'version': null, + + /** + * Returns the OS string. + * + * @memberOf platform.os + * @returns {string} The OS string. + */ + 'toString': function() { return 'null'; } + }; + + platform.parse = parse; + platform.toString = toStringPlatform; + + if (platform.version) { + description.unshift(version); + } + if (platform.name) { + description.unshift(name); + } + if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { + description.push(product ? '(' + os + ')' : 'on ' + os); + } + if (description.length) { + platform.description = description.join(' '); + } + return platform; + } + + /*--------------------------------------------------------------------------*/ + + // Export platform. + var platform = parse(); + + // Some AMD build optimizers, like r.js, check for condition patterns like the following: + if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // Expose platform on the global object to prevent errors when platform is + // loaded by a script tag in the presence of an AMD loader. + // See http://requirejs.org/docs/errors.html#mismatch for more details. + root.platform = platform; + + // Define as an anonymous module so platform can be aliased through path mapping. + define(function() { + return platform; + }); + } + // Check for `exports` after `define` in case a build optimizer adds an `exports` object. + else if (freeExports && freeModule) { + // Export for CommonJS support. + forOwn(platform, function(value, key) { + freeExports[key] = value; + }); + } + else { + // Export to the global object. + root.platform = platform; + } +}.call(this)); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],9:[function(require,module,exports){ +var v1 = require('./v1'); +var v4 = require('./v4'); + +var uuid = v4; +uuid.v1 = v1; +uuid.v4 = v4; + +module.exports = uuid; + +},{"./v1":12,"./v4":13}],10:[function(require,module,exports){ +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +var byteToHex = []; +for (var i = 0; i < 256; ++i) { + byteToHex[i] = (i + 0x100).toString(16).substr(1); +} + +function bytesToUuid(buf, offset) { + var i = offset || 0; + var bth = byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; +} + +module.exports = bytesToUuid; + +},{}],11:[function(require,module,exports){ +// Unique ID creation requires a high quality random # generator. In the +// browser this is a little complicated due to unknown quality of Math.random() +// and inconsistent support for the `crypto` API. We do the best we can via +// feature-detection + +// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. +var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) || + (typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto)); +if (getRandomValues) { + // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto + var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef + + module.exports = function whatwgRNG() { + getRandomValues(rnds8); + return rnds8; + }; +} else { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var rnds = new Array(16); + + module.exports = function mathRNG() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return rnds; + }; +} + +},{}],12:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html + +var _nodeId; +var _clockseq; + +// Previous uuid creation time +var _lastMSecs = 0; +var _lastNSecs = 0; + +// See https://github.com/broofa/node-uuid for API details +function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + var node = options.node || _nodeId; + var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; + + // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + if (node == null || clockseq == null) { + var seedBytes = rng(); + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [ + seedBytes[0] | 0x01, + seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] + ]; + } + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + for (var n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf ? buf : bytesToUuid(b); +} + +module.exports = v1; + +},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +function v4(options, buf, offset) { + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options === 'binary' ? new Array(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ++ii) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || bytesToUuid(rnds); +} + +module.exports = v4; + +},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){ +/* +WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based +on @visionmedia's Emitter from UI Kit. + +Why? I wanted it standalone. + +I also wanted support for wildcard emitters like this: + +emitter.on('*', function (eventName, other, event, payloads) { + +}); + +emitter.on('somenamespace*', function (eventName, payloads) { + +}); + +Please note that callbacks triggered by wildcard registered events also get +the event name as the first argument. +*/ + +module.exports = WildEmitter; + +function WildEmitter() { } + +WildEmitter.mixin = function (constructor) { + var prototype = constructor.prototype || constructor; + + prototype.isWildEmitter= true; + + // Listen on the given `event` with `fn`. Store a group name if present. + prototype.on = function (event, groupName, fn) { + this.callbacks = this.callbacks || {}; + var hasGroup = (arguments.length === 3), + group = hasGroup ? arguments[1] : undefined, + func = hasGroup ? arguments[2] : arguments[1]; + func._groupName = group; + (this.callbacks[event] = this.callbacks[event] || []).push(func); + return this; + }; + + // Adds an `event` listener that will be invoked a single + // time then automatically removed. + prototype.once = function (event, groupName, fn) { + var self = this, + hasGroup = (arguments.length === 3), + group = hasGroup ? arguments[1] : undefined, + func = hasGroup ? arguments[2] : arguments[1]; + function on() { + self.off(event, on); + func.apply(this, arguments); + } + this.on(event, group, on); + return this; + }; + + // Unbinds an entire group + prototype.releaseGroup = function (groupName) { + this.callbacks = this.callbacks || {}; + var item, i, len, handlers; + for (item in this.callbacks) { + handlers = this.callbacks[item]; + for (i = 0, len = handlers.length; i < len; i++) { + if (handlers[i]._groupName === groupName) { + //console.log('removing'); + // remove it and shorten the array we're looping through + handlers.splice(i, 1); + i--; + len--; + } + } + } + return this; + }; + + // Remove the given callback for `event` or all + // registered callbacks. + prototype.off = function (event, fn) { + this.callbacks = this.callbacks || {}; + var callbacks = this.callbacks[event], + i; + + if (!callbacks) return this; + + // remove all handlers + if (arguments.length === 1) { + delete this.callbacks[event]; + return this; + } + + // remove specific handler + i = callbacks.indexOf(fn); + callbacks.splice(i, 1); + if (callbacks.length === 0) { + delete this.callbacks[event]; + } + return this; + }; + + /// Emit `event` with the given args. + // also calls any `*` handlers + prototype.emit = function (event) { + this.callbacks = this.callbacks || {}; + var args = [].slice.call(arguments, 1), + callbacks = this.callbacks[event], + specialCallbacks = this.getWildcardCallbacks(event), + i, + len, + item, + listeners; + + if (callbacks) { + listeners = callbacks.slice(); + for (i = 0, len = listeners.length; i < len; ++i) { + if (!listeners[i]) { + break; + } + listeners[i].apply(this, args); + } + } + + if (specialCallbacks) { + len = specialCallbacks.length; + listeners = specialCallbacks.slice(); + for (i = 0, len = listeners.length; i < len; ++i) { + if (!listeners[i]) { + break; + } + listeners[i].apply(this, [event].concat(args)); + } + } + + return this; + }; + + // Helper for for finding special wildcard event handlers that match the event + prototype.getWildcardCallbacks = function (eventName) { + this.callbacks = this.callbacks || {}; + var item, + split, + result = []; + + for (item in this.callbacks) { + split = item.split('*'); + if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { + result = result.concat(this.callbacks[item]); + } + } + return result; + }; + +}; + +WildEmitter.mixin(WildEmitter); + +},{}],15:[function(require,module,exports){ +/*! + * EventEmitter v5.2.4 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - http://oli.me.uk/ + * @preserve + */ + +;(function (exports) { + 'use strict'; + + /** + * Class for managing events. + * Can be extended to provide event functionality in other classes. + * + * @class EventEmitter Manages event registering and emitting. + */ + function EventEmitter() {} + + // Shortcuts to improve speed and size + var proto = EventEmitter.prototype; + var originalGlobalValue = exports.EventEmitter; + + /** + * Finds the index of the listener for the event in its storage array. + * + * @param {Function[]} listeners Array of listeners to search through. + * @param {Function} listener Method to look for. + * @return {Number} Index of the specified listener, -1 if not found + * @api private + */ + function indexOfListener(listeners, listener) { + var i = listeners.length; + while (i--) { + if (listeners[i].listener === listener) { + return i; + } + } + + return -1; + } + + /** + * Alias a method while keeping the context correct, to allow for overwriting of target method. + * + * @param {String} name The name of the target method. + * @return {Function} The aliased method + * @api private + */ + function alias(name) { + return function aliasClosure() { + return this[name].apply(this, arguments); + }; + } + + /** + * Returns the listener array for the specified event. + * Will initialise the event object and listener arrays if required. + * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. + * Each property in the object response is an array of listener functions. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Function[]|Object} All listener functions for the event. + */ + proto.getListeners = function getListeners(evt) { + var events = this._getEvents(); + var response; + var key; + + // Return a concatenated array of all matching events if + // the selector is a regular expression. + if (evt instanceof RegExp) { + response = {}; + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + response[key] = events[key]; + } + } + } + else { + response = events[evt] || (events[evt] = []); + } + + return response; + }; + + /** + * Takes a list of listener objects and flattens it into a list of listener functions. + * + * @param {Object[]} listeners Raw listener objects. + * @return {Function[]} Just the listener functions. + */ + proto.flattenListeners = function flattenListeners(listeners) { + var flatListeners = []; + var i; + + for (i = 0; i < listeners.length; i += 1) { + flatListeners.push(listeners[i].listener); + } + + return flatListeners; + }; + + /** + * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Object} All listener functions for an event in an object. + */ + proto.getListenersAsObject = function getListenersAsObject(evt) { + var listeners = this.getListeners(evt); + var response; + + if (listeners instanceof Array) { + response = {}; + response[evt] = listeners; + } + + return response || listeners; + }; + + function isValidListener (listener) { + if (typeof listener === 'function' || listener instanceof RegExp) { + return true + } else if (listener && typeof listener === 'object') { + return isValidListener(listener.listener) + } else { + return false + } + } + + /** + * Adds a listener function to the specified event. + * The listener will not be added if it is a duplicate. + * If the listener returns true then it will be removed after it is called. + * If you pass a regular expression as the event name then the listener will be added to all events that match it. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListener = function addListener(evt, listener) { + if (!isValidListener(listener)) { + throw new TypeError('listener must be a function'); + } + + var listeners = this.getListenersAsObject(evt); + var listenerIsWrapped = typeof listener === 'object'; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { + listeners[key].push(listenerIsWrapped ? listener : { + listener: listener, + once: false + }); + } + } + + return this; + }; + + /** + * Alias of addListener + */ + proto.on = alias('addListener'); + + /** + * Semi-alias of addListener. It will add a listener that will be + * automatically removed after its first execution. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addOnceListener = function addOnceListener(evt, listener) { + return this.addListener(evt, { + listener: listener, + once: true + }); + }; + + /** + * Alias of addOnceListener. + */ + proto.once = alias('addOnceListener'); + + /** + * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. + * You need to tell it what event names should be matched by a regex. + * + * @param {String} evt Name of the event to create. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvent = function defineEvent(evt) { + this.getListeners(evt); + return this; + }; + + /** + * Uses defineEvent to define multiple events. + * + * @param {String[]} evts An array of event names to define. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvents = function defineEvents(evts) { + for (var i = 0; i < evts.length; i += 1) { + this.defineEvent(evts[i]); + } + return this; + }; + + /** + * Removes a listener function from the specified event. + * When passed a regular expression as the event name, it will remove the listener from all events that match it. + * + * @param {String|RegExp} evt Name of the event to remove the listener from. + * @param {Function} listener Method to remove from the event. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListener = function removeListener(evt, listener) { + var listeners = this.getListenersAsObject(evt); + var index; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key)) { + index = indexOfListener(listeners[key], listener); + + if (index !== -1) { + listeners[key].splice(index, 1); + } + } + } + + return this; + }; + + /** + * Alias of removeListener + */ + proto.off = alias('removeListener'); + + /** + * Adds listeners in bulk using the manipulateListeners method. + * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. + * You can also pass it a regular expression to add the array of listeners to all events that match it. + * Yeah, this function does quite a bit. That's probably a bad thing. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListeners = function addListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(false, evt, listeners); + }; + + /** + * Removes listeners in bulk using the manipulateListeners method. + * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be removed. + * You can also pass it a regular expression to remove the listeners from all events that match it. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListeners = function removeListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(true, evt, listeners); + }; + + /** + * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. + * The first argument will determine if the listeners are removed (true) or added (false). + * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be added/removed. + * You can also pass it a regular expression to manipulate the listeners of all events that match it. + * + * @param {Boolean} remove True if you want to remove listeners, false if you want to add. + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add/remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { + var i; + var value; + var single = remove ? this.removeListener : this.addListener; + var multiple = remove ? this.removeListeners : this.addListeners; + + // If evt is an object then pass each of its properties to this method + if (typeof evt === 'object' && !(evt instanceof RegExp)) { + for (i in evt) { + if (evt.hasOwnProperty(i) && (value = evt[i])) { + // Pass the single listener straight through to the singular method + if (typeof value === 'function') { + single.call(this, i, value); + } + else { + // Otherwise pass back to the multiple function + multiple.call(this, i, value); + } + } + } + } + else { + // So evt must be a string + // And listeners must be an array of listeners + // Loop over it and pass each one to the multiple method + i = listeners.length; + while (i--) { + single.call(this, evt, listeners[i]); + } + } + + return this; + }; + + /** + * Removes all listeners from a specified event. + * If you do not specify an event then all listeners will be removed. + * That means every event will be emptied. + * You can also pass a regex to remove all events that match it. + * + * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeEvent = function removeEvent(evt) { + var type = typeof evt; + var events = this._getEvents(); + var key; + + // Remove different things depending on the state of evt + if (type === 'string') { + // Remove all listeners for the specified event + delete events[evt]; + } + else if (evt instanceof RegExp) { + // Remove all events matching the regex. + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + delete events[key]; + } + } + } + else { + // Remove all listeners in all events + delete this._events; + } + + return this; + }; + + /** + * Alias of removeEvent. + * + * Added to mirror the node API. + */ + proto.removeAllListeners = alias('removeEvent'); + + /** + * Emits an event of your choice. + * When emitted, every listener attached to that event will be executed. + * If you pass the optional argument array then those arguments will be passed to every listener upon execution. + * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. + * So they will not arrive within the array on the other side, they will be separate. + * You can also pass a regular expression to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {Array} [args] Optional array of arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emitEvent = function emitEvent(evt, args) { + var listenersMap = this.getListenersAsObject(evt); + var listeners; + var listener; + var i; + var key; + var response; + + for (key in listenersMap) { + if (listenersMap.hasOwnProperty(key)) { + listeners = listenersMap[key].slice(0); + + for (i = 0; i < listeners.length; i++) { + // If the listener returns true then it shall be removed from the event + // The function is executed either with a basic call or an apply if there is an args array + listener = listeners[i]; + + if (listener.once === true) { + this.removeListener(evt, listener.listener); + } + + response = listener.listener.apply(this, args || []); + + if (response === this._getOnceReturnValue()) { + this.removeListener(evt, listener.listener); + } + } + } + } + + return this; + }; + + /** + * Alias of emitEvent + */ + proto.trigger = alias('emitEvent'); + + /** + * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. + * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {...*} Optional additional arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emit = function emit(evt) { + var args = Array.prototype.slice.call(arguments, 1); + return this.emitEvent(evt, args); + }; + + /** + * Sets the current value to check against when executing listeners. If a + * listeners return value matches the one set here then it will be removed + * after execution. This value defaults to true. + * + * @param {*} value The new value to check for when executing listeners. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.setOnceReturnValue = function setOnceReturnValue(value) { + this._onceReturnValue = value; + return this; + }; + + /** + * Fetches the current value to check against when executing listeners. If + * the listeners return value matches this one then it should be removed + * automatically. It will return true by default. + * + * @return {*|Boolean} The current value to check for or the default, true. + * @api private + */ + proto._getOnceReturnValue = function _getOnceReturnValue() { + if (this.hasOwnProperty('_onceReturnValue')) { + return this._onceReturnValue; + } + else { + return true; + } + }; + + /** + * Fetches the events object and creates one if required. + * + * @return {Object} The events storage object. + * @api private + */ + proto._getEvents = function _getEvents() { + return this._events || (this._events = {}); + }; + + /** + * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. + * + * @return {Function} Non conflicting EventEmitter class. + */ + EventEmitter.noConflict = function noConflict() { + exports.EventEmitter = originalGlobalValue; + return EventEmitter; + }; + + // Expose the class either via AMD, CommonJS or the global object + if (typeof define === 'function' && define.amd) { + define(function () { + return EventEmitter; + }); + } + else if (typeof module === 'object' && module.exports){ + module.exports = EventEmitter; + } + else { + exports.EventEmitter = EventEmitter; + } +}(this || {})); + +},{}],16:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenVidu_1 = require("./OpenVidu/OpenVidu"); +if (window) { + window['OpenVidu'] = OpenVidu_1.OpenVidu; +} + +},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Stream_1 = require("./Stream"); +var Connection = (function () { + function Connection(session, opts) { + this.session = session; + this.disposed = false; + var msg = "'Connection' created "; + if (!!opts) { + msg += "(remote) with 'connectionId' [" + opts.id + ']'; + } + else { + msg += '(local)'; + } + console.info(msg); + this.options = opts; + if (!!opts) { + this.connectionId = opts.id; + if (opts.metadata) { + this.data = opts.metadata; + } + if (opts.streams) { + this.initRemoteStreams(opts.streams); + } + } + this.creationTime = new Date().getTime(); + } + Connection.prototype.sendIceCandidate = function (candidate) { + console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate)); + this.session.openvidu.sendRequest('onIceCandidate', { + endpointName: this.connectionId, + candidate: candidate.candidate, + sdpMid: candidate.sdpMid, + sdpMLineIndex: candidate.sdpMLineIndex + }, function (error, response) { + if (error) { + console.error('Error sending ICE candidate: ' + + JSON.stringify(error)); + } + }); + }; + Connection.prototype.initRemoteStreams = function (options) { + var _this = this; + options.forEach(function (opts) { + var streamOptions = { + id: opts.id, + connection: _this, + frameRate: opts.frameRate, + recvAudio: opts.audioActive, + recvVideo: opts.videoActive, + typeOfVideo: opts.typeOfVideo + }; + var stream = new Stream_1.Stream(_this.session, streamOptions); + _this.addStream(stream); + }); + console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); + }; + Connection.prototype.addStream = function (stream) { + stream.connection = this; + this.stream = stream; + }; + Connection.prototype.removeStream = function (streamId) { + delete this.stream; + }; + Connection.prototype.dispose = function () { + if (!!this.stream) { + delete this.stream; + } + this.disposed = true; + }; + return Connection; +}()); +exports.Connection = Connection; + +},{"./Stream":22}],18:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState"); +var LocalRecorder = (function () { + function LocalRecorder(stream) { + this.stream = stream; + this.chunks = []; + this.count = 0; + this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; + this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; + this.state = LocalRecorderState_1.LocalRecorderState.READY; + } + LocalRecorder.prototype.record = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (typeof MediaRecorder === 'undefined') { + console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); + throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); + } + if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) { + throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); + } + console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'"); + if (typeof MediaRecorder.isTypeSupported === 'function') { + var options = void 0; + if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { + options = { mimeType: 'video/webm;codecs=vp9' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { + options = { mimeType: 'video/webm;codecs=h264' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { + options = { mimeType: 'video/webm;codecs=vp8' }; + } + console.log('Using mimeType ' + options.mimeType); + _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options); + } + else { + console.warn('isTypeSupported is not supported, using default codecs for browser'); + _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream()); + } + _this.mediaRecorder.start(10); + } + catch (err) { + reject(err); + } + _this.mediaRecorder.ondataavailable = function (e) { + _this.chunks.push(e.data); + }; + _this.mediaRecorder.onerror = function (e) { + console.error('MediaRecorder error: ', e); + }; + _this.mediaRecorder.onstart = function () { + console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + }; + _this.mediaRecorder.onpause = function () { + console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onresume = function () { + console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onwarning = function (e) { + console.log('MediaRecorder warning: ' + e); + }; + _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; + resolve(); + }); + }; + LocalRecorder.prototype.stop = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before')); + } + _this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + resolve(); + }; + _this.mediaRecorder.stop(); + } + catch (e) { + reject(e); + } + }); + }; + LocalRecorder.prototype.pause = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) { + reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before')); + } + _this.mediaRecorder.pause(); + _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED; + } + catch (error) { + reject(error); + } + }); + }; + LocalRecorder.prototype.resume = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) { + throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before')); + } + _this.mediaRecorder.resume(); + _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; + } + catch (error) { + reject(error); + } + }); + }; + LocalRecorder.prototype.preview = function (parentElement) { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + this.videoPreview = document.createElement('video'); + this.videoPreview.id = this.id; + this.videoPreview.autoplay = true; + if (typeof parentElement === 'string') { + this.htmlParentElementId = parentElement; + var parentElementDom = document.getElementById(parentElement); + if (parentElementDom) { + this.videoPreview = parentElementDom.appendChild(this.videoPreview); + } + } + else { + this.htmlParentElementId = parentElement.id; + this.videoPreview = parentElement.appendChild(this.videoPreview); + } + this.videoPreview.src = this.videoPreviewSrc; + return this.videoPreview; + }; + LocalRecorder.prototype.clean = function () { + var _this = this; + var f = function () { + delete _this.blob; + _this.chunks = []; + _this.count = 0; + delete _this.mediaRecorder; + _this.state = LocalRecorderState_1.LocalRecorderState.READY; + }; + if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) { + this.stop().then(function () { return f(); }).catch(function () { return f(); }); + } + else { + f(); + } + }; + LocalRecorder.prototype.download = function () { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var a = document.createElement('a'); + a.style.display = 'none'; + document.body.appendChild(a); + var url = window.URL.createObjectURL(this.blob); + a.href = url; + a.download = this.id + '.webm'; + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + } + }; + LocalRecorder.prototype.getBlob = function () { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); + } + else { + return this.blob; + } + }; + LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var http_1 = new XMLHttpRequest(); + http_1.open('POST', endpoint, true); + if (typeof headers === 'object') { + for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { + var key = _a[_i]; + http_1.setRequestHeader(key, headers[key]); + } + } + http_1.onreadystatechange = function () { + if (http_1.readyState === 4) { + if (http_1.status.toString().charAt(0) === '2') { + resolve(http_1.responseText); + } + else { + reject(http_1.status); + } + } + }; + http_1.send(_this.blob); + } + }); + }; + LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var http_2 = new XMLHttpRequest(); + http_2.open('POST', endpoint, true); + if (typeof headers === 'object') { + for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { + var key = _a[_i]; + http_2.setRequestHeader(key, headers[key]); + } + } + var sendable = new FormData(); + sendable.append('file', _this.blob, _this.id + '.webm'); + http_2.onreadystatechange = function () { + if (http_2.readyState === 4) { + if (http_2.status.toString().charAt(0) === '2') { + resolve(http_2.responseText); + } + else { + reject(http_2.status); + } + } + }; + http_2.send(sendable); + } + }); + }; + LocalRecorder.prototype.onStopDefault = function () { + console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')'); + this.blob = new Blob(this.chunks, { type: 'video/webm' }); + this.chunks = []; + this.videoPreviewSrc = window.URL.createObjectURL(this.blob); + this.state = LocalRecorderState_1.LocalRecorderState.FINISHED; + }; + return LocalRecorder; +}()); +exports.LocalRecorder = LocalRecorder; + +},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorder_1 = require("./LocalRecorder"); +var Publisher_1 = require("./Publisher"); +var Session_1 = require("./Session"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); +var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); +var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); +var platform = require("platform"); +var OpenVidu = (function () { + function OpenVidu() { + this.secret = ''; + this.recorder = false; + this.advancedConfiguration = {}; + console.info("'OpenVidu' initialized"); + } + OpenVidu.prototype.initSession = function () { + this.session = new Session_1.Session(this); + return this.session; + }; + OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) { + var properties; + if (!!param2 && (typeof param2 !== 'function')) { + properties = param2; + properties = { + audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, + frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), + insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, + mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, + publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, + publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, + resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), + videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined + }; + } + else { + properties = { + insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, + mirror: true, + publishAudio: true, + publishVideo: true, + resolution: '640x480' + }; + } + var publisher = new Publisher_1.Publisher(targetElement, properties, this); + var completionHandler; + if (!!param2 && (typeof param2 === 'function')) { + completionHandler = param2; + } + else if (!!param3) { + completionHandler = param3; + } + publisher.initialize() + .then(function () { + if (completionHandler !== undefined) { + completionHandler(undefined); + } + publisher.emitEvent('accessAllowed', []); + }).catch(function (error) { + if (completionHandler !== undefined) { + completionHandler(error); + } + publisher.emitEvent('accessDenied', []); + }); + return publisher; + }; + OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { + var _this = this; + return new Promise(function (resolve, reject) { + var publisher; + var callback = function (error) { + if (!!error) { + reject(error); + } + else { + resolve(publisher); + } + }; + if (!!properties) { + publisher = _this.initPublisher(targetElement, properties, callback); + } + else { + publisher = _this.initPublisher(targetElement, callback); + } + }); + }; + OpenVidu.prototype.initLocalRecorder = function (stream) { + return new LocalRecorder_1.LocalRecorder(stream); + }; + OpenVidu.prototype.checkSystemRequirements = function () { + var browser = platform.name; + var version = platform.version; + if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') && + (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') && + (browser !== 'Opera') && (browser !== 'Opera Mobile') && + (browser !== 'Safari')) { + return 0; + } + else { + return 1; + } + }; + OpenVidu.prototype.getDevices = function () { + return new Promise(function (resolve, reject) { + navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { + var devices = []; + deviceInfos.forEach(function (deviceInfo) { + if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { + devices.push({ + kind: deviceInfo.kind, + deviceId: deviceInfo.deviceId, + label: deviceInfo.label + }); + } + }); + resolve(devices); + }).catch(function (error) { + console.error('Error getting devices', error); + reject(error); + }); + }); + }; + OpenVidu.prototype.getUserMedia = function (options) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.generateMediaConstraints(options) + .then(function (constraints) { + navigator.mediaDevices.getUserMedia(constraints) + .then(function (mediaStream) { + resolve(mediaStream); + }) + .catch(function (error) { + var errorName; + var errorMessage = error.toString(); + if (!(options.videoSource === 'screen')) { + errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; + } + reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + OpenVidu.prototype.enableProdMode = function () { + console.log = function () { }; + console.debug = function () { }; + console.info = function () { }; + console.warn = function () { }; + }; + OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { + this.advancedConfiguration = configuration; + }; + OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { + var _this = this; + return new Promise(function (resolve, reject) { + var audio, video; + if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) { + audio = false; + } + else if (publisherProperties.audioSource === undefined) { + audio = true; + } + else { + audio = publisherProperties.audioSource; + } + if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) { + video = false; + } + else { + video = { + height: { + ideal: 480 + }, + width: { + ideal: 640 + } + }; + } + var mediaConstraints = { + audio: audio, + video: video + }; + if (typeof mediaConstraints.audio === 'string') { + mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } }; + } + if (mediaConstraints.video) { + if (!!publisherProperties.resolution) { + var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); + var width = Number(widthAndHeight[0]); + var height = Number(widthAndHeight[1]); + mediaConstraints.video.width.ideal = width; + mediaConstraints.video.height.ideal = height; + } + if (!!publisherProperties.frameRate) { + mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate }; + } + if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') { + if (publisherProperties.videoSource === 'screen') { + if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) { + var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); + console.error(error); + reject(error); + } + else { + if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) { + screenSharing.getScreenConstraints(function (error, screenConstraints) { + if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') { + if (error === 'permission-denied' || error === 'PermissionDeniedError') { + var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); + console.error(error_1); + reject(error_1); + } + else { + var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); + screenSharing.getChromeExtensionStatus(extensionId, function (status) { + if (status === 'installed-disabled') { + var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); + console.error(error_2); + reject(error_2); + } + if (status === 'not-installed') { + var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); + console.error(error_3); + reject(error_3); + } + }); + } + } + else { + mediaConstraints.video = screenConstraints; + resolve(mediaConstraints); + } + }); + } + else { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + if (!!error) { + if (error === 'not-installed') { + var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension : + 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold'; + var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl); + console.error(error_4); + reject(error_4); + } + else if (error === 'installed-disabled') { + var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); + console.error(error_5); + reject(error_5); + } + else if (error === 'permission-denied') { + var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); + console.error(error_6); + reject(error_6); + } + } + else { + mediaConstraints.video = screenConstraints.video; + resolve(mediaConstraints); + } + }); + } + publisherProperties.videoSource = 'screen'; + } + } + else { + mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource }; + resolve(mediaConstraints); + } + } + else { + resolve(mediaConstraints); + } + } + else { + resolve(mediaConstraints); + } + }); + }; + OpenVidu.prototype.startWs = function (onConnectSucces) { + var config = { + heartbeat: 5000, + sendCloseMessage: false, + ws: { + uri: this.wsUri, + useSockJS: false, + onconnected: onConnectSucces, + ondisconnect: this.disconnectCallback.bind(this), + onreconnecting: this.reconnectingCallback.bind(this), + onreconnected: this.reconnectedCallback.bind(this) + }, + rpc: { + requestTimeout: 10000, + participantJoined: this.session.onParticipantJoined.bind(this.session), + participantPublished: this.session.onParticipantPublished.bind(this.session), + participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), + participantLeft: this.session.onParticipantLeft.bind(this.session), + participantEvicted: this.session.onParticipantEvicted.bind(this.session), + recordingStarted: this.session.onRecordingStarted.bind(this.session), + recordingStopped: this.session.onRecordingStopped.bind(this.session), + sendMessage: this.session.onNewMessage.bind(this.session), + iceCandidate: this.session.recvIceCandidate.bind(this.session), + mediaError: this.session.onMediaError.bind(this.session) + } + }; + this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); + }; + OpenVidu.prototype.closeWs = function () { + this.jsonRpcClient.close(); + }; + OpenVidu.prototype.sendRequest = function (method, params, callback) { + if (params && params instanceof Function) { + callback = params; + params = {}; + } + console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); + this.jsonRpcClient.send(method, params, callback); + }; + OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) { + var is = (!!mediaSource && + mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' && + mediaSource.id !== undefined && typeof mediaSource.id === 'string' && + mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' && + mediaSource.label !== undefined && typeof mediaSource.label === 'string' && + mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' && + mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string'); + return is; + }; + OpenVidu.prototype.getWsUri = function () { + return this.wsUri; + }; + OpenVidu.prototype.getSecret = function () { + return this.secret; + }; + OpenVidu.prototype.getRecorder = function () { + return this.recorder; + }; + OpenVidu.prototype.disconnectCallback = function () { + console.warn('Websocket connection lost'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenVidu.prototype.reconnectingCallback = function () { + console.warn('Websocket connection lost (reconnecting)'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenVidu.prototype.reconnectedCallback = function () { + console.warn('Websocket reconnected'); + }; + OpenVidu.prototype.isRoomAvailable = function () { + if (this.session !== undefined && this.session instanceof Session_1.Session) { + return true; + } + else { + console.warn('Session instance not found'); + return false; + } + }; + return OpenVidu; +}()); +exports.OpenVidu = OpenVidu; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":42,"../OpenViduInternal/ScreenSharing/Screen-Capturing":47,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":46,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Session_1 = require("./Session"); +var Stream_1 = require("./Stream"); +var StreamManager_1 = require("./StreamManager"); +var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); +var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var Publisher = (function (_super) { + __extends(Publisher, _super); + function Publisher(targEl, properties, openvidu) { + var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this; + _this.openvidu = openvidu; + _this.accessAllowed = false; + _this.isSubscribedToRemote = false; + _this.accessDenied = false; + _this.properties = properties; + _this.stream.ee.on('local-stream-destroyed-by-disconnect', function (reason) { + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + }); + return _this; + } + Publisher.prototype.publishAudio = function (value) { + this.stream.getMediaStream().getAudioTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream'); + }; + Publisher.prototype.publishVideo = function (value) { + this.stream.getMediaStream().getVideoTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream'); + }; + Publisher.prototype.subscribeToRemote = function (value) { + value = (value !== undefined) ? value : true; + this.isSubscribedToRemote = value; + this.stream.subscribeToMyRemote(value); + }; + Publisher.prototype.on = function (type, handler) { + var _this = this; + _super.prototype.on.call(this, type, handler); + if (type === 'streamCreated') { + if (!!this.stream && this.stream.isLocalStreamPublished) { + this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); + } + else { + this.stream.ee.on('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); + }); + } + } + if (type === 'remoteVideoPlaying') { + if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); + } + } + if (type === 'accessAllowed') { + if (this.accessAllowed) { + this.ee.emitEvent('accessAllowed'); + } + } + if (type === 'accessDenied') { + if (this.accessDenied) { + this.ee.emitEvent('accessDenied'); + } + } + return this; + }; + Publisher.prototype.once = function (type, handler) { + var _this = this; + _super.prototype.once.call(this, type, handler); + if (type === 'streamCreated') { + if (!!this.stream && this.stream.isLocalStreamPublished) { + this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); + } + else { + this.stream.ee.once('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); + }); + } + } + if (type === 'remoteVideoPlaying') { + if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); + } + } + if (type === 'accessAllowed') { + if (this.accessAllowed) { + this.ee.emitEvent('accessAllowed'); + } + } + if (type === 'accessDenied') { + if (this.accessDenied) { + this.ee.emitEvent('accessDenied'); + } + } + return this; + }; + Publisher.prototype.initialize = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var errorCallback = function (openViduError) { + _this.accessDenied = true; + _this.accessAllowed = false; + reject(openViduError); + }; + var successCallback = function (mediaStream) { + _this.accessAllowed = true; + _this.accessDenied = false; + if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) { + mediaStream.removeTrack(mediaStream.getAudioTracks()[0]); + mediaStream.addTrack(_this.properties.audioSource); + } + if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) { + mediaStream.removeTrack(mediaStream.getVideoTracks()[0]); + mediaStream.addTrack(_this.properties.videoSource); + } + if (!!mediaStream.getAudioTracks()[0]) { + mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; + } + if (!!mediaStream.getVideoTracks()[0]) { + mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; + } + _this.stream.setMediaStream(mediaStream); + if (!_this.stream.displayMyRemote()) { + _this.stream.updateMediaStreamInVideos(); + } + _this.stream.isLocalStreamReadyToPublish = true; + _this.stream.ee.emitEvent('stream-ready-to-publish', []); + if (!!_this.firstVideoElement) { + _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode); + } + delete _this.firstVideoElement; + resolve(); + }; + _this.openvidu.generateMediaConstraints(_this.properties) + .then(function (constraints) { + var outboundStreamOptions = { + mediaConstraints: constraints, + publisherProperties: _this.properties + }; + _this.stream.setOutboundStreamOptions(outboundStreamOptions); + var constraintsAux = {}; + var timeForDialogEvent = 1250; + if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) { + var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio); + constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1; + constraintsAux.video = constraints.video; + var startTime_1 = Date.now(); + _this.setPermissionDialogTimer(timeForDialogEvent); + navigator.mediaDevices.getUserMedia(constraintsAux) + .then(function (mediaStream) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) { + constraintsAux.audio = definedAudioConstraint_1; + constraintsAux.video = false; + startTime_1 = Date.now(); + _this.setPermissionDialogTimer(timeForDialogEvent); + navigator.mediaDevices.getUserMedia(constraintsAux) + .then(function (audioOnlyStream) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); + successCallback(mediaStream); + }) + .catch(function (error) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + var errorName, errorMessage; + switch (error.name.toLowerCase()) { + case 'notfounderror': + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'notallowederror': + errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'overconstrainederror': + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + } + }); + } + else { + successCallback(mediaStream); + } + }) + .catch(function (error) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + var errorName, errorMessage; + switch (error.name.toLowerCase()) { + case 'notfounderror': + navigator.mediaDevices.getUserMedia({ + audio: false, + video: constraints.video + }) + .then(function (mediaStream) { + mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }).catch(function (e) { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + break; + case 'notallowederror': + errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'overconstrainederror': + navigator.mediaDevices.getUserMedia({ + audio: false, + video: constraints.video + }) + .then(function (mediaStream) { + mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }).catch(function (e) { + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; + errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + break; + } + }); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'")); + } + }) + .catch(function (error) { + errorCallback(error); + }); + }); + }; + Publisher.prototype.updateSession = function (session) { + this.session = session; + this.stream.session = session; + }; + Publisher.prototype.emitEvent = function (type, eventArray) { + this.ee.emitEvent(type, eventArray); + }; + Publisher.prototype.reestablishStreamPlayingEvent = function () { + if (this.ee.getListeners('streamPlaying').length > 0) { + this.addPlayEventToFirstVideo(); + } + }; + Publisher.prototype.setPermissionDialogTimer = function (waitTime) { + var _this = this; + this.permissionDialogTimeout = setTimeout(function () { + _this.ee.emitEvent('accessDialogOpened', []); + }, waitTime); + }; + Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) { + clearTimeout(this.permissionDialogTimeout); + if ((Date.now() - startTime) > waitTime) { + this.ee.emitEvent('accessDialogClosed', []); + } + }; + return Publisher; +}(StreamManager_1.StreamManager)); +exports.Publisher = Publisher; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/VideoElementEvent":36,"./Session":21,"./Stream":22,"./StreamManager":23}],21:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Connection_1 = require("./Connection"); +var Subscriber_1 = require("./Subscriber"); +var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent"); +var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent"); +var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); +var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent"); +var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var platform = require("platform"); +var EventEmitter = require("wolfy87-eventemitter"); +var Session = (function () { + function Session(openvidu) { + this.streamManagers = []; + this.remoteStreamsCreated = {}; + this.remoteConnections = {}; + this.speakingEventsEnabled = false; + this.ee = new EventEmitter(); + this.openvidu = openvidu; + } + Session.prototype.connect = function (token, metadata) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.processToken(token); + if (_this.openvidu.checkSystemRequirements()) { + _this.options = { + sessionId: _this.sessionId, + participantId: token, + metadata: !!metadata ? _this.stringClientMetadata(metadata) : '' + }; + _this.connectAux(token).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu')); + } + }); + }; + Session.prototype.disconnect = function () { + this.leave(false, 'disconnect'); + }; + Session.prototype.subscribe = function (stream, targetElement, param3, param4) { + var properties = {}; + if (!!param3 && typeof param3 !== 'function') { + properties = { + insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, + subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, + subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true + }; + } + else { + properties = { + insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, + subscribeToAudio: true, + subscribeToVideo: true + }; + } + var completionHandler; + if (!!param3 && (typeof param3 === 'function')) { + completionHandler = param3; + } + else if (!!param4) { + completionHandler = param4; + } + console.info('Subscribing to ' + stream.connection.connectionId); + stream.subscribe() + .then(function () { + console.info('Subscribed correctly to ' + stream.connection.connectionId); + if (completionHandler !== undefined) { + completionHandler(undefined); + } + }) + .catch(function (error) { + if (completionHandler !== undefined) { + completionHandler(error); + } + }); + var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties); + if (!!subscriber.targetElement) { + stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode); + } + return subscriber; + }; + Session.prototype.subscribeAsync = function (stream, targetElement, properties) { + var _this = this; + return new Promise(function (resolve, reject) { + var subscriber; + var callback = function (error) { + if (!!error) { + reject(error); + } + else { + resolve(subscriber); + } + }; + if (!!properties) { + subscriber = _this.subscribe(stream, targetElement, properties, callback); + } + else { + subscriber = _this.subscribe(stream, targetElement, callback); + } + }); + }; + Session.prototype.unsubscribe = function (subscriber) { + var connectionId = subscriber.stream.connection.connectionId; + console.info('Unsubscribing from ' + connectionId); + this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { + if (error) { + console.error('Error unsubscribing from ' + connectionId, error); + } + else { + console.info('Unsubscribed correctly from ' + connectionId); + } + subscriber.stream.disposeWebRtcPeer(); + subscriber.stream.disposeMediaStream(); + }); + subscriber.stream.streamManager.removeAllVideos(); + }; + Session.prototype.publish = function (publisher) { + var _this = this; + return new Promise(function (resolve, reject) { + publisher.session = _this; + publisher.stream.session = _this; + if (!publisher.stream.isLocalStreamPublished) { + _this.connection.addStream(publisher.stream); + publisher.stream.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + } + else { + publisher.initialize() + .then(function () { + _this.connection.addStream(publisher.stream); + publisher.reestablishStreamPlayingEvent(); + publisher.stream.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }).catch(function (error) { + reject(error); + }); + } + }); + }; + Session.prototype.unpublish = function (publisher) { + var stream = publisher.stream; + if (!stream.connection) { + console.error('The associated Connection object of this Publisher is null', stream); + return; + } + else if (stream.connection !== this.connection) { + console.error('The associated Connection object of this Publisher is not your local Connection.' + + "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); + return; + } + else { + console.info('Unpublishing local media (' + stream.connection.connectionId + ')'); + this.openvidu.sendRequest('unpublishVideo', function (error, response) { + if (error) { + console.error(error); + } + else { + console.info('Media unpublished correctly'); + } + }); + stream.disposeWebRtcPeer(); + delete stream.connection.stream; + var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish'); + publisher.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + } + }; + Session.prototype.signal = function (signal) { + var _this = this; + return new Promise(function (resolve, reject) { + var signalMessage = {}; + if (signal.to && signal.to.length > 0) { + var connectionIds_1 = []; + signal.to.forEach(function (connection) { + connectionIds_1.push(connection.connectionId); + }); + signalMessage['to'] = connectionIds_1; + } + else { + signalMessage['to'] = []; + } + signalMessage['data'] = signal.data ? signal.data : ''; + signalMessage['type'] = signal.type ? signal.type : ''; + _this.openvidu.sendRequest('sendMessage', { + message: JSON.stringify(signalMessage) + }, function (error, response) { + if (!!error) { + reject(error); + } + else { + resolve(); + } + }); + }); + }; + Session.prototype.on = function (type, handler) { + this.ee.on(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + type + "' triggered by 'Session'"); + } + handler(event); + }); + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = true; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !str.speechEvent && str.hasAudio) { + str.enableSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.once = function (type, handler) { + this.ee.once(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + type + "' triggered by 'Session'"); + } + handler(event); + }); + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = true; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !str.speechEvent && str.hasAudio) { + str.enableOnceSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.off = function (type, handler) { + if (!handler) { + this.ee.removeAllListeners(type); + } + else { + this.ee.off(type, handler); + } + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = false; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !!str.speechEvent) { + str.disableSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.onParticipantJoined = function (response) { + var _this = this; + this.getConnection(response.id, '') + .then(function (connection) { + console.warn('Connection ' + response.id + ' already exists in connections list'); + }) + .catch(function (openViduError) { + var connection = new Connection_1.Connection(_this, response); + _this.remoteConnections[response.id] = connection; + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); + }); + }; + Session.prototype.onParticipantLeft = function (msg) { + var _this = this; + this.getRemoteConnection(msg.name, 'Remote connection ' + msg.name + " unknown when 'onParticipantLeft'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (connection) { + if (!!connection.stream) { + var stream = connection.stream; + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + delete _this.remoteStreamsCreated[stream.streamId]; + } + delete _this.remoteConnections[connection.connectionId]; + _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onParticipantPublished = function (response) { + var _this = this; + var afterConnectionFound = function (connection) { + _this.remoteConnections[connection.connectionId] = connection; + if (!_this.remoteStreamsCreated[connection.stream.streamId]) { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]); + } + _this.remoteStreamsCreated[connection.stream.streamId] = true; + }; + var connection; + this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (con) { + connection = con; + response.metadata = con.data; + connection.options = response; + connection.initRemoteStreams(response.streams); + afterConnectionFound(connection); + }) + .catch(function (openViduError) { + connection = new Connection_1.Connection(_this, response); + afterConnectionFound(connection); + }); + }; + Session.prototype.onParticipantUnpublished = function (msg) { + var _this = this; + this.getRemoteConnection(msg.name, "Remote connection '" + msg.name + "' unknown when 'onParticipantUnpublished'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (connection) { + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + var streamId = connection.stream.streamId; + delete _this.remoteStreamsCreated[streamId]; + connection.removeStream(streamId); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onParticipantEvicted = function (msg) { + }; + Session.prototype.onNewMessage = function (msg) { + var _this = this; + console.info('New signal: ' + JSON.stringify(msg)); + this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: " + + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId) + .then(function (connection) { + _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); + _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.recvIceCandidate = function (msg) { + var candidate = { + candidate: msg.candidate, + sdpMid: msg.sdpMid, + sdpMLineIndex: msg.sdpMLineIndex, + toJSON: function () { + return { candidate: msg.candidate }; + } + }; + this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) + .then(function (connection) { + var stream = connection.stream; + stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) { + console.error('Error adding candidate for ' + stream.streamId + + ' stream of endpoint ' + msg.endpointName + ': ' + error); + }); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onSessionClosed = function (msg) { + console.info('Session closed: ' + JSON.stringify(msg)); + var s = msg.room; + if (s !== undefined) { + this.ee.emitEvent('session-closed', [{ + session: s + }]); + } + else { + console.warn('Session undefined on session closed', msg); + } + }; + Session.prototype.onLostConnection = function () { + console.warn('Lost connection in Session ' + this.sessionId); + if (!!this.sessionId && !this.connection.disposed) { + this.leave(true, 'networkDisconnect'); + } + }; + Session.prototype.onMediaError = function (params) { + console.error('Media error: ' + JSON.stringify(params)); + var err = params.error; + if (err) { + this.ee.emitEvent('error-media', [{ + error: err + }]); + } + else { + console.warn('Received undefined media error. Params:', params); + } + }; + Session.prototype.onRecordingStarted = function (response) { + this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]); + }; + Session.prototype.onRecordingStopped = function (response) { + this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]); + }; + Session.prototype.emitEvent = function (type, eventArray) { + this.ee.emitEvent(type, eventArray); + }; + Session.prototype.leave = function (forced, reason) { + var _this = this; + forced = !!forced; + console.info('Leaving Session (forced=' + forced + ')'); + if (!!this.connection) { + if (!this.connection.disposed && !forced) { + this.openvidu.sendRequest('leaveRoom', function (error, response) { + if (error) { + console.error(error); + } + _this.openvidu.closeWs(); + }); + } + else { + this.openvidu.closeWs(); + } + if (!!this.connection.stream) { + this.connection.stream.disposeWebRtcPeer(); + if (this.connection.stream.isLocalStreamPublished) { + this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); + } + } + if (!this.connection.disposed) { + var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason); + this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); + sessionDisconnectEvent.callDefaultBehaviour(); + } + } + else { + console.warn('You were not connected to the session ' + this.sessionId); + } + }; + Session.prototype.connectAux = function (token) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.openvidu.startWs(function (error) { + if (!!error) { + reject(error); + } + else { + var joinParams = { + token: (!!token) ? token : '', + session: _this.sessionId, + metadata: !!_this.options.metadata ? _this.options.metadata : '', + secret: _this.openvidu.getSecret(), + recorder: _this.openvidu.getRecorder(), + }; + _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { + if (!!error) { + reject(error); + } + else { + _this.connection = new Connection_1.Connection(_this); + _this.connection.connectionId = response.id; + _this.connection.data = response.metadata; + var events_1 = { + connections: new Array(), + streams: new Array() + }; + var existingParticipants = response.value; + existingParticipants.forEach(function (participant) { + var connection = new Connection_1.Connection(_this, participant); + _this.remoteConnections[connection.connectionId] = connection; + events_1.connections.push(connection); + if (!!connection.stream) { + _this.remoteStreamsCreated[connection.stream.streamId] = true; + events_1.streams.push(connection.stream); + } + }); + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]); + events_1.connections.forEach(function (connection) { + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); + }); + events_1.streams.forEach(function (stream) { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]); + }); + resolve(); + } + }); + } + }); + }); + }; + Session.prototype.stringClientMetadata = function (metadata) { + if (typeof metadata !== 'string') { + return JSON.stringify(metadata); + } + else { + return metadata; + } + }; + Session.prototype.getConnection = function (connectionId, errorMessage) { + var _this = this; + return new Promise(function (resolve, reject) { + var connection = _this.remoteConnections[connectionId]; + if (!!connection) { + resolve(connection); + } + else { + if (_this.connection.connectionId === connectionId) { + resolve(_this.connection); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); + } + } + }); + }; + Session.prototype.getRemoteConnection = function (connectionId, errorMessage) { + var _this = this; + return new Promise(function (resolve, reject) { + var connection = _this.remoteConnections[connectionId]; + if (!!connection) { + resolve(connection); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); + } + }); + }; + Session.prototype.processToken = function (token) { + var url = new URL(token); + this.sessionId = url.searchParams.get('sessionId'); + var secret = url.searchParams.get('secret'); + var recorder = url.searchParams.get('recorder'); + var turnUsername = url.searchParams.get('turnUsername'); + var turnCredential = url.searchParams.get('turnCredential'); + var role = url.searchParams.get('role'); + if (!!secret) { + this.openvidu.secret = secret; + } + if (!!recorder) { + this.openvidu.recorder = true; + } + if (!!turnUsername && !!turnCredential) { + var stunUrl = 'stun:' + url.hostname + ':3478'; + var turnUrl1 = 'turn:' + url.hostname + ':3478'; + var turnUrl2 = turnUrl1 + '?transport=tcp'; + this.openvidu.iceServers = [ + { urls: [stunUrl] }, + { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential } + ]; + console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']'); + } + if (!!role) { + this.openvidu.role = role; + } + this.openvidu.wsUri = 'wss://' + url.host + '/openvidu'; + }; + return Session; +}()); +exports.Session = Session; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer"); +var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats"); +var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent"); +var EventEmitter = require("wolfy87-eventemitter"); +var hark = require("hark"); +var Stream = (function () { + function Stream(session, options) { + var _this = this; + this.ee = new EventEmitter(); + this.isSubscribeToRemote = false; + this.isLocalStreamReadyToPublish = false; + this.isLocalStreamPublished = false; + this.session = session; + if (options.hasOwnProperty('id')) { + this.inboundStreamOpts = options; + this.streamId = this.inboundStreamOpts.id; + this.hasAudio = this.inboundStreamOpts.recvAudio; + this.hasVideo = this.inboundStreamOpts.recvVideo; + this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo; + this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; + } + else { + this.outboundStreamOpts = options; + if (this.isSendVideo()) { + if (this.isSendScreen()) { + this.typeOfVideo = 'SCREEN'; + } + else { + this.typeOfVideo = 'CAMERA'; + } + this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; + } + else { + delete this.typeOfVideo; + } + this.hasAudio = this.isSendAudio(); + this.hasVideo = this.isSendVideo(); + } + this.ee.on('mediastream-updated', function () { + _this.streamManager.updateMediaStream(_this.mediaStream); + console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']'); + }); + } + Stream.prototype.getMediaStream = function () { + return this.mediaStream; + }; + Stream.prototype.setMediaStream = function (mediaStream) { + this.mediaStream = mediaStream; + }; + Stream.prototype.updateMediaStreamInVideos = function () { + this.ee.emitEvent('mediastream-updated'); + }; + Stream.prototype.getWebRtcPeer = function () { + return this.webRtcPeer; + }; + Stream.prototype.getRTCPeerConnection = function () { + return this.webRtcPeer.pc; + }; + Stream.prototype.subscribeToMyRemote = function (value) { + this.isSubscribeToRemote = value; + }; + Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { + this.outboundStreamOpts = outboundStreamOpts; + }; + Stream.prototype.subscribe = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.initWebRtcPeerReceive() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + Stream.prototype.publish = function () { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.isLocalStreamReadyToPublish) { + _this.initWebRtcPeerSend() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + } + else { + _this.ee.once('stream-ready-to-publish', function () { + _this.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }); + } + }); + }; + Stream.prototype.disposeWebRtcPeer = function () { + if (this.webRtcPeer) { + this.webRtcPeer.dispose(); + } + if (this.speechEvent) { + this.speechEvent.stop(); + } + this.stopWebRtcStats(); + console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed'); + }; + Stream.prototype.disposeMediaStream = function () { + if (this.mediaStream) { + this.mediaStream.getAudioTracks().forEach(function (track) { + track.stop(); + }); + this.mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + delete this.mediaStream; + } + console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed'); + }; + Stream.prototype.displayMyRemote = function () { + return this.isSubscribeToRemote; + }; + Stream.prototype.isSendAudio = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.audioSource !== null && + this.outboundStreamOpts.publisherProperties.audioSource !== false); + }; + Stream.prototype.isSendVideo = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.videoSource !== null && + this.outboundStreamOpts.publisherProperties.videoSource !== false); + }; + Stream.prototype.isSendScreen = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.videoSource === 'screen'); + }; + Stream.prototype.setSpeechEventIfNotExists = function () { + if (!this.speechEvent) { + var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}; + harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50; + harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50; + this.speechEvent = hark(this.mediaStream, harkOptions); + } + }; + Stream.prototype.enableSpeakingEvents = function () { + var _this = this; + this.setSpeechEventIfNotExists(); + this.speechEvent.on('speaking', function () { + _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); + }); + this.speechEvent.on('stopped_speaking', function () { + _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); + }); + }; + Stream.prototype.enableOnceSpeakingEvents = function () { + var _this = this; + this.setSpeechEventIfNotExists(); + this.speechEvent.on('speaking', function () { + _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); + _this.disableSpeakingEvents(); + }); + this.speechEvent.on('stopped_speaking', function () { + _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); + _this.disableSpeakingEvents(); + }); + }; + Stream.prototype.disableSpeakingEvents = function () { + this.speechEvent.stop(); + this.speechEvent = undefined; + }; + Stream.prototype.isLocal = function () { + return (!this.inboundStreamOpts && !!this.outboundStreamOpts); + }; + Stream.prototype.getSelectedIceCandidate = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.webRtcStats.getSelectedIceCandidateInfo() + .then(function (report) { return resolve(report); }) + .catch(function (error) { return reject(error); }); + }); + }; + Stream.prototype.getRemoteIceCandidateList = function () { + return this.webRtcPeer.remoteCandidatesQueue; + }; + Stream.prototype.getLocalIceCandidateList = function () { + return this.webRtcPeer.localCandidatesQueue; + }; + Stream.prototype.initWebRtcPeerSend = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var userMediaConstraints = { + audio: _this.isSendAudio(), + video: _this.isSendVideo() + }; + var options = { + mediaStream: _this.mediaStream, + mediaConstraints: userMediaConstraints, + onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), + iceServers: _this.getIceServersConf(), + simulcast: false + }; + var successCallback = function (sdpOfferParam) { + console.debug('Sending SDP offer to publish as ' + + _this.streamId, sdpOfferParam); + _this.session.openvidu.sendRequest('publishVideo', { + sdpOffer: sdpOfferParam, + doLoopback: _this.displayMyRemote() || false, + audioActive: _this.isSendAudio(), + videoActive: _this.isSendVideo(), + typeOfVideo: ((_this.isSendVideo()) ? (_this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''), + frameRate: !!_this.frameRate ? _this.frameRate : -1 + }, function (error, response) { + if (error) { + reject('Error on publishVideo: ' + JSON.stringify(error)); + } + else { + _this.webRtcPeer.processAnswer(response.sdpAnswer) + .then(function () { + _this.streamId = response.id; + _this.isLocalStreamPublished = true; + if (_this.displayMyRemote()) { + _this.remotePeerSuccesfullyEstablished(); + } + _this.ee.emitEvent('stream-created-by-publisher'); + _this.initWebRtcStats(); + resolve(); + }) + .catch(function (error) { + reject(error); + }); + console.info("'Publisher' successfully published to session"); + } + }); + }; + if (_this.displayMyRemote()) { + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options); + } + else { + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options); + } + _this.webRtcPeer.generateOffer().then(function (offer) { + successCallback(offer); + }).catch(function (error) { + reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error))); + }); + }); + }; + Stream.prototype.initWebRtcPeerReceive = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var offerConstraints = { + audio: _this.inboundStreamOpts.recvAudio, + video: _this.inboundStreamOpts.recvVideo + }; + console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); + var options = { + onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), + mediaConstraints: offerConstraints, + iceServers: _this.getIceServersConf(), + simulcast: false + }; + var successCallback = function (sdpOfferParam) { + console.debug('Sending SDP offer to subscribe to ' + + _this.streamId, sdpOfferParam); + _this.session.openvidu.sendRequest('receiveVideoFrom', { + sender: _this.streamId, + sdpOffer: sdpOfferParam + }, function (error, response) { + if (error) { + reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error))); + } + else { + _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () { + _this.remotePeerSuccesfullyEstablished(); + _this.initWebRtcStats(); + resolve(); + }).catch(function (error) { + reject(error); + }); + } + }); + }; + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options); + _this.webRtcPeer.generateOffer() + .then(function (offer) { + successCallback(offer); + }) + .catch(function (error) { + reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error))); + }); + }); + }; + Stream.prototype.remotePeerSuccesfullyEstablished = function () { + this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0]; + console.debug('Peer remote stream', this.mediaStream); + if (!!this.mediaStream) { + this.ee.emitEvent('mediastream-updated'); + if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) { + this.enableSpeakingEvents(); + } + } + }; + Stream.prototype.initWebRtcStats = function () { + this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); + this.webRtcStats.initWebRtcStats(); + }; + Stream.prototype.stopWebRtcStats = function () { + if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { + this.webRtcStats.stopWebRtcStats(); + } + }; + Stream.prototype.getIceServersConf = function () { + var returnValue; + if (!!this.session.openvidu.advancedConfiguration.iceServers) { + returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ? + undefined : + this.session.openvidu.advancedConfiguration.iceServers; + } + else if (this.session.openvidu.iceServers) { + returnValue = this.session.openvidu.iceServers; + } + else { + returnValue = undefined; + } + return returnValue; + }; + return Stream; +}()); +exports.Stream = Stream; + +},{"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":48,"../OpenViduInternal/WebRtcStats/WebRtcStats":49,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); +var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var EventEmitter = require("wolfy87-eventemitter"); +var StreamManager = (function () { + function StreamManager(stream, targetElement) { + var _this = this; + this.videos = []; + this.lazyLaunchVideoElementCreatedEvent = false; + this.ee = new EventEmitter(); + this.stream = stream; + this.stream.streamManager = this; + this.remote = !this.stream.isLocal(); + if (!!targetElement) { + var targEl = void 0; + if (typeof targetElement === 'string') { + targEl = document.getElementById(targetElement); + } + else if (targetElement instanceof HTMLElement) { + targEl = targetElement; + } + if (!!targEl) { + this.firstVideoElement = { + targetElement: targEl, + video: document.createElement('video'), + id: '' + }; + this.targetElement = targEl; + this.element = targEl; + } + } + this.canPlayListener = function () { + if (_this.stream.isLocal()) { + if (!_this.stream.displayMyRemote()) { + console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); + } + else { + console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]); + } + } + else { + console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); + } + _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]); + }; + } + StreamManager.prototype.on = function (type, handler) { + this.ee.on(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered", event); + } + else { + console.info("Event '" + type + "' triggered"); + } + handler(event); + }); + if (type === 'videoElementCreated') { + if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); + this.lazyLaunchVideoElementCreatedEvent = false; + } + } + if (type === 'streamPlaying' || type === 'videoPlaying') { + if (this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); + this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); + } + } + return this; + }; + StreamManager.prototype.once = function (type, handler) { + this.ee.once(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered once", event); + } + else { + console.info("Event '" + type + "' triggered once"); + } + handler(event); + }); + if (type === 'videoElementCreated') { + if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); + } + } + if (type === 'streamPlaying' || type === 'videoPlaying') { + if (this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); + this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); + } + } + return this; + }; + StreamManager.prototype.off = function (type, handler) { + if (!handler) { + this.ee.removeAllListeners(type); + } + else { + this.ee.off(type, handler); + } + return this; + }; + StreamManager.prototype.addVideoElement = function (video) { + this.initializeVideoProperties(video); + for (var _i = 0, _a = this.videos; _i < _a.length; _i++) { + var v = _a[_i]; + if (v.video === video) { + return 0; + } + } + var returnNumber = 1; + this.initializeVideoProperties(video); + for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) { + var streamManager = _c[_b]; + if (streamManager.disassociateVideo(video)) { + returnNumber = -1; + break; + } + } + this.stream.session.streamManagers.forEach(function (streamManager) { + streamManager.disassociateVideo(video); + }); + this.pushNewStreamManagerVideo({ + video: video, + id: video.id + }); + console.info('New video element associated to ', this); + return returnNumber; + }; + StreamManager.prototype.createVideoElement = function (targetElement, insertMode) { + var targEl; + if (typeof targetElement === 'string') { + targEl = document.getElementById(targEl); + if (!targEl) { + throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); + } + } + else if (targetElement instanceof HTMLElement) { + targEl = targetElement; + } + else { + throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); + } + var video = document.createElement('video'); + this.initializeVideoProperties(video); + var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; + switch (insMode) { + case VideoInsertMode_1.VideoInsertMode.AFTER: + targEl.parentNode.insertBefore(video, targEl.nextSibling); + break; + case VideoInsertMode_1.VideoInsertMode.APPEND: + targEl.appendChild(video); + break; + case VideoInsertMode_1.VideoInsertMode.BEFORE: + targEl.parentNode.insertBefore(video, targEl); + break; + case VideoInsertMode_1.VideoInsertMode.PREPEND: + targEl.insertBefore(video, targEl.childNodes[0]); + break; + case VideoInsertMode_1.VideoInsertMode.REPLACE: + targEl.parentNode.replaceChild(video, targEl); + break; + default: + insMode = VideoInsertMode_1.VideoInsertMode.APPEND; + targEl.appendChild(video); + break; + } + var v = { + targetElement: targEl, + video: video, + insertMode: insMode, + id: video.id + }; + this.pushNewStreamManagerVideo(v); + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]); + this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement; + return video; + }; + StreamManager.prototype.initializeVideoProperties = function (video) { + video.srcObject = this.stream.getMediaStream(); + video.autoplay = true; + video.controls = false; + if (!video.id) { + video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId; + if (!this.id && !!this.targetElement) { + this.id = video.id; + } + } + if (!this.remote && !this.stream.displayMyRemote()) { + video.muted = true; + if (this.stream.outboundStreamOpts.publisherProperties.mirror) { + this.mirrorVideo(video); + } + } + }; + StreamManager.prototype.removeAllVideos = function () { + var _this = this; + for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) { + if (this.stream.session.streamManagers[i] === this) { + this.stream.session.streamManagers.splice(i, 1); + } + } + this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) { + streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener); + if (!!streamManagerVideo.targetElement) { + streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video); + _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]); + _this.videos.splice(videos.length - 1 - index, 1); + } + else { + streamManagerVideo.video.srcObject = null; + } + }); + }; + StreamManager.prototype.disassociateVideo = function (video) { + var disassociated = false; + for (var i = 0; i < this.videos.length; i++) { + if (this.videos[i].video === video) { + this.videos.splice(i, 1); + disassociated = true; + console.info('Video element disassociated from ', this); + break; + } + } + return disassociated; + }; + StreamManager.prototype.addPlayEventToFirstVideo = function () { + if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) { + this.videos[0].video.addEventListener('canplay', this.canPlayListener); + } + }; + StreamManager.prototype.updateMediaStream = function (mediaStream) { + this.videos.forEach(function (streamManagerVideo) { + streamManagerVideo.video.srcObject = mediaStream; + }); + }; + StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) { + this.videos.push(streamManagerVideo); + this.addPlayEventToFirstVideo(); + if (this.stream.session.streamManagers.indexOf(this) === -1) { + this.stream.session.streamManagers.push(this); + } + }; + StreamManager.prototype.mirrorVideo = function (video) { + video.style.transform = 'rotateY(180deg)'; + video.style.webkitTransform = 'rotateY(180deg)'; + }; + return StreamManager; +}()); +exports.StreamManager = StreamManager; + +},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":36,"wolfy87-eventemitter":15}],24:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var StreamManager_1 = require("./StreamManager"); +var Subscriber = (function (_super) { + __extends(Subscriber, _super); + function Subscriber(stream, targEl, properties) { + var _this = _super.call(this, stream, targEl) || this; + _this.element = _this.targetElement; + _this.stream = stream; + _this.properties = properties; + return _this; + } + Subscriber.prototype.subscribeToAudio = function (value) { + this.stream.getMediaStream().getAudioTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream'); + return this; + }; + Subscriber.prototype.subscribeToVideo = function (value) { + this.stream.getMediaStream().getVideoTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream'); + return this; + }; + return Subscriber; +}(StreamManager_1.StreamManager)); +exports.Subscriber = Subscriber; + +},{"./StreamManager":23}],25:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorderState; +(function (LocalRecorderState) { + LocalRecorderState["READY"] = "READY"; + LocalRecorderState["RECORDING"] = "RECORDING"; + LocalRecorderState["PAUSED"] = "PAUSED"; + LocalRecorderState["FINISHED"] = "FINISHED"; +})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {})); + +},{}],26:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduErrorName; +(function (OpenViduErrorName) { + OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; + OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED"; + OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; + OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; + OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; + OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED"; + OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; + OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; + OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; + OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; + OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; + OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED"; + OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; +})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); +var OpenViduError = (function () { + function OpenViduError(name, message) { + this.name = name; + this.message = message; + } + return OpenViduError; +}()); +exports.OpenViduError = OpenViduError; + +},{}],27:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var VideoInsertMode; +(function (VideoInsertMode) { + VideoInsertMode["AFTER"] = "AFTER"; + VideoInsertMode["APPEND"] = "APPEND"; + VideoInsertMode["BEFORE"] = "BEFORE"; + VideoInsertMode["PREPEND"] = "PREPEND"; + VideoInsertMode["REPLACE"] = "REPLACE"; +})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); + +},{}],28:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var ConnectionEvent = (function (_super) { + __extends(ConnectionEvent, _super); + function ConnectionEvent(cancelable, target, type, connection, reason) { + var _this = _super.call(this, cancelable, target, type) || this; + _this.connection = connection; + _this.reason = reason; + return _this; + } + ConnectionEvent.prototype.callDefaultBehaviour = function () { }; + return ConnectionEvent; +}(Event_1.Event)); +exports.ConnectionEvent = ConnectionEvent; + +},{"./Event":29}],29:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Event = (function () { + function Event(cancelable, target, type) { + this.hasBeenPrevented = false; + this.cancelable = cancelable; + this.target = target; + this.type = type; + } + Event.prototype.isDefaultPrevented = function () { + return this.hasBeenPrevented; + }; + Event.prototype.preventDefault = function () { + this.callDefaultBehaviour = function () { }; + this.hasBeenPrevented = true; + }; + return Event; +}()); +exports.Event = Event; + +},{}],30:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var PublisherSpeakingEvent = (function (_super) { + __extends(PublisherSpeakingEvent, _super); + function PublisherSpeakingEvent(target, type, connection, streamId) { + var _this = _super.call(this, false, target, type) || this; + _this.type = type; + _this.connection = connection; + _this.streamId = streamId; + return _this; + } + PublisherSpeakingEvent.prototype.callDefaultBehaviour = function () { }; + return PublisherSpeakingEvent; +}(Event_1.Event)); +exports.PublisherSpeakingEvent = PublisherSpeakingEvent; + +},{"./Event":29}],31:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var RecordingEvent = (function (_super) { + __extends(RecordingEvent, _super); + function RecordingEvent(target, type, id, name) { + var _this = _super.call(this, false, target, type) || this; + _this.id = id; + if (name !== id) { + _this.name = name; + } + return _this; + } + RecordingEvent.prototype.callDefaultBehaviour = function () { }; + return RecordingEvent; +}(Event_1.Event)); +exports.RecordingEvent = RecordingEvent; + +},{"./Event":29}],32:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var SessionDisconnectedEvent = (function (_super) { + __extends(SessionDisconnectedEvent, _super); + function SessionDisconnectedEvent(target, reason) { + var _this = _super.call(this, true, target, 'sessionDisconnected') || this; + _this.reason = reason; + return _this; + } + SessionDisconnectedEvent.prototype.callDefaultBehaviour = function () { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); + var session = this.target; + for (var connectionId in session.remoteConnections) { + if (!!session.remoteConnections[connectionId].stream) { + session.remoteConnections[connectionId].stream.disposeWebRtcPeer(); + session.remoteConnections[connectionId].stream.disposeMediaStream(); + if (session.remoteConnections[connectionId].stream.streamManager) { + session.remoteConnections[connectionId].stream.streamManager.removeAllVideos(); + } + delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId]; + session.remoteConnections[connectionId].dispose(); + } + delete session.remoteConnections[connectionId]; + } + }; + return SessionDisconnectedEvent; +}(Event_1.Event)); +exports.SessionDisconnectedEvent = SessionDisconnectedEvent; + +},{"./Event":29}],33:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var SignalEvent = (function (_super) { + __extends(SignalEvent, _super); + function SignalEvent(target, type, data, from) { + var _this = _super.call(this, false, target, type) || this; + _this.type = type; + _this.data = data; + _this.from = from; + return _this; + } + SignalEvent.prototype.callDefaultBehaviour = function () { }; + return SignalEvent; +}(Event_1.Event)); +exports.SignalEvent = SignalEvent; + +},{"./Event":29}],34:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var Publisher_1 = require("../../OpenVidu/Publisher"); +var Session_1 = require("../../OpenVidu/Session"); +var StreamEvent = (function (_super) { + __extends(StreamEvent, _super); + function StreamEvent(cancelable, target, type, stream, reason) { + var _this = _super.call(this, cancelable, target, type) || this; + _this.stream = stream; + _this.reason = reason; + return _this; + } + StreamEvent.prototype.callDefaultBehaviour = function () { + if (this.type === 'streamDestroyed') { + if (this.target instanceof Session_1.Session) { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); + this.stream.disposeWebRtcPeer(); + } + else if (this.target instanceof Publisher_1.Publisher) { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Publisher'"); + this.stream.isLocalStreamReadyToPublish = false; + } + this.stream.disposeMediaStream(); + if (this.stream.streamManager) + this.stream.streamManager.removeAllVideos(); + delete this.stream.session.remoteStreamsCreated[this.stream.streamId]; + var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId]; + if (!!remoteConnection && !!remoteConnection.options) { + var streamOptionsServer = remoteConnection.options.streams; + for (var i = streamOptionsServer.length - 1; i >= 0; --i) { + if (streamOptionsServer[i].id === this.stream.streamId) { + streamOptionsServer.splice(i, 1); + } + } + } + } + }; + return StreamEvent; +}(Event_1.Event)); +exports.StreamEvent = StreamEvent; + +},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var StreamManagerEvent = (function (_super) { + __extends(StreamManagerEvent, _super); + function StreamManagerEvent(target) { + return _super.call(this, false, target, 'streamPlaying') || this; + } + StreamManagerEvent.prototype.callDefaultBehaviour = function () { }; + return StreamManagerEvent; +}(Event_1.Event)); +exports.StreamManagerEvent = StreamManagerEvent; + +},{"./Event":29}],36:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var VideoElementEvent = (function (_super) { + __extends(VideoElementEvent, _super); + function VideoElementEvent(element, target, type) { + var _this = _super.call(this, false, target, type) || this; + _this.element = element; + return _this; + } + VideoElementEvent.prototype.callDefaultBehaviour = function () { }; + return VideoElementEvent; +}(Event_1.Event)); +exports.VideoElementEvent = VideoElementEvent; + +},{"./Event":29}],37:[function(require,module,exports){ +function Mapper() { + var sources = {}; + this.forEach = function (callback) { + for (var key in sources) { + var source = sources[key]; + for (var key2 in source) + callback(source[key2]); + } + ; + }; + this.get = function (id, source) { + var ids = sources[source]; + if (ids == undefined) + return undefined; + return ids[id]; + }; + this.remove = function (id, source) { + var ids = sources[source]; + if (ids == undefined) + return; + delete ids[id]; + for (var i in ids) { + return false; + } + delete sources[source]; + }; + this.set = function (value, id, source) { + if (value == undefined) + return this.remove(id, source); + var ids = sources[source]; + if (ids == undefined) + sources[source] = ids = {}; + ids[id] = value; + }; +} +; +Mapper.prototype.pop = function (id, source) { + var value = this.get(id, source); + if (value == undefined) + return undefined; + this.remove(id, source); + return value; +}; +module.exports = Mapper; + +},{}],38:[function(require,module,exports){ +var JsonRpcClient = require('./jsonrpcclient'); +exports.JsonRpcClient = JsonRpcClient; + +},{"./jsonrpcclient":39}],39:[function(require,module,exports){ +var RpcBuilder = require('../'); +var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); +Date.now = Date.now || function () { + return +new Date; +}; +var PING_INTERVAL = 5000; +var RECONNECTING = 'RECONNECTING'; +var CONNECTED = 'CONNECTED'; +var DISCONNECTED = 'DISCONNECTED'; +var Logger = console; +function JsonRpcClient(configuration) { + var self = this; + var wsConfig = configuration.ws; + var notReconnectIfNumLessThan = -1; + var pingNextNum = 0; + var enabledPings = true; + var pingPongStarted = false; + var pingInterval; + var status = DISCONNECTED; + var onreconnecting = wsConfig.onreconnecting; + var onreconnected = wsConfig.onreconnected; + var onconnected = wsConfig.onconnected; + var onerror = wsConfig.onerror; + configuration.rpc.pull = function (params, request) { + request.reply(null, "push"); + }; + wsConfig.onreconnecting = function () { + Logger.debug("--------- ONRECONNECTING -----------"); + if (status === RECONNECTING) { + Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it"); + return; + } + status = RECONNECTING; + if (onreconnecting) { + onreconnecting(); + } + }; + wsConfig.onreconnected = function () { + Logger.debug("--------- ONRECONNECTED -----------"); + if (status === CONNECTED) { + Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it"); + return; + } + status = CONNECTED; + enabledPings = true; + updateNotReconnectIfLessThan(); + usePing(); + if (onreconnected) { + onreconnected(); + } + }; + wsConfig.onconnected = function () { + Logger.debug("--------- ONCONNECTED -----------"); + if (status === CONNECTED) { + Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it"); + return; + } + status = CONNECTED; + enabledPings = true; + usePing(); + if (onconnected) { + onconnected(); + } + }; + wsConfig.onerror = function (error) { + Logger.debug("--------- ONERROR -----------"); + status = DISCONNECTED; + if (onerror) { + onerror(error); + } + }; + var ws = new WebSocketWithReconnection(wsConfig); + Logger.debug('Connecting websocket to URI: ' + wsConfig.uri); + var rpcBuilderOptions = { + request_timeout: configuration.rpc.requestTimeout, + ping_request_timeout: configuration.rpc.heartbeatRequestTimeout + }; + var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) { + Logger.debug('Received request: ' + JSON.stringify(request)); + try { + var func = configuration.rpc[request.method]; + if (func === undefined) { + Logger.error("Method " + request.method + " not registered in client"); + } + else { + func(request.params, request); + } + } + catch (err) { + Logger.error('Exception processing request: ' + JSON.stringify(request)); + Logger.error(err); + } + }); + this.send = function (method, params, callback) { + if (method !== 'ping') { + Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); + } + var requestTime = Date.now(); + rpc.encode(method, params, function (error, result) { + if (error) { + try { + Logger.error("ERROR:" + error.message + " in Request: method:" + + method + " params:" + JSON.stringify(params) + " request:" + + error.request); + if (error.data) { + Logger.error("ERROR DATA:" + JSON.stringify(error.data)); + } + } + catch (e) { } + error.requestTime = requestTime; + } + if (callback) { + if (result != undefined && result.value !== 'pong') { + Logger.debug('Response: ' + JSON.stringify(result)); + } + callback(error, result); + } + }); + }; + function updateNotReconnectIfLessThan() { + Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' + + notReconnectIfNumLessThan + ')'); + notReconnectIfNumLessThan = pingNextNum; + } + function sendPing() { + if (enabledPings) { + var params = null; + if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) { + params = { + interval: configuration.heartbeat || PING_INTERVAL + }; + } + pingNextNum++; + self.send('ping', params, (function (pingNum) { + return function (error, result) { + if (error) { + Logger.debug("Error in ping request #" + pingNum + " (" + + error.message + ")"); + if (pingNum > notReconnectIfNumLessThan) { + enabledPings = false; + updateNotReconnectIfLessThan(); + Logger.debug("Server did not respond to ping message #" + + pingNum + ". Reconnecting... "); + ws.reconnectWs(); + } + } + }; + })(pingNextNum)); + } + else { + Logger.debug("Trying to send ping, but ping is not enabled"); + } + } + function usePing() { + if (!pingPongStarted) { + Logger.debug("Starting ping (if configured)"); + pingPongStarted = true; + if (configuration.heartbeat != undefined) { + pingInterval = setInterval(sendPing, configuration.heartbeat); + sendPing(); + } + } + } + this.close = function () { + Logger.debug("Closing jsonRpcClient explicitly by client"); + if (pingInterval != undefined) { + Logger.debug("Clearing ping interval"); + clearInterval(pingInterval); + } + pingPongStarted = false; + enabledPings = false; + if (configuration.sendCloseMessage) { + Logger.debug("Sending close message"); + this.send('closeSession', null, function (error, result) { + if (error) { + Logger.error("Error sending close message: " + JSON.stringify(error)); + } + ws.close(); + }); + } + else { + ws.close(); + } + }; + this.forceClose = function (millis) { + ws.forceClose(millis); + }; + this.reconnect = function () { + ws.reconnectWs(); + }; +} +module.exports = JsonRpcClient; + +},{"../":42,"./transports/webSocketWithReconnection":41}],40:[function(require,module,exports){ +var WebSocketWithReconnection = require('./webSocketWithReconnection'); +exports.WebSocketWithReconnection = WebSocketWithReconnection; + +},{"./webSocketWithReconnection":41}],41:[function(require,module,exports){ +(function (global){ +"use strict"; +var BrowserWebSocket = global.WebSocket || global.MozWebSocket; +var Logger = console; +var MAX_RETRIES = 2000; +var RETRY_TIME_MS = 3000; +var CONNECTING = 0; +var OPEN = 1; +var CLOSING = 2; +var CLOSED = 3; +function WebSocketWithReconnection(config) { + var closing = false; + var registerMessageHandler; + var wsUri = config.uri; + var useSockJS = config.useSockJS; + var reconnecting = false; + var forcingDisconnection = false; + var ws; + if (useSockJS) { + ws = new SockJS(wsUri); + } + else { + ws = new WebSocket(wsUri); + } + ws.onopen = function () { + logConnected(ws, wsUri); + if (config.onconnected) { + config.onconnected(); + } + }; + ws.onerror = function (error) { + Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error); + if (config.onerror) { + config.onerror(error); + } + }; + function logConnected(ws, wsUri) { + try { + Logger.debug("WebSocket connected to " + wsUri); + } + catch (e) { + Logger.error(e); + } + } + var reconnectionOnClose = function () { + if (ws.readyState === CLOSED) { + if (closing) { + Logger.debug("Connection closed by user"); + } + else { + Logger.debug("Connection closed unexpectecly. Reconnecting..."); + reconnectToSameUri(MAX_RETRIES, 1); + } + } + else { + Logger.debug("Close callback from previous websocket. Ignoring it"); + } + }; + ws.onclose = reconnectionOnClose; + function reconnectToSameUri(maxRetries, numRetries) { + Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); + if (numRetries === 1) { + if (reconnecting) { + Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); + return; + } + else { + reconnecting = true; + } + if (config.onreconnecting) { + config.onreconnecting(); + } + } + if (forcingDisconnection) { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + else { + if (config.newWsUriOnReconnection) { + config.newWsUriOnReconnection(function (error, newWsUri) { + if (error) { + Logger.debug(error); + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + else { + reconnectToNewUri(maxRetries, numRetries, newWsUri); + } + }); + } + else { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + } + } + function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { + Logger.debug("Reconnection attempt #" + numRetries); + ws.close(); + wsUri = reconnectWsUri || wsUri; + var newWs; + if (useSockJS) { + newWs = new SockJS(wsUri); + } + else { + newWs = new WebSocket(wsUri); + } + newWs.onopen = function () { + Logger.debug("Reconnected after " + numRetries + " attempts..."); + logConnected(newWs, wsUri); + reconnecting = false; + registerMessageHandler(); + if (config.onreconnected()) { + config.onreconnected(); + } + newWs.onclose = reconnectionOnClose; + }; + var onErrorOrClose = function (error) { + Logger.warn("Reconnection error: ", error); + if (numRetries === maxRetries) { + if (config.ondisconnect) { + config.ondisconnect(); + } + } + else { + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + }; + newWs.onerror = onErrorOrClose; + ws = newWs; + } + this.close = function () { + closing = true; + ws.close(); + }; + this.forceClose = function (millis) { + Logger.debug("Testing: Force WebSocket close"); + if (millis) { + Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); + var goodWsUri = wsUri; + wsUri = "wss://21.234.12.34.4:443/"; + forcingDisconnection = true; + setTimeout(function () { + Logger.debug("Testing: Recover good wsUri " + goodWsUri); + wsUri = goodWsUri; + forcingDisconnection = false; + }, millis); + } + ws.close(); + }; + this.reconnectWs = function () { + Logger.debug("reconnectWs"); + reconnectToSameUri(MAX_RETRIES, 1, wsUri); + }; + this.send = function (message) { + ws.send(message); + }; + this.addEventListener = function (type, callback) { + registerMessageHandler = function () { + ws.addEventListener(type, callback); + }; + registerMessageHandler(); + }; +} +module.exports = WebSocketWithReconnection; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],42:[function(require,module,exports){ +var defineProperty_IE8 = false; +if (Object.defineProperty) { + try { + Object.defineProperty({}, "x", {}); + } + catch (e) { + defineProperty_IE8 = true; + } +} +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== 'function') { + throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); + }; + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + return fBound; + }; +} +var EventEmitter = require('events').EventEmitter; +var inherits = require('inherits'); +var packers = require('./packers'); +var Mapper = require('./Mapper'); +var BASE_TIMEOUT = 5000; +function unifyResponseMethods(responseMethods) { + if (!responseMethods) + return {}; + for (var key in responseMethods) { + var value = responseMethods[key]; + if (typeof value == 'string') + responseMethods[key] = + { + response: value + }; + } + ; + return responseMethods; +} +; +function unifyTransport(transport) { + if (!transport) + return; + if (transport instanceof Function) + return { send: transport }; + if (transport.send instanceof Function) + return transport; + if (transport.postMessage instanceof Function) { + transport.send = transport.postMessage; + return transport; + } + if (transport.write instanceof Function) { + transport.send = transport.write; + return transport; + } + if (transport.onmessage !== undefined) + return; + if (transport.pause instanceof Function) + return; + throw new SyntaxError("Transport is not a function nor a valid object"); +} +; +function RpcNotification(method, params) { + if (defineProperty_IE8) { + this.method = method; + this.params = params; + } + else { + Object.defineProperty(this, 'method', { value: method, enumerable: true }); + Object.defineProperty(this, 'params', { value: params, enumerable: true }); + } +} +; +function RpcBuilder(packer, options, transport, onRequest) { + var self = this; + if (!packer) + throw new SyntaxError('Packer is not defined'); + if (!packer.pack || !packer.unpack) + throw new SyntaxError('Packer is invalid'); + var responseMethods = unifyResponseMethods(packer.responseMethods); + if (options instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after onRequest"); + onRequest = options; + transport = undefined; + options = undefined; + } + ; + if (options && options.send instanceof Function) { + if (transport && !(transport instanceof Function)) + throw new SyntaxError("Only a function can be after transport"); + onRequest = transport; + transport = options; + options = undefined; + } + ; + if (transport instanceof Function) { + if (onRequest != undefined) + throw new SyntaxError("There can't be parameters after onRequest"); + onRequest = transport; + transport = undefined; + } + ; + if (transport && transport.send instanceof Function) + if (onRequest && !(onRequest instanceof Function)) + throw new SyntaxError("Only a function can be after transport"); + options = options || {}; + EventEmitter.call(this); + if (onRequest) + this.on('request', onRequest); + if (defineProperty_IE8) + this.peerID = options.peerID; + else + Object.defineProperty(this, 'peerID', { value: options.peerID }); + var max_retries = options.max_retries || 0; + function transportMessage(event) { + self.decode(event.data || event); + } + ; + this.getTransport = function () { + return transport; + }; + this.setTransport = function (value) { + if (transport) { + if (transport.removeEventListener) + transport.removeEventListener('message', transportMessage); + else if (transport.removeListener) + transport.removeListener('data', transportMessage); + } + ; + if (value) { + if (value.addEventListener) + value.addEventListener('message', transportMessage); + else if (value.addListener) + value.addListener('data', transportMessage); + } + ; + transport = unifyTransport(value); + }; + if (!defineProperty_IE8) + Object.defineProperty(this, 'transport', { + get: this.getTransport.bind(this), + set: this.setTransport.bind(this) + }); + this.setTransport(transport); + var request_timeout = options.request_timeout || BASE_TIMEOUT; + var ping_request_timeout = options.ping_request_timeout || request_timeout; + var response_timeout = options.response_timeout || BASE_TIMEOUT; + var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT; + var requestID = 0; + var requests = new Mapper(); + var responses = new Mapper(); + var processedResponses = new Mapper(); + var message2Key = {}; + function storeResponse(message, id, dest) { + var response = { + message: message, + timeout: setTimeout(function () { + responses.remove(id, dest); + }, response_timeout) + }; + responses.set(response, id, dest); + } + ; + function storeProcessedResponse(ack, from) { + var timeout = setTimeout(function () { + processedResponses.remove(ack, from); + }, duplicates_timeout); + processedResponses.set(timeout, ack, from); + } + ; + function RpcRequest(method, params, id, from, transport) { + RpcNotification.call(this, method, params); + this.getTransport = function () { + return transport; + }; + this.setTransport = function (value) { + transport = unifyTransport(value); + }; + if (!defineProperty_IE8) + Object.defineProperty(this, 'transport', { + get: this.getTransport.bind(this), + set: this.setTransport.bind(this) + }); + var response = responses.get(id, from); + if (!(transport || self.getTransport())) { + if (defineProperty_IE8) + this.duplicated = Boolean(response); + else + Object.defineProperty(this, 'duplicated', { + value: Boolean(response) + }); + } + var responseMethod = responseMethods[method]; + this.pack = packer.pack.bind(packer, this, id); + this.reply = function (error, result, transport) { + if (error instanceof Function || error && error.send instanceof Function) { + if (result != undefined) + throw new SyntaxError("There can't be parameters after callback"); + transport = error; + result = null; + error = undefined; + } + else if (result instanceof Function + || result && result.send instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after callback"); + transport = result; + result = null; + } + ; + transport = unifyTransport(transport); + if (response) + clearTimeout(response.timeout); + if (from != undefined) { + if (error) + error.dest = from; + if (result) + result.dest = from; + } + ; + var message; + if (error || result != undefined) { + if (self.peerID != undefined) { + if (error) + error.from = self.peerID; + else + result.from = self.peerID; + } + if (responseMethod) { + if (responseMethod.error == undefined && error) + message = + { + error: error + }; + else { + var method = error + ? responseMethod.error + : responseMethod.response; + message = + { + method: method, + params: error || result + }; + } + } + else + message = + { + error: error, + result: result + }; + message = packer.pack(message, id); + } + else if (response) + message = response.message; + else + message = packer.pack({ result: null }, id); + storeResponse(message, id, from); + transport = transport || this.getTransport() || self.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + } + ; + inherits(RpcRequest, RpcNotification); + function cancel(message) { + var key = message2Key[message]; + if (!key) + return; + delete message2Key[message]; + var request = requests.pop(key.id, key.dest); + if (!request) + return; + clearTimeout(request.timeout); + storeProcessedResponse(key.id, key.dest); + } + ; + this.cancel = function (message) { + if (message) + return cancel(message); + for (var message in message2Key) + cancel(message); + }; + this.close = function () { + var transport = this.getTransport(); + if (transport && transport.close) + transport.close(); + this.cancel(); + processedResponses.forEach(clearTimeout); + responses.forEach(function (response) { + clearTimeout(response.timeout); + }); + }; + this.encode = function (method, params, dest, transport, callback) { + if (params instanceof Function) { + if (dest != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = params; + transport = undefined; + dest = undefined; + params = undefined; + } + else if (dest instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = dest; + transport = undefined; + dest = undefined; + } + else if (transport instanceof Function) { + if (callback != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = transport; + transport = undefined; + } + ; + if (self.peerID != undefined) { + params = params || {}; + params.from = self.peerID; + } + ; + if (dest != undefined) { + params = params || {}; + params.dest = dest; + } + ; + var message = { + method: method, + params: params + }; + if (callback) { + var id = requestID++; + var retried = 0; + message = packer.pack(message, id); + function dispatchCallback(error, result) { + self.cancel(message); + callback(error, result); + } + ; + var request = { + message: message, + callback: dispatchCallback, + responseMethods: responseMethods[method] || {} + }; + var encode_transport = unifyTransport(transport); + function sendRequest(transport) { + var rt = (method === 'ping' ? ping_request_timeout : request_timeout); + request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++)); + message2Key[message] = { id: id, dest: dest }; + requests.set(request, id, dest); + transport = transport || encode_transport || self.getTransport(); + if (transport) + return transport.send(message); + return message; + } + ; + function retry(transport) { + transport = unifyTransport(transport); + console.warn(retried + ' retry for request message:', message); + var timeout = processedResponses.pop(id, dest); + clearTimeout(timeout); + return sendRequest(transport); + } + ; + function timeout() { + if (retried < max_retries) + return retry(transport); + var error = new Error('Request has timed out'); + error.request = message; + error.retry = retry; + dispatchCallback(error); + } + ; + return sendRequest(transport); + } + ; + message = packer.pack(message); + transport = transport || this.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + this.decode = function (message, transport) { + if (!message) + throw new TypeError("Message is not defined"); + try { + message = packer.unpack(message); + } + catch (e) { + return console.debug(e, message); + } + ; + var id = message.id; + var ack = message.ack; + var method = message.method; + var params = message.params || {}; + var from = params.from; + var dest = params.dest; + if (self.peerID != undefined && from == self.peerID) + return; + if (id == undefined && ack == undefined) { + var notification = new RpcNotification(method, params); + if (self.emit('request', notification)) + return; + return notification; + } + ; + function processRequest() { + transport = unifyTransport(transport) || self.getTransport(); + if (transport) { + var response = responses.get(id, from); + if (response) + return transport.send(response.message); + } + ; + var idAck = (id != undefined) ? id : ack; + var request = new RpcRequest(method, params, idAck, from, transport); + if (self.emit('request', request)) + return; + return request; + } + ; + function processResponse(request, error, result) { + request.callback(error, result); + } + ; + function duplicatedResponse(timeout) { + console.warn("Response already processed", message); + clearTimeout(timeout); + storeProcessedResponse(ack, from); + } + ; + if (method) { + if (dest == undefined || dest == self.peerID) { + var request = requests.get(ack, from); + if (request) { + var responseMethods = request.responseMethods; + if (method == responseMethods.error) + return processResponse(request, params); + if (method == responseMethods.response) + return processResponse(request, null, params); + return processRequest(); + } + var processed = processedResponses.get(ack, from); + if (processed) + return duplicatedResponse(processed); + } + return processRequest(); + } + ; + var error = message.error; + var result = message.result; + if (error && error.dest && error.dest != self.peerID) + return; + if (result && result.dest && result.dest != self.peerID) + return; + var request = requests.get(ack, from); + if (!request) { + var processed = processedResponses.get(ack, from); + if (processed) + return duplicatedResponse(processed); + return console.warn("No callback was defined for this message", message); + } + ; + processResponse(request, error, result); + }; +} +; +inherits(RpcBuilder, EventEmitter); +RpcBuilder.RpcNotification = RpcNotification; +module.exports = RpcBuilder; +var clients = require('./clients'); +var transports = require('./clients/transports'); +RpcBuilder.clients = clients; +RpcBuilder.clients.transports = transports; +RpcBuilder.packers = packers; + +},{"./Mapper":37,"./clients":38,"./clients/transports":40,"./packers":45,"events":1,"inherits":6}],43:[function(require,module,exports){ +function pack(message, id) { + var result = { + jsonrpc: "2.0" + }; + if (message.method) { + result.method = message.method; + if (message.params) + result.params = message.params; + if (id != undefined) + result.id = id; + } + else if (id != undefined) { + if (message.error) { + if (message.result !== undefined) + throw new TypeError("Both result and error are defined"); + result.error = message.error; + } + else if (message.result !== undefined) + result.result = message.result; + else + throw new TypeError("No result or error is defined"); + result.id = id; + } + ; + return JSON.stringify(result); +} +; +function unpack(message) { + var result = message; + if (typeof message === 'string' || message instanceof String) { + result = JSON.parse(message); + } + var version = result.jsonrpc; + if (version !== '2.0') + throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); + if (result.method == undefined) { + if (result.id == undefined) + throw new TypeError("Invalid message: " + message); + var result_defined = result.result !== undefined; + var error_defined = result.error !== undefined; + if (result_defined && error_defined) + throw new TypeError("Both result and error are defined: " + message); + if (!result_defined && !error_defined) + throw new TypeError("No result or error is defined: " + message); + result.ack = result.id; + delete result.id; + } + return result; +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],44:[function(require,module,exports){ +function pack(message) { + throw new TypeError("Not yet implemented"); +} +; +function unpack(message) { + throw new TypeError("Not yet implemented"); +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],45:[function(require,module,exports){ +var JsonRPC = require('./JsonRPC'); +var XmlRPC = require('./XmlRPC'); +exports.JsonRPC = JsonRPC; +exports.XmlRPC = XmlRPC; + +},{"./JsonRPC":43,"./XmlRPC":44}],46:[function(require,module,exports){ +window.getScreenId = function (callback, custom_parameter) { + if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) { + callback({ + video: true + }); + return; + } + if (!!navigator.mozGetUserMedia) { + callback(null, 'firefox', { + video: { + mozMediaSource: 'window', + mediaSource: 'window' + } + }); + return; + } + window.addEventListener('message', onIFrameCallback); + function onIFrameCallback(event) { + if (!event.data) + return; + if (event.data.chromeMediaSourceId) { + if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { + callback('permission-denied'); + } + else { + callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack)); + } + window.removeEventListener('message', onIFrameCallback); + } + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); + window.removeEventListener('message', onIFrameCallback); + } + } + if (!custom_parameter) { + setTimeout(postGetSourceIdMessage, 100); + } + else { + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); + } +}; +function getScreenConstraints(error, sourceId, canRequestAudioTrack) { + var screen_constraints = { + audio: false, + video: { + mandatory: { + chromeMediaSource: error ? 'screen' : 'desktop', + maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, + maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 + }, + optional: [] + } + }; + if (!!canRequestAudioTrack) { + screen_constraints.audio = { + mandatory: { + chromeMediaSource: error ? 'screen' : 'desktop', + }, + optional: [] + }; + } + if (sourceId) { + screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; + if (screen_constraints.audio && screen_constraints.audio.mandatory) { + screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId; + } + } + return screen_constraints; +} +function postGetSourceIdMessage(custom_parameter) { + if (!iframe) { + loadIFrame(function () { + postGetSourceIdMessage(custom_parameter); + }); + return; + } + if (!iframe.isLoaded) { + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); + return; + } + if (!custom_parameter) { + iframe.contentWindow.postMessage({ + captureSourceId: true + }, '*'); + } + else if (!!custom_parameter.forEach) { + iframe.contentWindow.postMessage({ + captureCustomSourceId: custom_parameter + }, '*'); + } + else { + iframe.contentWindow.postMessage({ + captureSourceIdWithAudio: true + }, '*'); + } +} +var iframe; +window.getScreenConstraints = function (callback) { + loadIFrame(function () { + getScreenId(function (error, sourceId, screen_constraints) { + if (!screen_constraints) { + screen_constraints = { + video: true + }; + } + callback(error, screen_constraints.video); + }); + }); +}; +function loadIFrame(loadCallback) { + if (iframe) { + loadCallback(); + return; + } + iframe = document.createElement('iframe'); + iframe.onload = function () { + iframe.isLoaded = true; + loadCallback(); + }; + iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/'; + iframe.style.display = 'none'; + (document.body || document.documentElement).appendChild(iframe); +} +window.getChromeExtensionStatus = function (callback) { + if (!!navigator.mozGetUserMedia) { + callback('installed-enabled'); + return; + } + window.addEventListener('message', onIFrameCallback); + function onIFrameCallback(event) { + if (!event.data) + return; + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus); + window.removeEventListener('message', onIFrameCallback); + } + } + setTimeout(postGetChromeExtensionStatusMessage, 100); +}; +function postGetChromeExtensionStatusMessage() { + if (!iframe) { + loadIFrame(postGetChromeExtensionStatusMessage); + return; + } + if (!iframe.isLoaded) { + setTimeout(postGetChromeExtensionStatusMessage, 100); + return; + } + iframe.contentWindow.postMessage({ + getChromeExtensionStatus: true + }, '*'); +} +exports.getScreenId = getScreenId; + +},{}],47:[function(require,module,exports){ +var chromeMediaSource = 'screen'; +var sourceId; +var screenCallback; +var isFirefox = typeof window.InstallTrigger !== 'undefined'; +var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; +var isChrome = !!window.chrome && !isOpera; +window.addEventListener('message', function (event) { + if (event.origin != window.location.origin) { + return; + } + onMessageCallback(event.data); +}); +function onMessageCallback(data) { + if (data == 'PermissionDeniedError') { + if (screenCallback) + return screenCallback('PermissionDeniedError'); + else + throw new Error('PermissionDeniedError'); + } + if (data == 'rtcmulticonnection-extension-loaded') { + chromeMediaSource = 'desktop'; + } + if (data.sourceId && screenCallback) { + screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true); + } +} +function isChromeExtensionAvailable(callback) { + if (!callback) + return; + if (chromeMediaSource == 'desktop') + return callback(true); + window.postMessage('are-you-there', '*'); + setTimeout(function () { + if (chromeMediaSource == 'screen') { + callback(false); + } + else + callback(true); + }, 2000); +} +function getSourceId(callback) { + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage('get-sourceId', '*'); +} +function getCustomSourceId(arr, callback) { + if (!arr || !arr.forEach) + throw '"arr" parameter is mandatory and it must be an array.'; + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage({ + 'get-custom-sourceId': arr + }, '*'); +} +function getSourceIdWithAudio(callback) { + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage('audio-plus-tab', '*'); +} +function getChromeExtensionStatus(extensionid, callback) { + if (isFirefox) + return callback('not-chrome'); + if (arguments.length != 2) { + callback = extensionid; + extensionid = 'lfcgfepafnobdloecchnfaclibenjold'; + } + var image = document.createElement('img'); + image.src = 'chrome-extension://' + extensionid + '/icon.png'; + image.onload = function () { + chromeMediaSource = 'screen'; + window.postMessage('are-you-there', '*'); + setTimeout(function () { + if (chromeMediaSource == 'screen') { + callback('installed-disabled'); + } + else + callback('installed-enabled'); + }, 2000); + }; + image.onerror = function () { + callback('not-installed'); + }; +} +function getScreenConstraintsWithAudio(callback) { + getScreenConstraints(callback, true); +} +function getScreenConstraints(callback, captureSourceIdWithAudio) { + sourceId = ''; + var firefoxScreenConstraints = { + mozMediaSource: 'window', + mediaSource: 'window' + }; + if (isFirefox) + return callback(null, firefoxScreenConstraints); + var screen_constraints = { + mandatory: { + chromeMediaSource: chromeMediaSource, + maxWidth: screen.width > 1920 ? screen.width : 1920, + maxHeight: screen.height > 1080 ? screen.height : 1080 + }, + optional: [] + }; + if (chromeMediaSource == 'desktop' && !sourceId) { + if (captureSourceIdWithAudio) { + getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + if (canRequestAudioTrack) { + screen_constraints.canRequestAudioTrack = true; + } + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } + else { + getSourceId(function (sourceId) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } + return; + } + if (chromeMediaSource == 'desktop') { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + } + callback(null, screen_constraints); +} +exports.getScreenConstraints = getScreenConstraints; +exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio; +exports.isChromeExtensionAvailable = isChromeExtensionAvailable; +exports.getChromeExtensionStatus = getChromeExtensionStatus; +exports.getSourceId = getSourceId; + +},{}],48:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var freeice = require("freeice"); +var uuid = require("uuid"); +var platform = require("platform"); +var WebRtcPeer = (function () { + function WebRtcPeer(configuration) { + var _this = this; + this.configuration = configuration; + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.iceCandidateList = []; + this.candidategatheringdone = false; + this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice(); + this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers }); + this.id = !!configuration.id ? configuration.id : uuid.v4(); + this.pc.onicecandidate = function (event) { + var candidate = event.candidate; + if (candidate) { + _this.localCandidatesQueue.push({ candidate: candidate.candidate }); + _this.candidategatheringdone = false; + _this.configuration.onicecandidate(event.candidate); + } + else if (!_this.candidategatheringdone) { + _this.candidategatheringdone = true; + } + }; + this.pc.onsignalingstatechange = function () { + if (_this.pc.signalingState === 'stable') { + while (_this.iceCandidateList.length > 0) { + _this.pc.addIceCandidate(_this.iceCandidateList.shift()); + } + } + }; + this.start(); + } + WebRtcPeer.prototype.start = function () { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.pc.signalingState === 'closed') { + reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); + } + if (!!_this.configuration.mediaStream) { + _this.pc.addStream(_this.configuration.mediaStream); + } + if (_this.configuration.mode === 'sendonly' && + (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) { + _this.configuration.mode = 'sendrecv'; + } + resolve(); + }); + }; + WebRtcPeer.prototype.dispose = function () { + var _this = this; + console.debug('Disposing WebRtcPeer'); + try { + if (this.pc) { + if (this.pc.signalingState === 'closed') { + return; + } + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.pc.getLocalStreams().forEach(function (str) { + _this.streamStop(str); + }); + this.pc.close(); + } + } + catch (err) { + console.warn('Exception disposing webrtc peer ' + err); + } + }; + WebRtcPeer.prototype.generateOffer = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var offerAudio, offerVideo = true; + if (!!_this.configuration.mediaConstraints) { + offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ? + _this.configuration.mediaConstraints.audio : true; + offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ? + _this.configuration.mediaConstraints.video : true; + } + var constraints = { + offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio), + offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo) + }; + console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints)); + _this.pc.createOffer(constraints).then(function (offer) { + console.debug('Created SDP offer'); + return _this.pc.setLocalDescription(offer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.processOffer = function (sdpOffer) { + var _this = this; + return new Promise(function (resolve, reject) { + var offer = { + type: 'offer', + sdp: sdpOffer + }; + console.debug('SDP offer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('PeerConnection is closed'); + } + _this.pc.setRemoteDescription(offer) + .then(function () { + return _this.pc.createAnswer(); + }).then(function (answer) { + console.debug('Created SDP answer'); + return _this.pc.setLocalDescription(answer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.processAnswer = function (sdpAnswer) { + var _this = this; + return new Promise(function (resolve, reject) { + var answer = { + type: 'answer', + sdp: sdpAnswer + }; + console.debug('SDP answer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('RTCPeerConnection is closed'); + } + _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) { + var _this = this; + return new Promise(function (resolve, reject) { + console.debug('Remote ICE candidate received', iceCandidate); + _this.remoteCandidatesQueue.push(iceCandidate); + switch (_this.pc.signalingState) { + case 'closed': + reject(new Error('PeerConnection object is closed')); + break; + case 'stable': + if (!!_this.pc.remoteDescription) { + _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); }); + } + break; + default: + _this.iceCandidateList.push(iceCandidate); + resolve(); + } + }); + }; + WebRtcPeer.prototype.streamStop = function (stream) { + stream.getTracks().forEach(function (track) { + track.stop(); + stream.removeTrack(track); + }); + }; + return WebRtcPeer; +}()); +exports.WebRtcPeer = WebRtcPeer; +var WebRtcPeerRecvonly = (function (_super) { + __extends(WebRtcPeerRecvonly, _super); + function WebRtcPeerRecvonly(configuration) { + var _this = this; + configuration.mode = 'recvonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerRecvonly; +}(WebRtcPeer)); +exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; +var WebRtcPeerSendonly = (function (_super) { + __extends(WebRtcPeerSendonly, _super); + function WebRtcPeerSendonly(configuration) { + var _this = this; + configuration.mode = 'sendonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendonly; +}(WebRtcPeer)); +exports.WebRtcPeerSendonly = WebRtcPeerSendonly; +var WebRtcPeerSendrecv = (function (_super) { + __extends(WebRtcPeerSendrecv, _super); + function WebRtcPeerSendrecv(configuration) { + var _this = this; + configuration.mode = 'sendrecv'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendrecv; +}(WebRtcPeer)); +exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; + +},{"freeice":2,"platform":8,"uuid":9}],49:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var platform = require("platform"); +var WebRtcStats = (function () { + function WebRtcStats(stream) { + this.stream = stream; + this.webRtcStatsEnabled = false; + this.statsInterval = 1; + this.stats = { + inbound: { + audio: { + bytesReceived: 0, + packetsReceived: 0, + packetsLost: 0 + }, + video: { + bytesReceived: 0, + packetsReceived: 0, + packetsLost: 0, + framesDecoded: 0, + nackCount: 0 + } + }, + outbound: { + audio: { + bytesSent: 0, + packetsSent: 0, + }, + video: { + bytesSent: 0, + packetsSent: 0, + framesEncoded: 0, + nackCount: 0 + } + } + }; + } + WebRtcStats.prototype.isEnabled = function () { + return this.webRtcStatsEnabled; + }; + WebRtcStats.prototype.initWebRtcStats = function () { + var _this = this; + var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); + if (elastestInstrumentation) { + console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); + this.webRtcStatsEnabled = true; + var instrumentation_1 = JSON.parse(elastestInstrumentation); + this.statsInterval = instrumentation_1.webrtc.interval; + console.warn('localStorage item: ' + JSON.stringify(instrumentation_1)); + this.webRtcStatsIntervalId = setInterval(function () { + _this.sendStatsToHttpEndpoint(instrumentation_1); + }, this.statsInterval * 1000); + return; + } + console.debug('WebRtc stats not enabled'); + }; + WebRtcStats.prototype.stopWebRtcStats = function () { + if (this.webRtcStatsEnabled) { + clearInterval(this.webRtcStatsIntervalId); + console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); + } + }; + WebRtcStats.prototype.getSelectedIceCandidateInfo = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) { + if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0; + var localCandidates = {}; + var remoteCandidates = {}; + for (var key in stats) { + var stat = stats[key]; + if (stat.type === 'localcandidate') { + localCandidates[stat.id] = stat; + } + else if (stat.type === 'remotecandidate') { + remoteCandidates[stat.id] = stat; + } + else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) { + googCandidatePair = stat; + localCandidateId = stat.localCandidateId; + remoteCandidateId = stat.remoteCandidateId; + } + } + var finalLocalCandidate_1 = localCandidates[localCandidateId]; + if (!!finalLocalCandidate_1) { + var candList = _this.stream.getLocalIceCandidateList(); + var cand = candList.filter(function (c) { + return (!!c.candidate && + c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 && + c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 && + c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0); + }); + finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates'; + } + else { + finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used'; + } + var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId]; + if (!!finalRemoteCandidate_1) { + var candList = _this.stream.getRemoteIceCandidateList(); + var cand = candList.filter(function (c) { + return (!!c.candidate && + c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 && + c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 && + c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0); + }); + finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates'; + } + else { + finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used'; + } + resolve({ + googCandidatePair: googCandidatePair, + localCandidate: finalLocalCandidate_1, + remoteCandidate: finalRemoteCandidate_1 + }); + } + else { + reject('Selected ICE candidate info only available for Chrome'); + } + }, function (error) { + reject(error); + }); + }); + }; + WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { + var _this = this; + var sendPost = function (json) { + var http = new XMLHttpRequest(); + var url = instrumentation.webrtc.httpEndpoint; + http.open('POST', url, true); + http.setRequestHeader('Content-type', 'application/json'); + http.onreadystatechange = function () { + if (http.readyState === 4 && http.status === 200) { + console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId); + } + }; + http.send(json); + }; + var f = function (stats) { + if (platform.name.indexOf('Firefox') !== -1) { + stats.forEach(function (stat) { + var json = {}; + if ((stat.type === 'inbound-rtp') && + (stat.nackCount !== null && + stat.isRemote === false && + stat.id.startsWith('inbound') && + stat.remoteId.startsWith('inbound'))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var jit = stat.jitter * 1000; + var metrics = { + bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + jitter: jit, + packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + bytesReceived: 'bytes', + jitter: 'ms', + packetsReceived: 'packets', + packetsLost: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = 'frames'; + units['nackCount'] = 'packets'; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.nackCount; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ((stat.type === 'outbound-rtp') && + (stat.isRemote === false && + stat.id.toLowerCase().includes('outbound'))) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + bytesSent: 'bytes', + packetsSent: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = 'frames'; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + }); + } + else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { + var key = _a[_i]; + var stat = stats[key]; + if (stat.type === 'ssrc') { + var json = {}; + if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || + (stat.mediaType === 'video' && 'qpSum' in stat))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + jitter: stat.googJitterBufferMs, + packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + bytesReceived: 'bytes', + jitter: 'ms', + packetsReceived: 'packets', + packetsLost: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = 'frames'; + units['nackCount'] = 'packets'; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.googNacksSent; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ('bytesSent' in stat) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + bytesSent: 'bytes', + packetsSent: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = 'frames'; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + } + } + } + }; + this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); }); + }; + WebRtcStats.prototype.standardizeReport = function (response) { + console.log(response); + var standardReport = {}; + if (platform.name.indexOf('Firefox') !== -1) { + Object.keys(response).forEach(function (key) { + console.log(response[key]); + }); + return response; + } + response.result().forEach(function (report) { + var standardStats = { + id: report.id, + timestamp: report.timestamp, + type: report.type + }; + report.names().forEach(function (name) { + standardStats[name] = report.stat(name); + }); + standardReport[standardStats.id] = standardStats; + }); + return standardReport; + }; + WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) { + var _this = this; + if (platform.name.indexOf('Firefox') !== -1) { + return pc.getStats(null).then(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }).catch(failureCb); + } + else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + return pc.getStats(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }, null, failureCb); + } + }; + return WebRtcStats; +}()); +exports.WebRtcStats = WebRtcStats; + +},{"platform":8}]},{},[16]) +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9NYXBwZXIuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvSnNvblJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL1htbFJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmctQXV0by5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNQZWVyL1dlYlJ0Y1BlZXIudHMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1N0YXRzL1dlYlJ0Y1N0YXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzZ0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3RlQSxnREFBK0M7QUFFL0MsSUFBSSxNQUFNLEVBQUU7SUFFUixNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsbUJBQVEsQ0FBQztDQUNqQzs7Ozs7QUNhRCxtQ0FBa0M7QUFV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LEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztTQUN2QjtJQUNMLENBQUM7SUFFTCxrQkFBQztBQUFELENBcllBLEFBcVlDLElBQUE7QUFyWVksa0NBQVciLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLyohXG4gKiBQbGF0Zm9ybS5qcyA8aHR0cHM6Ly9tdGhzLmJlL3BsYXRmb3JtPlxuICogQ29weXJpZ2h0IDIwMTQtMjAxOCBCZW5qYW1pbiBUYW4gPGh0dHBzOi8vYm5qbW50NG4ubm93LnNoLz5cbiAqIENvcHlyaWdodCAyMDExLTIwMTMgSm9obi1EYXZpZCBEYWx0b24gPGh0dHA6Ly9hbGx5b3VjYW5sZWV0LmNvbS8+XG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbXRocy5iZS9taXQ+XG4gKi9cbjsoZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBCYWNrdXAgcG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIG9sZFJvb3QgPSByb290O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcyBvciBCcm93c2VyaWZpZWQgY29kZSBhbmQgdXNlIGl0IGFzIGByb290YC4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSBmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlICYmIHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSkge1xuICAgIHJvb3QgPSBmcmVlR2xvYmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgdGhlIG1heGltdW0gbGVuZ3RoIG9mIGFuIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgKiBTZWUgdGhlIFtFUzYgc3BlY10oaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGgpXG4gICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAqL1xuICB2YXIgbWF4U2FmZUludGVnZXIgPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuXG4gIC8qKiBSZWd1bGFyIGV4cHJlc3Npb24gdG8gZGV0ZWN0IE9wZXJhLiAqL1xuICB2YXIgcmVPcGVyYSA9IC9cXGJPcGVyYS87XG5cbiAgLyoqIFBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciB0aGlzQmluZGluZyA9IHRoaXM7XG5cbiAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAvKiogVXNlZCB0byBjaGVjayBmb3Igb3duIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LiAqL1xuICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiB2YWx1ZXMuICovXG4gIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDYXBpdGFsaXplcyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgIHN0cmluZyA9IFN0cmluZyhzdHJpbmcpO1xuICAgIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG4gIH1cblxuICAvKipcbiAgICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGNsZWFuIHVwIHRoZSBPUyBuYW1lLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3MgVGhlIE9TIG5hbWUgdG8gY2xlYW4gdXAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVybl0gQSBgUmVnRXhwYCBwYXR0ZXJuIG1hdGNoaW5nIHRoZSBPUyBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhYmVsXSBBIGxhYmVsIGZvciB0aGUgT1MuXG4gICAqL1xuICBmdW5jdGlvbiBjbGVhbnVwT1Mob3MsIHBhdHRlcm4sIGxhYmVsKSB7XG4gICAgLy8gUGxhdGZvcm0gdG9rZW5zIGFyZSBkZWZpbmVkIGF0OlxuICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIC8vIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDgxMTIyMDUzOTUwL2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIHZhciBkYXRhID0ge1xuICAgICAgJzEwLjAnOiAnMTAnLFxuICAgICAgJzYuNCc6ICAnMTAgVGVjaG5pY2FsIFByZXZpZXcnLFxuICAgICAgJzYuMyc6ICAnOC4xJyxcbiAgICAgICc2LjInOiAgJzgnLFxuICAgICAgJzYuMSc6ICAnU2VydmVyIDIwMDggUjIgLyA3JyxcbiAgICAgICc2LjAnOiAgJ1NlcnZlciAyMDA4IC8gVmlzdGEnLFxuICAgICAgJzUuMic6ICAnU2VydmVyIDIwMDMgLyBYUCA2NC1iaXQnLFxuICAgICAgJzUuMSc6ICAnWFAnLFxuICAgICAgJzUuMDEnOiAnMjAwMCBTUDEnLFxuICAgICAgJzUuMCc6ICAnMjAwMCcsXG4gICAgICAnNC4wJzogICdOVCcsXG4gICAgICAnNC45MCc6ICdNRSdcbiAgICB9O1xuICAgIC8vIERldGVjdCBXaW5kb3dzIHZlcnNpb24gZnJvbSBwbGF0Zm9ybSB0b2tlbnMuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwgJiYgL15XaW4vaS50ZXN0KG9zKSAmJiAhL15XaW5kb3dzIFBob25lIC9pLnRlc3Qob3MpICYmXG4gICAgICAgIChkYXRhID0gZGF0YVsvW1xcZC5dKyQvLmV4ZWMob3MpXSkpIHtcbiAgICAgIG9zID0gJ1dpbmRvd3MgJyArIGRhdGE7XG4gICAgfVxuICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgIG9zID0gU3RyaW5nKG9zKTtcblxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGxhYmVsKTtcbiAgICB9XG5cbiAgICBvcyA9IGZvcm1hdChcbiAgICAgIG9zLnJlcGxhY2UoLyBjZSQvaSwgJyBDRScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJocHcvaSwgJ3dlYicpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWNpbnRvc2hcXGIvLCAnTWFjIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL19Qb3dlclBDXFxiL2ksICcgT1MnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKE9TIFgpIFteIFxcZF0rL2ksICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWMgKE9TIFgpXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyhcXGQpLywgJyAkMScpXG4gICAgICAgIC5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgLnJlcGxhY2UoLyg/OiBCZVBDfFsgLl0qZmNbIFxcZC5dKykkL2ksICcnKVxuICAgICAgICAucmVwbGFjZSgvXFxieDg2XFwuNjRcXGIvZ2ksICd4ODZfNjQnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKFdpbmRvd3MgUGhvbmUpIE9TXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihDaHJvbWUgT1MgXFx3KykgW1xcZC5dK1xcYi8sICckMScpXG4gICAgICAgIC5zcGxpdCgnIG9uICcpWzBdXG4gICAgKTtcblxuICAgIHJldHVybiBvcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpdGVyYXRpb24gdXRpbGl0eSBmb3IgYXJyYXlzIGFuZCBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBlYWNoKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gb2JqZWN0ID8gb2JqZWN0Lmxlbmd0aCA6IDA7XG5cbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPiAtMSAmJiBsZW5ndGggPD0gbWF4U2FmZUludGVnZXIpIHtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtpbmRleF0sIGluZGV4LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3JPd24ob2JqZWN0LCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaW0gYW5kIGNvbmRpdGlvbmFsbHkgY2FwaXRhbGl6ZSBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGZvcm1hdChzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSB0cmltKHN0cmluZyk7XG4gICAgcmV0dXJuIC9eKD86d2ViT1N8aSg/Ok9TfFApKS8udGVzdChzdHJpbmcpXG4gICAgICA/IHN0cmluZ1xuICAgICAgOiBjYXBpdGFsaXplKHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZXMgb3ZlciBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgZXhlY3V0aW5nIHRoZSBgY2FsbGJhY2tgIGZvciBlYWNoLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gZXhlY3V0ZWQgcGVyIG93biBwcm9wZXJ0eS5cbiAgICovXG4gIGZ1bmN0aW9uIGZvck93bihvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtrZXldLCBrZXksIG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIGEgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYFtbQ2xhc3NdXWAuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRDbGFzc09mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGxcbiAgICAgID8gY2FwaXRhbGl6ZSh2YWx1ZSlcbiAgICAgIDogdG9TdHJpbmcuY2FsbCh2YWx1ZSkuc2xpY2UoOCwgLTEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvc3Qgb2JqZWN0cyBjYW4gcmV0dXJuIHR5cGUgdmFsdWVzIHRoYXQgYXJlIGRpZmZlcmVudCBmcm9tIHRoZWlyIGFjdHVhbFxuICAgKiBkYXRhIHR5cGUuIFRoZSBvYmplY3RzIHdlIGFyZSBjb25jZXJuZWQgd2l0aCB1c3VhbGx5IHJldHVybiBub24tcHJpbWl0aXZlXG4gICAqIHR5cGVzIG9mIFwib2JqZWN0XCIsIFwiZnVuY3Rpb25cIiwgb3IgXCJ1bmtub3duXCIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBvd25lciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgYSBub24tcHJpbWl0aXZlLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RUeXBlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICB2YXIgdHlwZSA9IG9iamVjdCAhPSBudWxsID8gdHlwZW9mIG9iamVjdFtwcm9wZXJ0eV0gOiAnbnVtYmVyJztcbiAgICByZXR1cm4gIS9eKD86Ym9vbGVhbnxudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZCkkLy50ZXN0KHR5cGUpICYmXG4gICAgICAodHlwZSA9PSAnb2JqZWN0JyA/ICEhb2JqZWN0W3Byb3BlcnR5XSA6IHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmVzIGEgc3RyaW5nIGZvciB1c2UgaW4gYSBgUmVnRXhwYCBieSBtYWtpbmcgaHlwaGVucyBhbmQgc3BhY2VzIG9wdGlvbmFsLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcXVhbGlmeS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBxdWFsaWZ5KHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC8oWyAtXSkoPyEkKS9nLCAnJDE/Jyk7XG4gIH1cblxuICAvKipcbiAgICogQSBiYXJlLWJvbmVzIGBBcnJheSNyZWR1Y2VgIGxpa2UgdXRpbGl0eSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Kn0gVGhlIGFjY3VtdWxhdGVkIHJlc3VsdC5cbiAgICovXG4gIGZ1bmN0aW9uIHJlZHVjZShhcnJheSwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWNjdW11bGF0b3IgPSBudWxsO1xuICAgIGVhY2goYXJyYXksIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBhcnJheSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvXiArfCArJC9nLCAnJyk7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbGF0Zm9ybSBvYmplY3QuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgKiBAcGFyYW0ge09iamVjdHxzdHJpbmd9IFt1YT1uYXZpZ2F0b3IudXNlckFnZW50XSBUaGUgdXNlciBhZ2VudCBzdHJpbmcgb3JcbiAgICogIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBIHBsYXRmb3JtIG9iamVjdC5cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlKHVhKSB7XG5cbiAgICAvKiogVGhlIGVudmlyb25tZW50IGNvbnRleHQgb2JqZWN0LiAqL1xuICAgIHZhciBjb250ZXh0ID0gcm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBhIGN1c3RvbSBjb250ZXh0IGlzIHByb3ZpZGVkLiAqL1xuICAgIHZhciBpc0N1c3RvbUNvbnRleHQgPSB1YSAmJiB0eXBlb2YgdWEgPT0gJ29iamVjdCcgJiYgZ2V0Q2xhc3NPZih1YSkgIT0gJ1N0cmluZyc7XG5cbiAgICAvLyBKdWdnbGUgYXJndW1lbnRzLlxuICAgIGlmIChpc0N1c3RvbUNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB1YTtcbiAgICAgIHVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKiogQnJvd3NlciBuYXZpZ2F0b3Igb2JqZWN0LiAqL1xuICAgIHZhciBuYXYgPSBjb250ZXh0Lm5hdmlnYXRvciB8fCB7fTtcblxuICAgIC8qKiBCcm93c2VyIHVzZXIgYWdlbnQgc3RyaW5nLiAqL1xuICAgIHZhciB1c2VyQWdlbnQgPSBuYXYudXNlckFnZW50IHx8ICcnO1xuXG4gICAgdWEgfHwgKHVhID0gdXNlckFnZW50KTtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBgdGhpc0JpbmRpbmdgIGlzIHRoZSBbTW9kdWxlU2NvcGVdLiAqL1xuICAgIHZhciBpc01vZHVsZVNjb3BlID0gaXNDdXN0b21Db250ZXh0IHx8IHRoaXNCaW5kaW5nID09IG9sZFJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYnJvd3NlciBpcyBsaWtlIENocm9tZS4gKi9cbiAgICB2YXIgbGlrZUNocm9tZSA9IGlzQ3VzdG9tQ29udGV4dFxuICAgICAgPyAhIW5hdi5saWtlQ2hyb21lXG4gICAgICA6IC9cXGJDaHJvbWVcXGIvLnRlc3QodWEpICYmICEvaW50ZXJuYWx8XFxuL2kudGVzdCh0b1N0cmluZy50b1N0cmluZygpKTtcblxuICAgIC8qKiBJbnRlcm5hbCBgW1tDbGFzc11dYCB2YWx1ZSBzaG9ydGN1dHMuICovXG4gICAgdmFyIG9iamVjdENsYXNzID0gJ09iamVjdCcsXG4gICAgICAgIGFpclJ1bnRpbWVDbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1NjcmlwdEJyaWRnaW5nUHJveHlPYmplY3QnLFxuICAgICAgICBlbnZpcm9DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ0Vudmlyb25tZW50JyxcbiAgICAgICAgamF2YUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBjb250ZXh0LmphdmEpID8gJ0phdmFQYWNrYWdlJyA6IGdldENsYXNzT2YoY29udGV4dC5qYXZhKSxcbiAgICAgICAgcGhhbnRvbUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnUnVudGltZU9iamVjdCc7XG5cbiAgICAvKiogRGV0ZWN0IEphdmEgZW52aXJvbm1lbnRzLiAqL1xuICAgIHZhciBqYXZhID0gL1xcYkphdmEvLnRlc3QoamF2YUNsYXNzKSAmJiBjb250ZXh0LmphdmE7XG5cbiAgICAvKiogRGV0ZWN0IFJoaW5vLiAqL1xuICAgIHZhciByaGlubyA9IGphdmEgJiYgZ2V0Q2xhc3NPZihjb250ZXh0LmVudmlyb25tZW50KSA9PSBlbnZpcm9DbGFzcztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYWxwaGEuICovXG4gICAgdmFyIGFscGhhID0gamF2YSA/ICdhJyA6ICdcXHUwM2IxJztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYmV0YS4gKi9cbiAgICB2YXIgYmV0YSA9IGphdmEgPyAnYicgOiAnXFx1MDNiMic7XG5cbiAgICAvKiogQnJvd3NlciBkb2N1bWVudCBvYmplY3QuICovXG4gICAgdmFyIGRvYyA9IGNvbnRleHQuZG9jdW1lbnQgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgT3BlcmEgYnJvd3NlciAoUHJlc3RvLWJhc2VkKS5cbiAgICAgKiBodHRwOi8vd3d3Lmhvd3RvY3JlYXRlLmNvLnVrL29wZXJhU3R1ZmYvb3BlcmFPYmplY3QuaHRtbFxuICAgICAqIGh0dHA6Ly9kZXYub3BlcmEuY29tL2FydGljbGVzL3ZpZXcvb3BlcmEtbWluaS13ZWItY29udGVudC1hdXRob3JpbmctZ3VpZGVsaW5lcy8jb3BlcmFtaW5pXG4gICAgICovXG4gICAgdmFyIG9wZXJhID0gY29udGV4dC5vcGVyYW1pbmkgfHwgY29udGV4dC5vcGVyYTtcblxuICAgIC8qKiBPcGVyYSBgW1tDbGFzc11dYC4gKi9cbiAgICB2YXIgb3BlcmFDbGFzcyA9IHJlT3BlcmEudGVzdChvcGVyYUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBvcGVyYSkgPyBvcGVyYVsnW1tDbGFzc11dJ10gOiBnZXRDbGFzc09mKG9wZXJhKSlcbiAgICAgID8gb3BlcmFDbGFzc1xuICAgICAgOiAob3BlcmEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKiBUZW1wb3JhcnkgdmFyaWFibGUgdXNlZCBvdmVyIHRoZSBzY3JpcHQncyBsaWZldGltZS4gKi9cbiAgICB2YXIgZGF0YTtcblxuICAgIC8qKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZS4gKi9cbiAgICB2YXIgYXJjaCA9IHVhO1xuXG4gICAgLyoqIFBsYXRmb3JtIGRlc2NyaXB0aW9uIGFycmF5LiAqL1xuICAgIHZhciBkZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgLyoqIFBsYXRmb3JtIGFscGhhL2JldGEgaW5kaWNhdG9yLiAqL1xuICAgIHZhciBwcmVyZWxlYXNlID0gbnVsbDtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgdGhhdCBlbnZpcm9ubWVudCBmZWF0dXJlcyBzaG91bGQgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwbGF0Zm9ybS4gKi9cbiAgICB2YXIgdXNlRmVhdHVyZXMgPSB1YSA9PSB1c2VyQWdlbnQ7XG5cbiAgICAvKiogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi4gKi9cbiAgICB2YXIgdmVyc2lvbiA9IHVzZUZlYXR1cmVzICYmIG9wZXJhICYmIHR5cGVvZiBvcGVyYS52ZXJzaW9uID09ICdmdW5jdGlvbicgJiYgb3BlcmEudmVyc2lvbigpO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgT1MgZW5kcyB3aXRoIFwiLyBWZXJzaW9uXCIgKi9cbiAgICB2YXIgaXNTcGVjaWFsQ2FzZWRPUztcblxuICAgIC8qIERldGVjdGFibGUgbGF5b3V0IGVuZ2luZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIGxheW91dCA9IGdldExheW91dChbXG4gICAgICB7ICdsYWJlbCc6ICdFZGdlSFRNTCcsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnVHJpZGVudCcsXG4gICAgICB7ICdsYWJlbCc6ICdXZWJLaXQnLCAncGF0dGVybic6ICdBcHBsZVdlYktpdCcgfSxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdQcmVzdG8nLFxuICAgICAgJ05ldEZyb250JyxcbiAgICAgICdUYXNtYW4nLFxuICAgICAgJ0tIVE1MJyxcbiAgICAgICdHZWNrbydcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgYnJvd3NlciBuYW1lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbmFtZSA9IGdldE5hbWUoW1xuICAgICAgJ0Fkb2JlIEFJUicsXG4gICAgICAnQXJvcmEnLFxuICAgICAgJ0F2YW50IEJyb3dzZXInLFxuICAgICAgJ0JyZWFjaCcsXG4gICAgICAnQ2FtaW5vJyxcbiAgICAgICdFbGVjdHJvbicsXG4gICAgICAnRXBpcGhhbnknLFxuICAgICAgJ0Zlbm5lYycsXG4gICAgICAnRmxvY2snLFxuICAgICAgJ0dhbGVvbicsXG4gICAgICAnR3JlZW5Ccm93c2VyJyxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdJY2V3ZWFzZWwnLFxuICAgICAgJ0stTWVsZW9uJyxcbiAgICAgICdLb25xdWVyb3InLFxuICAgICAgJ0x1bmFzY2FwZScsXG4gICAgICAnTWF4dGhvbicsXG4gICAgICB7ICdsYWJlbCc6ICdNaWNyb3NvZnQgRWRnZScsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnTWlkb3JpJyxcbiAgICAgICdOb29rIEJyb3dzZXInLFxuICAgICAgJ1BhbGVNb29uJyxcbiAgICAgICdQaGFudG9tSlMnLFxuICAgICAgJ1JhdmVuJyxcbiAgICAgICdSZWtvbnEnLFxuICAgICAgJ1JvY2tNZWx0JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NhbXN1bmcgSW50ZXJuZXQnLCAncGF0dGVybic6ICdTYW1zdW5nQnJvd3NlcicgfSxcbiAgICAgICdTZWFNb25rZXknLFxuICAgICAgeyAnbGFiZWwnOiAnU2lsaycsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdTbGVpcG5pcicsXG4gICAgICAnU2xpbUJyb3dzZXInLFxuICAgICAgeyAnbGFiZWwnOiAnU1JXYXJlIElyb24nLCAncGF0dGVybic6ICdJcm9uJyB9LFxuICAgICAgJ1N1bnJpc2UnLFxuICAgICAgJ1N3aWZ0Zm94JyxcbiAgICAgICdXYXRlcmZveCcsXG4gICAgICAnV2ViUG9zaXRpdmUnLFxuICAgICAgJ09wZXJhIE1pbmknLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEgTWluaScsICdwYXR0ZXJuJzogJ09QaU9TJyB9LFxuICAgICAgJ09wZXJhJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhJywgJ3BhdHRlcm4nOiAnT1BSJyB9LFxuICAgICAgJ0Nocm9tZScsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgTW9iaWxlJywgJ3BhdHRlcm4nOiAnKD86Q3JpT1N8Q3JNbyknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94JywgJ3BhdHRlcm4nOiAnKD86RmlyZWZveHxNaW5lZmllbGQpJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCBmb3IgaU9TJywgJ3BhdHRlcm4nOiAnRnhpT1MnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ0lFTW9iaWxlJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdNU0lFJyB9LFxuICAgICAgJ1NhZmFyaSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgcHJvZHVjdHMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0JsYWNrQmVycnknLCAncGF0dGVybic6ICdCQjEwJyB9LFxuICAgICAgJ0JsYWNrQmVycnknLFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMnLCAncGF0dGVybic6ICdHVC1JOTAwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMicsICdwYXR0ZXJuJzogJ0dULUk5MTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMzJywgJ3BhdHRlcm4nOiAnR1QtSTkzMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzQnLCAncGF0dGVybic6ICdHVC1JOTUwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNScsICdwYXR0ZXJuJzogJ1NNLUc5MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYnLCAncGF0dGVybic6ICdTTS1HOTIwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTI1JyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3JywgJ3BhdHRlcm4nOiAnU00tRzkzMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNyBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkzNScgfSxcbiAgICAgICdHb29nbGUgVFYnLFxuICAgICAgJ0x1bWlhJyxcbiAgICAgICdpUGFkJyxcbiAgICAgICdpUG9kJyxcbiAgICAgICdpUGhvbmUnLFxuICAgICAgJ0tpbmRsZScsXG4gICAgICB7ICdsYWJlbCc6ICdLaW5kbGUgRmlyZScsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdOZXh1cycsXG4gICAgICAnTm9vaycsXG4gICAgICAnUGxheUJvb2snLFxuICAgICAgJ1BsYXlTdGF0aW9uIFZpdGEnLFxuICAgICAgJ1BsYXlTdGF0aW9uJyxcbiAgICAgICdUb3VjaFBhZCcsXG4gICAgICAnVHJhbnNmb3JtZXInLFxuICAgICAgeyAnbGFiZWwnOiAnV2lpIFUnLCAncGF0dGVybic6ICdXaWlVJyB9LFxuICAgICAgJ1dpaScsXG4gICAgICAnWGJveCBPbmUnLFxuICAgICAgeyAnbGFiZWwnOiAnWGJveCAzNjAnLCAncGF0dGVybic6ICdYYm94JyB9LFxuICAgICAgJ1hvb20nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG1hbnVmYWN0dXJlcnMuICovXG4gICAgdmFyIG1hbnVmYWN0dXJlciA9IGdldE1hbnVmYWN0dXJlcih7XG4gICAgICAnQXBwbGUnOiB7ICdpUGFkJzogMSwgJ2lQaG9uZSc6IDEsICdpUG9kJzogMSB9LFxuICAgICAgJ0FyY2hvcyc6IHt9LFxuICAgICAgJ0FtYXpvbic6IHsgJ0tpbmRsZSc6IDEsICdLaW5kbGUgRmlyZSc6IDEgfSxcbiAgICAgICdBc3VzJzogeyAnVHJhbnNmb3JtZXInOiAxIH0sXG4gICAgICAnQmFybmVzICYgTm9ibGUnOiB7ICdOb29rJzogMSB9LFxuICAgICAgJ0JsYWNrQmVycnknOiB7ICdQbGF5Qm9vayc6IDEgfSxcbiAgICAgICdHb29nbGUnOiB7ICdHb29nbGUgVFYnOiAxLCAnTmV4dXMnOiAxIH0sXG4gICAgICAnSFAnOiB7ICdUb3VjaFBhZCc6IDEgfSxcbiAgICAgICdIVEMnOiB7fSxcbiAgICAgICdMRyc6IHt9LFxuICAgICAgJ01pY3Jvc29mdCc6IHsgJ1hib3gnOiAxLCAnWGJveCBPbmUnOiAxIH0sXG4gICAgICAnTW90b3JvbGEnOiB7ICdYb29tJzogMSB9LFxuICAgICAgJ05pbnRlbmRvJzogeyAnV2lpIFUnOiAxLCAgJ1dpaSc6IDEgfSxcbiAgICAgICdOb2tpYSc6IHsgJ0x1bWlhJzogMSB9LFxuICAgICAgJ1NhbXN1bmcnOiB7ICdHYWxheHkgUyc6IDEsICdHYWxheHkgUzInOiAxLCAnR2FsYXh5IFMzJzogMSwgJ0dhbGF4eSBTNCc6IDEgfSxcbiAgICAgICdTb255JzogeyAnUGxheVN0YXRpb24nOiAxLCAnUGxheVN0YXRpb24gVml0YSc6IDEgfVxuICAgIH0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBvcGVyYXRpbmcgc3lzdGVtcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgb3MgPSBnZXRPUyhbXG4gICAgICAnV2luZG93cyBQaG9uZScsXG4gICAgICAnQW5kcm9pZCcsXG4gICAgICAnQ2VudE9TJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBPUycsICdwYXR0ZXJuJzogJ0NyT1MnIH0sXG4gICAgICAnRGViaWFuJyxcbiAgICAgICdGZWRvcmEnLFxuICAgICAgJ0ZyZWVCU0QnLFxuICAgICAgJ0dlbnRvbycsXG4gICAgICAnSGFpa3UnLFxuICAgICAgJ0t1YnVudHUnLFxuICAgICAgJ0xpbnV4IE1pbnQnLFxuICAgICAgJ09wZW5CU0QnLFxuICAgICAgJ1JlZCBIYXQnLFxuICAgICAgJ1N1U0UnLFxuICAgICAgJ1VidW50dScsXG4gICAgICAnWHVidW50dScsXG4gICAgICAnQ3lnd2luJyxcbiAgICAgICdTeW1iaWFuIE9TJyxcbiAgICAgICdocHdPUycsXG4gICAgICAnd2ViT1MgJyxcbiAgICAgICd3ZWJPUycsXG4gICAgICAnVGFibGV0IE9TJyxcbiAgICAgICdUaXplbicsXG4gICAgICAnTGludXgnLFxuICAgICAgJ01hYyBPUyBYJyxcbiAgICAgICdNYWNpbnRvc2gnLFxuICAgICAgJ01hYycsXG4gICAgICAnV2luZG93cyA5ODsnLFxuICAgICAgJ1dpbmRvd3MgJ1xuICAgIF0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGxheW91dCBlbmdpbmUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbGF5b3V0IGVuZ2luZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMYXlvdXQoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIG1hbnVmYWN0dXJlciBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gb2JqZWN0IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbWFudWZhY3R1cmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlcihndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgICAvLyBMb29rdXAgdGhlIG1hbnVmYWN0dXJlciBieSBwcm9kdWN0IG9yIHNjYW4gdGhlIFVBIGZvciB0aGUgbWFudWZhY3R1cmVyLlxuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChcbiAgICAgICAgICB2YWx1ZVtwcm9kdWN0XSB8fFxuICAgICAgICAgIHZhbHVlWy9eW2Etel0rKD86ICtbYS16XStcXGIpKi9pLmV4ZWMocHJvZHVjdCldIHx8XG4gICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBxdWFsaWZ5KGtleSkgKyAnKD86XFxcXGJ8XFxcXHcqXFxcXGQpJywgJ2knKS5leGVjKHVhKVxuICAgICAgICApICYmIGtleTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBicm93c2VyIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgYnJvd3NlciBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hbWUoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIE9TIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgT1MgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRPUyhndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/Oi9bXFxcXGQuXSt8WyBcXFxcdy5dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xlYW51cE9TKHJlc3VsdCwgcGF0dGVybiwgZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgcHJvZHVjdCBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHByb2R1Y3QgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRQcm9kdWN0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcZCtbLlxcXFx3X10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcdystW1xcXFx3XSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzo7ICooPzpbYS16XStbXy1dKT9bYS16XStcXFxcZCt8W14gKCk7LV0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAvLyBTcGxpdCBieSBmb3J3YXJkIHNsYXNoIGFuZCBhcHBlbmQgcHJvZHVjdCB2ZXJzaW9uIGlmIG5lZWRlZC5cbiAgICAgICAgICBpZiAoKHJlc3VsdCA9IFN0cmluZygoZ3Vlc3MubGFiZWwgJiYgIVJlZ0V4cChwYXR0ZXJuLCAnaScpLnRlc3QoZ3Vlc3MubGFiZWwpKSA/IGd1ZXNzLmxhYmVsIDogcmVzdWx0KS5zcGxpdCgnLycpKVsxXSAmJiAhL1tcXGQuXSsvLnRlc3QocmVzdWx0WzBdKSkge1xuICAgICAgICAgICAgcmVzdWx0WzBdICs9ICcgJyArIHJlc3VsdFsxXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgICAgICAgZ3Vlc3MgPSBndWVzcy5sYWJlbCB8fCBndWVzcztcbiAgICAgICAgICByZXN1bHQgPSBmb3JtYXQocmVzdWx0WzBdXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgZ3Vlc3MpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJzsgKig/OicgKyBndWVzcyArICdbXy1dKT8nLCAnaScpLCAnICcpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJygnICsgZ3Vlc3MgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCAnJDEgJDInKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2ZXJzaW9uIHVzaW5nIGFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXR0ZXJucyBBbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCB2ZXJzaW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZlcnNpb24ocGF0dGVybnMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UocGF0dGVybnMsIGZ1bmN0aW9uKHJlc3VsdCwgcGF0dGVybikge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChSZWdFeHAocGF0dGVybiArXG4gICAgICAgICAgJyg/Oi1bXFxcXGQuXSsvfCg/OiBmb3IgW1xcXFx3LV0rKT9bIC8tXSkoW1xcXFxkLl0rW14gKCk7L18tXSopJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fCBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIHdoZW4gdGhlIHBsYXRmb3JtIG9iamVjdCBpcyBjb2VyY2VkIHRvIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG5hbWUgdG9TdHJpbmdcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgaWYgYXZhaWxhYmxlLCBlbHNlIGFuIGVtcHR5IHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZ1BsYXRmb3JtKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRpb24gfHwgJyc7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQ29udmVydCBsYXlvdXQgdG8gYW4gYXJyYXkgc28gd2UgY2FuIGFkZCBleHRyYSBkZXRhaWxzLlxuICAgIGxheW91dCAmJiAobGF5b3V0ID0gW2xheW91dF0pO1xuXG4gICAgLy8gRGV0ZWN0IHByb2R1Y3QgbmFtZXMgdGhhdCBjb250YWluIHRoZWlyIG1hbnVmYWN0dXJlcidzIG5hbWUuXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiAhcHJvZHVjdCkge1xuICAgICAgcHJvZHVjdCA9IGdldFByb2R1Y3QoW21hbnVmYWN0dXJlcl0pO1xuICAgIH1cbiAgICAvLyBDbGVhbiB1cCBHb29nbGUgVFYuXG4gICAgaWYgKChkYXRhID0gL1xcYkdvb2dsZSBUVlxcYi8uZXhlYyhwcm9kdWN0KSkpIHtcbiAgICAgIHByb2R1Y3QgPSBkYXRhWzBdO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc2ltdWxhdG9ycy5cbiAgICBpZiAoL1xcYlNpbXVsYXRvclxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBwcm9kdWN0ID0gKHByb2R1Y3QgPyBwcm9kdWN0ICsgJyAnIDogJycpICsgJ1NpbXVsYXRvcic7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBNaW5pIDgrIHJ1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUgb24gaU9TLlxuICAgIGlmIChuYW1lID09ICdPcGVyYSBNaW5pJyAmJiAvXFxiT1BpT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBNb2JpbGUgMTEuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAvXFxibGlrZSBpUGhvbmUgT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkYXRhID0gcGFyc2UodWEucmVwbGFjZSgvbGlrZSBpUGhvbmUgT1MvLCAnJykpO1xuICAgICAgbWFudWZhY3R1cmVyID0gZGF0YS5tYW51ZmFjdHVyZXI7XG4gICAgICBwcm9kdWN0ID0gZGF0YS5wcm9kdWN0O1xuICAgIH1cbiAgICAvLyBEZXRlY3QgaU9TLlxuICAgIGVsc2UgaWYgKC9eaVAvLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIG5hbWUgfHwgKG5hbWUgPSAnU2FmYXJpJyk7XG4gICAgICBvcyA9ICdpT1MnICsgKChkYXRhID0gLyBPUyAoW1xcZF9dKykvaS5leGVjKHVhKSlcbiAgICAgICAgPyAnICcgKyBkYXRhWzFdLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICA6ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEt1YnVudHUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnS29ucXVlcm9yJyAmJiAhL2J1bnR1L2kudGVzdChvcykpIHtcbiAgICAgIG9zID0gJ0t1YnVudHUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQW5kcm9pZCBicm93c2Vycy5cbiAgICBlbHNlIGlmICgobWFudWZhY3R1cmVyICYmIG1hbnVmYWN0dXJlciAhPSAnR29vZ2xlJyAmJlxuICAgICAgICAoKC9DaHJvbWUvLnRlc3QobmFtZSkgJiYgIS9cXGJNb2JpbGUgU2FmYXJpXFxiL2kudGVzdCh1YSkpIHx8IC9cXGJWaXRhXFxiLy50ZXN0KHByb2R1Y3QpKSkgfHxcbiAgICAgICAgKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSAmJiAvXkNocm9tZS8udGVzdChuYW1lKSAmJiAvXFxiVmVyc2lvblxcLy9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSA9ICdBbmRyb2lkIEJyb3dzZXInO1xuICAgICAgb3MgPSAvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6ICdBbmRyb2lkJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFNpbGsgZGVza3RvcC9hY2NlbGVyYXRlZCBtb2Rlcy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTaWxrJykge1xuICAgICAgaWYgKCEvXFxiTW9iaS9pLnRlc3QodWEpKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQnO1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIH1cbiAgICAgIGlmICgvQWNjZWxlcmF0ZWQgKj0gKnRydWUvaS50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdhY2NlbGVyYXRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgUGFsZU1vb24gaWRlbnRpZnlpbmcgYXMgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdQYWxlTW9vbicgJiYgKGRhdGEgPSAvXFxiRmlyZWZveFxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyBGaXJlZm94ICcgKyBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggT1MgYW5kIHByb2R1Y3RzIHJ1bm5pbmcgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdGaXJlZm94JyAmJiAoZGF0YSA9IC9cXGIoTW9iaWxlfFRhYmxldHxUVilcXGIvaS5leGVjKHVhKSkpIHtcbiAgICAgIG9zIHx8IChvcyA9ICdGaXJlZm94IE9TJyk7XG4gICAgICBwcm9kdWN0IHx8IChwcm9kdWN0ID0gZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBmYWxzZSBwb3NpdGl2ZXMgZm9yIEZpcmVmb3gvU2FmYXJpLlxuICAgIGVsc2UgaWYgKCFuYW1lIHx8IChkYXRhID0gIS9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAvXFxiKD86RmlyZWZveHxTYWZhcmkpXFxiLy5leGVjKG5hbWUpKSkge1xuICAgICAgLy8gRXNjYXBlIHRoZSBgL2AgZm9yIEZpcmVmb3ggMS5cbiAgICAgIGlmIChuYW1lICYmICFwcm9kdWN0ICYmIC9bXFwvLF18XlteKF0rP1xcKS8udGVzdCh1YS5zbGljZSh1YS5pbmRleE9mKGRhdGEgKyAnLycpICsgOCkpKSB7XG4gICAgICAgIC8vIENsZWFyIG5hbWUgb2YgZmFsc2UgcG9zaXRpdmVzLlxuICAgICAgICBuYW1lID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFJlYXNzaWduIGEgZ2VuZXJpYyBuYW1lLlxuICAgICAgaWYgKChkYXRhID0gcHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgb3MpICYmXG4gICAgICAgICAgKHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IC9cXGIoPzpBbmRyb2lkfFN5bWJpYW4gT1N8VGFibGV0IE9TfHdlYk9TKVxcYi8udGVzdChvcykpKSB7XG4gICAgICAgIG5hbWUgPSAvW2Etel0rKD86IEhhdCk/L2kuZXhlYygvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6IGRhdGEpICsgJyBCcm93c2VyJztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIENocm9tZSB2ZXJzaW9uIHRvIGRlc2NyaXB0aW9uIGZvciBFbGVjdHJvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdFbGVjdHJvbicgJiYgKGRhdGEgPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBub24tT3BlcmEgKFByZXN0by1iYXNlZCkgdmVyc2lvbnMgKG9yZGVyIGlzIGltcG9ydGFudCkuXG4gICAgaWYgKCF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbihbXG4gICAgICAgICcoPzpDbG91ZDl8Q3JpT1N8Q3JNb3xFZGdlfEZ4aU9TfElFTW9iaWxlfElyb258T3BlcmEgP01pbml8T1BpT1N8T1BSfFJhdmVufFNhbXN1bmdCcm93c2VyfFNpbGsoPyEvW1xcXFxkLl0rJCkpJyxcbiAgICAgICAgJ1ZlcnNpb24nLFxuICAgICAgICBxdWFsaWZ5KG5hbWUpLFxuICAgICAgICAnKD86RmlyZWZveHxNaW5lZmllbGR8TmV0RnJvbnQpJ1xuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBzdHViYm9ybiBsYXlvdXQgZW5naW5lcy5cbiAgICBpZiAoKGRhdGEgPVxuICAgICAgICAgIGxheW91dCA9PSAnaUNhYicgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+IDMgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAvXFxiT3BlcmFcXGIvLnRlc3QobmFtZSkgJiYgKC9cXGJPUFJcXGIvLnRlc3QodWEpID8gJ0JsaW5rJyA6ICdQcmVzdG8nKSB8fFxuICAgICAgICAgIC9cXGIoPzpNaWRvcml8Tm9va3xTYWZhcmkpXFxiL2kudGVzdCh1YSkgJiYgIS9eKD86VHJpZGVudHxFZGdlSFRNTCkkLy50ZXN0KGxheW91dCkgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAhbGF5b3V0ICYmIC9cXGJNU0lFXFxiL2kudGVzdCh1YSkgJiYgKG9zID09ICdNYWMgT1MnID8gJ1Rhc21hbicgOiAnVHJpZGVudCcpIHx8XG4gICAgICAgICAgbGF5b3V0ID09ICdXZWJLaXQnICYmIC9cXGJQbGF5U3RhdGlvblxcYig/ISBWaXRhXFxiKS9pLnRlc3QobmFtZSkgJiYgJ05ldEZyb250J1xuICAgICAgICApKSB7XG4gICAgICBsYXlvdXQgPSBbZGF0YV07XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDcgZGVza3RvcCBtb2RlLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgKGRhdGEgPSAoLzsgKig/OlhCTFdQfFp1bmVXUCkoXFxkKykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSAnICsgKC9cXCskLy50ZXN0KGRhdGEpID8gZGF0YSA6IGRhdGEgKyAnLngnKTtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA4LnggZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKC9cXGJXUERlc2t0b3BcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgbmFtZSA9ICdJRSBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSA4LngnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB2ZXJzaW9uIHx8ICh2ZXJzaW9uID0gKC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpIHx8IDApWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIDExIGlkZW50aWZ5aW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKG5hbWUgIT0gJ0lFJyAmJiBsYXlvdXQgPT0gJ1RyaWRlbnQnICYmIChkYXRhID0gL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkpKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyAnICsgbmFtZSArICh2ZXJzaW9uID8gJyAnICsgdmVyc2lvbiA6ICcnKSk7XG4gICAgICB9XG4gICAgICBuYW1lID0gJ0lFJztcbiAgICAgIHZlcnNpb24gPSBkYXRhWzFdO1xuICAgIH1cbiAgICAvLyBMZXZlcmFnZSBlbnZpcm9ubWVudCBmZWF0dXJlcy5cbiAgICBpZiAodXNlRmVhdHVyZXMpIHtcbiAgICAgIC8vIERldGVjdCBzZXJ2ZXItc2lkZSBlbnZpcm9ubWVudHMuXG4gICAgICAvLyBSaGlubyBoYXMgYSBnbG9iYWwgZnVuY3Rpb24gd2hpbGUgb3RoZXJzIGhhdmUgYSBnbG9iYWwgb2JqZWN0LlxuICAgICAgaWYgKGlzSG9zdFR5cGUoY29udGV4dCwgJ2dsb2JhbCcpKSB7XG4gICAgICAgIGlmIChqYXZhKSB7XG4gICAgICAgICAgZGF0YSA9IGphdmEubGFuZy5TeXN0ZW07XG4gICAgICAgICAgYXJjaCA9IGRhdGEuZ2V0UHJvcGVydHkoJ29zLmFyY2gnKTtcbiAgICAgICAgICBvcyA9IG9zIHx8IGRhdGEuZ2V0UHJvcGVydHkoJ29zLm5hbWUnKSArICcgJyArIGRhdGEuZ2V0UHJvcGVydHkoJ29zLnZlcnNpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmhpbm8pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmVyc2lvbiA9IGNvbnRleHQucmVxdWlyZSgncmluZ28vZW5naW5lJykudmVyc2lvbi5qb2luKCcuJyk7XG4gICAgICAgICAgICBuYW1lID0gJ1JpbmdvSlMnO1xuICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgaWYgKChkYXRhID0gY29udGV4dC5zeXN0ZW0pICYmIGRhdGEuZ2xvYmFsLnN5c3RlbSA9PSBjb250ZXh0LnN5c3RlbSkge1xuICAgICAgICAgICAgICBuYW1lID0gJ05hcndoYWwnO1xuICAgICAgICAgICAgICBvcyB8fCAob3MgPSBkYXRhWzBdLm9zIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnUmhpbm8nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgY29udGV4dC5wcm9jZXNzID09ICdvYmplY3QnICYmICFjb250ZXh0LnByb2Nlc3MuYnJvd3NlciAmJlxuICAgICAgICAgIChkYXRhID0gY29udGV4dC5wcm9jZXNzKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5lbGVjdHJvbiA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ0VsZWN0cm9uJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMuZWxlY3Ryb247XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLm53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyB2ZXJzaW9uLCAnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOVy5qcyc7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLm53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnTm9kZS5qcyc7XG4gICAgICAgICAgICBhcmNoID0gZGF0YS5hcmNoO1xuICAgICAgICAgICAgb3MgPSBkYXRhLnBsYXRmb3JtO1xuICAgICAgICAgICAgdmVyc2lvbiA9IC9bXFxkLl0rLy5leGVjKGRhdGEudmVyc2lvbik7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbiA/IHZlcnNpb25bMF0gOiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEFkb2JlIEFJUi5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnJ1bnRpbWUpKSA9PSBhaXJSdW50aW1lQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdBZG9iZSBBSVInO1xuICAgICAgICBvcyA9IGRhdGEuZmxhc2guc3lzdGVtLkNhcGFiaWxpdGllcy5vcztcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBQaGFudG9tSlMuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5waGFudG9tKSkgPT0gcGhhbnRvbUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnUGhhbnRvbUpTJztcbiAgICAgICAgdmVyc2lvbiA9IChkYXRhID0gZGF0YS52ZXJzaW9uIHx8IG51bGwpICYmIChkYXRhLm1ham9yICsgJy4nICsgZGF0YS5taW5vciArICcuJyArIGRhdGEucGF0Y2gpO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIGNvbXBhdGliaWxpdHkgbW9kZXMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAoZGF0YSA9IC9cXGJUcmlkZW50XFwvKFxcZCspL2kuZXhlYyh1YSkpKSB7XG4gICAgICAgIC8vIFdlJ3JlIGluIGNvbXBhdGliaWxpdHkgbW9kZSB3aGVuIHRoZSBUcmlkZW50IHZlcnNpb24gKyA0IGRvZXNuJ3RcbiAgICAgICAgLy8gZXF1YWwgdGhlIGRvY3VtZW50IG1vZGUuXG4gICAgICAgIHZlcnNpb24gPSBbdmVyc2lvbiwgZG9jLmRvY3VtZW50TW9kZV07XG4gICAgICAgIGlmICgoZGF0YSA9ICtkYXRhWzFdICsgNCkgIT0gdmVyc2lvblsxXSkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0lFICcgKyB2ZXJzaW9uWzFdICsgJyBtb2RlJyk7XG4gICAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnJyk7XG4gICAgICAgICAgdmVyc2lvblsxXSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgdmVyc2lvbiA9IG5hbWUgPT0gJ0lFJyA/IFN0cmluZyh2ZXJzaW9uWzFdLnRvRml4ZWQoMSkpIDogdmVyc2lvblswXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSAxMSBtYXNraW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgL14oPzpDaHJvbWV8RmlyZWZveClcXGIvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnbWFza2luZyBhcyAnICsgbmFtZSArICcgJyArIHZlcnNpb24pO1xuICAgICAgICBuYW1lID0gJ0lFJztcbiAgICAgICAgdmVyc2lvbiA9ICcxMS4wJztcbiAgICAgICAgbGF5b3V0ID0gWydUcmlkZW50J107XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcyAmJiBmb3JtYXQob3MpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgcHJlcmVsZWFzZSBwaGFzZXMuXG4gICAgaWYgKHZlcnNpb24gJiYgKGRhdGEgPVxuICAgICAgICAgIC8oPzpbYWJdfGRwfHByZXxbYWJdXFxkK3ByZSkoPzpcXGQrXFwrPyk/JC9pLmV4ZWModmVyc2lvbikgfHxcbiAgICAgICAgICAvKD86YWxwaGF8YmV0YSkoPzogP1xcZCk/L2kuZXhlYyh1YSArICc7JyArICh1c2VGZWF0dXJlcyAmJiBuYXYuYXBwTWlub3JWZXJzaW9uKSkgfHxcbiAgICAgICAgICAvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgJ2EnXG4gICAgICAgICkpIHtcbiAgICAgIHByZXJlbGVhc2UgPSAvYi9pLnRlc3QoZGF0YSkgPyAnYmV0YScgOiAnYWxwaGEnO1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZShSZWdFeHAoZGF0YSArICdcXFxcKz8kJyksICcnKSArXG4gICAgICAgIChwcmVyZWxlYXNlID09ICdiZXRhJyA/IGJldGEgOiBhbHBoYSkgKyAoL1xcZCtcXCs/Ly5leGVjKGRhdGEpIHx8ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggTW9iaWxlLlxuICAgIGlmIChuYW1lID09ICdGZW5uZWMnIHx8IG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGIoPzpBbmRyb2lkfEZpcmVmb3ggT1MpXFxiLy50ZXN0KG9zKSkge1xuICAgICAgbmFtZSA9ICdGaXJlZm94IE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIE9ic2N1cmUgTWF4dGhvbidzIHVucmVsaWFibGUgdmVyc2lvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdNYXh0aG9uJyAmJiB2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKC9cXC5bXFxkLl0rLywgJy54Jyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBYYm94IDM2MCBhbmQgWGJveCBPbmUuXG4gICAgZWxzZSBpZiAoL1xcYlhib3hcXGIvaS50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnKSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcgJiYgL1xcYklFTW9iaWxlXFxiLy50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdtb2JpbGUgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgbW9iaWxlIHBvc3RmaXguXG4gICAgZWxzZSBpZiAoKC9eKD86Q2hyb21lfElFfE9wZXJhKSQvLnRlc3QobmFtZSkgfHwgbmFtZSAmJiAhcHJvZHVjdCAmJiAhL0Jyb3dzZXJ8TW9iaS8udGVzdChuYW1lKSkgJiZcbiAgICAgICAgKG9zID09ICdXaW5kb3dzIENFJyB8fCAvTW9iaS9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBwbGF0Zm9ybSBwcmV2aWV3LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0lFJyAmJiB1c2VGZWF0dXJlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGNvbnRleHQuZXh0ZXJuYWwgPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdwbGF0Zm9ybSBwcmV2aWV3Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdlbWJlZGRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgQmxhY2tCZXJyeSBPUyB2ZXJzaW9uLlxuICAgIC8vIGh0dHA6Ly9kb2NzLmJsYWNrYmVycnkuY29tL2VuL2RldmVsb3BlcnMvZGVsaXZlcmFibGVzLzE4MTY5L0hUVFBfaGVhZGVyc19zZW50X2J5X0JCX0Jyb3dzZXJfMTIzNDkxMV8xMS5qc3BcbiAgICBlbHNlIGlmICgoL1xcYkJsYWNrQmVycnlcXGIvLnRlc3QocHJvZHVjdCkgfHwgL1xcYkJCMTBcXGIvLnRlc3QodWEpKSAmJiAoZGF0YSA9XG4gICAgICAgICAgKFJlZ0V4cChwcm9kdWN0LnJlcGxhY2UoLyArL2csICcgKicpICsgJy8oWy5cXFxcZF0rKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICkpIHtcbiAgICAgIGRhdGEgPSBbZGF0YSwgL0JCMTAvLnRlc3QodWEpXTtcbiAgICAgIG9zID0gKGRhdGFbMV0gPyAocHJvZHVjdCA9IG51bGwsIG1hbnVmYWN0dXJlciA9ICdCbGFja0JlcnJ5JykgOiAnRGV2aWNlIFNvZnR3YXJlJykgKyAnICcgKyBkYXRhWzBdO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBpZGVudGlmeWluZy9tYXNraW5nIGl0c2VsZiBhcyBhbm90aGVyIGJyb3dzZXIuXG4gICAgLy8gaHR0cDovL3d3dy5vcGVyYS5jb20vc3VwcG9ydC9rYi92aWV3Lzg0My9cbiAgICBlbHNlIGlmICh0aGlzICE9IGZvck93biAmJiBwcm9kdWN0ICE9ICdXaWknICYmIChcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgb3BlcmEpIHx8XG4gICAgICAgICAgKC9PcGVyYS8udGVzdChuYW1lKSAmJiAvXFxiKD86TVNJRXxGaXJlZm94KVxcYi9pLnRlc3QodWEpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiT1MgWCAoPzpcXGQrXFwuKXsyLH0vLnRlc3Qob3MpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdJRScgJiYgKFxuICAgICAgICAgICAgKG9zICYmICEvXldpbi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDUuNSkgfHxcbiAgICAgICAgICAgIC9cXGJXaW5kb3dzIFhQXFxiLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gOCB8fFxuICAgICAgICAgICAgdmVyc2lvbiA9PSA4ICYmICEvXFxiVHJpZGVudFxcYi8udGVzdCh1YSlcbiAgICAgICAgICApKVxuICAgICAgICApICYmICFyZU9wZXJhLnRlc3QoKGRhdGEgPSBwYXJzZS5jYWxsKGZvck93biwgdWEucmVwbGFjZShyZU9wZXJhLCAnJykgKyAnOycpKSkgJiYgZGF0YS5uYW1lKSB7XG4gICAgICAvLyBXaGVuIFwiaWRlbnRpZnlpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIGJvdGggT3BlcmEgYW5kIHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGRhdGEgPSAnaW5nIGFzICcgKyBkYXRhLm5hbWUgKyAoKGRhdGEgPSBkYXRhLnZlcnNpb24pID8gJyAnICsgZGF0YSA6ICcnKTtcbiAgICAgIGlmIChyZU9wZXJhLnRlc3QobmFtZSkpIHtcbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSAmJiBvcyA9PSAnTWFjIE9TJykge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gJ2lkZW50aWZ5JyArIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBXaGVuIFwibWFza2luZ1wiLCB0aGUgVUEgY29udGFpbnMgb25seSB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBlbHNlIHtcbiAgICAgICAgZGF0YSA9ICdtYXNrJyArIGRhdGE7XG4gICAgICAgIGlmIChvcGVyYUNsYXNzKSB7XG4gICAgICAgICAgbmFtZSA9IGZvcm1hdChvcGVyYUNsYXNzLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMSAkMicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lID0gJ09wZXJhJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdXNlRmVhdHVyZXMpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGF5b3V0ID0gWydQcmVzdG8nXTtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXZWJLaXQgTmlnaHRseSBhbmQgYXBwcm94aW1hdGUgQ2hyb21lL1NhZmFyaSB2ZXJzaW9ucy5cbiAgICBpZiAoKGRhdGEgPSAoL1xcYkFwcGxlV2ViS2l0XFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgLy8gQ29ycmVjdCBidWlsZCBudW1iZXIgZm9yIG51bWVyaWMgY29tcGFyaXNvbi5cbiAgICAgIC8vIChlLmcuIFwiNTMyLjVcIiBiZWNvbWVzIFwiNTMyLjA1XCIpXG4gICAgICBkYXRhID0gW3BhcnNlRmxvYXQoZGF0YS5yZXBsYWNlKC9cXC4oXFxkKSQvLCAnLjAkMScpKSwgZGF0YV07XG4gICAgICAvLyBOaWdodGx5IGJ1aWxkcyBhcmUgcG9zdGZpeGVkIHdpdGggYSBcIitcIi5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmIGRhdGFbMV0uc2xpY2UoLTEpID09ICcrJykge1xuICAgICAgICBuYW1lID0gJ1dlYktpdCBOaWdodGx5JztcbiAgICAgICAgcHJlcmVsZWFzZSA9ICdhbHBoYSc7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhWzFdLnNsaWNlKDAsIC0xKTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFyIGluY29ycmVjdCBicm93c2VyIHZlcnNpb25zLlxuICAgICAgZWxzZSBpZiAodmVyc2lvbiA9PSBkYXRhWzFdIHx8XG4gICAgICAgICAgdmVyc2lvbiA9PSAoZGF0YVsyXSA9ICgvXFxiU2FmYXJpXFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgZnVsbCBDaHJvbWUgdmVyc2lvbiB3aGVuIGF2YWlsYWJsZS5cbiAgICAgIGRhdGFbMV0gPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKS9pLmV4ZWModWEpIHx8IDApWzFdO1xuICAgICAgLy8gRGV0ZWN0IEJsaW5rIGxheW91dCBlbmdpbmUuXG4gICAgICBpZiAoZGF0YVswXSA9PSA1MzcuMzYgJiYgZGF0YVsyXSA9PSA1MzcuMzYgJiYgcGFyc2VGbG9hdChkYXRhWzFdKSA+PSAyOCAmJiBsYXlvdXQgPT0gJ1dlYktpdCcpIHtcbiAgICAgICAgbGF5b3V0ID0gWydCbGluayddO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEphdmFTY3JpcHRDb3JlLlxuICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzY4NDc0L2hvdy1jYW4taS1kZXRlY3Qtd2hpY2gtamF2YXNjcmlwdC1lbmdpbmUtdjgtb3ItanNjLWlzLXVzZWQtYXQtcnVudGltZS1pbi1hbmRyb2lcbiAgICAgIGlmICghdXNlRmVhdHVyZXMgfHwgKCFsaWtlQ2hyb21lICYmICFkYXRhWzFdKSkge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIFNhZmFyaScpO1xuICAgICAgICBkYXRhID0gKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNDAwID8gMSA6IGRhdGEgPCA1MDAgPyAyIDogZGF0YSA8IDUyNiA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQgPyAnNCsnIDogZGF0YSA8IDUzNSA/IDUgOiBkYXRhIDwgNTM3ID8gNiA6IGRhdGEgPCA1MzggPyA3IDogZGF0YSA8IDYwMSA/IDggOiAnOCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBDaHJvbWUnKTtcbiAgICAgICAgZGF0YSA9IGRhdGFbMV0gfHwgKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNTMwID8gMSA6IGRhdGEgPCA1MzIgPyAyIDogZGF0YSA8IDUzMi4wNSA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQuMDMgPyA1IDogZGF0YSA8IDUzNC4wNyA/IDYgOiBkYXRhIDwgNTM0LjEwID8gNyA6IGRhdGEgPCA1MzQuMTMgPyA4IDogZGF0YSA8IDUzNC4xNiA/IDkgOiBkYXRhIDwgNTM0LjI0ID8gMTAgOiBkYXRhIDwgNTM0LjMwID8gMTEgOiBkYXRhIDwgNTM1LjAxID8gMTIgOiBkYXRhIDwgNTM1LjAyID8gJzEzKycgOiBkYXRhIDwgNTM1LjA3ID8gMTUgOiBkYXRhIDwgNTM1LjExID8gMTYgOiBkYXRhIDwgNTM1LjE5ID8gMTcgOiBkYXRhIDwgNTM2LjA1ID8gMTggOiBkYXRhIDwgNTM2LjEwID8gMTkgOiBkYXRhIDwgNTM3LjAxID8gMjAgOiBkYXRhIDwgNTM3LjExID8gJzIxKycgOiBkYXRhIDwgNTM3LjEzID8gMjMgOiBkYXRhIDwgNTM3LjE4ID8gMjQgOiBkYXRhIDwgNTM3LjI0ID8gMjUgOiBkYXRhIDwgNTM3LjM2ID8gMjYgOiBsYXlvdXQgIT0gJ0JsaW5rJyA/ICcyNycgOiAnMjgnKTtcbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgcG9zdGZpeCBvZiBcIi54XCIgb3IgXCIrXCIgZm9yIGFwcHJveGltYXRlIHZlcnNpb25zLlxuICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gKz0gJyAnICsgKGRhdGEgKz0gdHlwZW9mIGRhdGEgPT0gJ251bWJlcicgPyAnLngnIDogL1suK10vLnRlc3QoZGF0YSkgPyAnJyA6ICcrJykpO1xuICAgICAgLy8gT2JzY3VyZSB2ZXJzaW9uIGZvciBzb21lIFNhZmFyaSAxLTIgcmVsZWFzZXMuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAoIXZlcnNpb24gfHwgcGFyc2VJbnQodmVyc2lvbikgPiA0NSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IGRhdGE7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBkZXNrdG9wIG1vZGVzLlxuICAgIGlmIChuYW1lID09ICdPcGVyYScgJiYgIChkYXRhID0gL1xcYnpib3Z8enZhdiQvLmV4ZWMob3MpKSkge1xuICAgICAgbmFtZSArPSAnICc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIGlmIChkYXRhID09ICd6dmF2Jykge1xuICAgICAgICBuYW1lICs9ICdNaW5pJztcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuYW1lICs9ICdNb2JpbGUnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSArICckJyksICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IENocm9tZSBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAvXFxiQ2hyb21lXFxiLy5leGVjKGxheW91dCAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIG5hbWUgPSAnQ2hyb21lIE1vYmlsZSc7XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcblxuICAgICAgaWYgKC9cXGJPUyBYXFxiLy50ZXN0KG9zKSkge1xuICAgICAgICBtYW51ZmFjdHVyZXIgPSAnQXBwbGUnO1xuICAgICAgICBvcyA9ICdpT1MgNC4zKyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFN0cmlwIGluY29ycmVjdCBPUyB2ZXJzaW9ucy5cbiAgICBpZiAodmVyc2lvbiAmJiB2ZXJzaW9uLmluZGV4T2YoKGRhdGEgPSAvW1xcZC5dKyQvLmV4ZWMob3MpKSkgPT0gMCAmJlxuICAgICAgICB1YS5pbmRleE9mKCcvJyArIGRhdGEgKyAnLScpID4gLTEpIHtcbiAgICAgIG9zID0gdHJpbShvcy5yZXBsYWNlKGRhdGEsICcnKSk7XG4gICAgfVxuICAgIC8vIEFkZCBsYXlvdXQgZW5naW5lLlxuICAgIGlmIChsYXlvdXQgJiYgIS9cXGIoPzpBdmFudHxOb29rKVxcYi8udGVzdChuYW1lKSAmJiAoXG4gICAgICAgIC9Ccm93c2VyfEx1bmFzY2FwZXxNYXh0aG9uLy50ZXN0KG5hbWUpIHx8XG4gICAgICAgIG5hbWUgIT0gJ1NhZmFyaScgJiYgL15pT1MvLnRlc3Qob3MpICYmIC9cXGJTYWZhcmlcXGIvLnRlc3QobGF5b3V0WzFdKSB8fFxuICAgICAgICAvXig/OkFkb2JlfEFyb3JhfEJyZWFjaHxNaWRvcml8T3BlcmF8UGhhbnRvbXxSZWtvbnF8Um9ja3xTYW1zdW5nIEludGVybmV0fFNsZWlwbmlyfFdlYikvLnRlc3QobmFtZSkgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgLy8gRG9uJ3QgYWRkIGxheW91dCBkZXRhaWxzIHRvIGRlc2NyaXB0aW9uIGlmIHRoZXkgYXJlIGZhbHNleS5cbiAgICAgIChkYXRhID0gbGF5b3V0W2xheW91dC5sZW5ndGggLSAxXSkgJiYgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gQ29tYmluZSBjb250ZXh0dWFsIGluZm9ybWF0aW9uLlxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIGRlc2NyaXB0aW9uID0gWycoJyArIGRlc2NyaXB0aW9uLmpvaW4oJzsgJykgKyAnKSddO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgbWFudWZhY3R1cmVyIHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgcHJvZHVjdCAmJiBwcm9kdWN0LmluZGV4T2YobWFudWZhY3R1cmVyKSA8IDApIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ29uICcgKyBtYW51ZmFjdHVyZXIpO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgcHJvZHVjdCB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAocHJvZHVjdCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgoL15vbiAvLnRlc3QoZGVzY3JpcHRpb25bZGVzY3JpcHRpb24ubGVuZ3RoIC0gMV0pID8gJycgOiAnb24gJykgKyBwcm9kdWN0KTtcbiAgICB9XG4gICAgLy8gUGFyc2UgdGhlIE9TIGludG8gYW4gb2JqZWN0LlxuICAgIGlmIChvcykge1xuICAgICAgZGF0YSA9IC8gKFtcXGQuK10rKSQvLmV4ZWMob3MpO1xuICAgICAgaXNTcGVjaWFsQ2FzZWRPUyA9IGRhdGEgJiYgb3MuY2hhckF0KG9zLmxlbmd0aCAtIGRhdGFbMF0ubGVuZ3RoIC0gMSkgPT0gJy8nO1xuICAgICAgb3MgPSB7XG4gICAgICAgICdhcmNoaXRlY3R1cmUnOiAzMixcbiAgICAgICAgJ2ZhbWlseSc6IChkYXRhICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/IG9zLnJlcGxhY2UoZGF0YVswXSwgJycpIDogb3MsXG4gICAgICAgICd2ZXJzaW9uJzogZGF0YSA/IGRhdGFbMV0gOiBudWxsLFxuICAgICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgdmVyc2lvbiA9IHRoaXMudmVyc2lvbjtcbiAgICAgICAgICByZXR1cm4gdGhpcy5mYW1pbHkgKyAoKHZlcnNpb24gJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gJyAnICsgdmVyc2lvbiA6ICcnKSArICh0aGlzLmFyY2hpdGVjdHVyZSA9PSA2NCA/ICcgNjQtYml0JyA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gQWRkIGJyb3dzZXIvT1MgYXJjaGl0ZWN0dXJlLlxuICAgIGlmICgoZGF0YSA9IC9cXGIoPzpBTUR8SUF8V2lufFdPV3x4ODZffHgpNjRcXGIvaS5leGVjKGFyY2gpKSAmJiAhL1xcYmk2ODZcXGIvaS50ZXN0KGFyY2gpKSB7XG4gICAgICBpZiAob3MpIHtcbiAgICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgICAgIG9zLmZhbWlseSA9IG9zLmZhbWlseS5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSksICcnKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgICBuYW1lICYmICgvXFxiV09XNjRcXGIvaS50ZXN0KHVhKSB8fFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiAvXFx3KD86ODZ8MzIpJC8udGVzdChuYXYuY3B1Q2xhc3MgfHwgbmF2LnBsYXRmb3JtKSAmJiAhL1xcYldpbjY0OyB4NjRcXGIvaS50ZXN0KHVhKSkpXG4gICAgICApIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnMzItYml0Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENocm9tZSAzOSBhbmQgYWJvdmUgb24gT1MgWCBpcyBhbHdheXMgNjQtYml0LlxuICAgIGVsc2UgaWYgKFxuICAgICAgICBvcyAmJiAvXk9TIFgvLnRlc3Qob3MuZmFtaWx5KSAmJlxuICAgICAgICBuYW1lID09ICdDaHJvbWUnICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPj0gMzlcbiAgICApIHtcbiAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgIH1cblxuICAgIHVhIHx8ICh1YSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgdmFyIHBsYXRmb3JtID0ge307XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gZGVzY3JpcHRpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3NlcidzIGxheW91dCBlbmdpbmUuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gbGF5b3V0IGVuZ2luZXMgaW5jbHVkZTpcbiAgICAgKiBcIkJsaW5rXCIsIFwiRWRnZUhUTUxcIiwgXCJHZWNrb1wiLCBcIlRyaWRlbnRcIiBhbmQgXCJXZWJLaXRcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5sYXlvdXQgPSBsYXlvdXQgJiYgbGF5b3V0WzBdO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QncyBtYW51ZmFjdHVyZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBtYW51ZmFjdHVyZXJzIGluY2x1ZGU6XG4gICAgICogXCJBcHBsZVwiLCBcIkFyY2hvc1wiLCBcIkFtYXpvblwiLCBcIkFzdXNcIiwgXCJCYXJuZXMgJiBOb2JsZVwiLCBcIkJsYWNrQmVycnlcIixcbiAgICAgKiBcIkdvb2dsZVwiLCBcIkhQXCIsIFwiSFRDXCIsIFwiTEdcIiwgXCJNaWNyb3NvZnRcIiwgXCJNb3Rvcm9sYVwiLCBcIk5pbnRlbmRvXCIsXG4gICAgICogXCJOb2tpYVwiLCBcIlNhbXN1bmdcIiBhbmQgXCJTb255XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubWFudWZhY3R1cmVyID0gbWFudWZhY3R1cmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIvZW52aXJvbm1lbnQuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gYnJvd3NlciBuYW1lcyBpbmNsdWRlOlxuICAgICAqIFwiQ2hyb21lXCIsIFwiRWxlY3Ryb25cIiwgXCJGaXJlZm94XCIsIFwiRmlyZWZveCBmb3IgaU9TXCIsIFwiSUVcIixcbiAgICAgKiBcIk1pY3Jvc29mdCBFZGdlXCIsIFwiUGhhbnRvbUpTXCIsIFwiU2FmYXJpXCIsIFwiU2VhTW9ua2V5XCIsIFwiU2lsa1wiLFxuICAgICAqIFwiT3BlcmEgTWluaVwiIGFuZCBcIk9wZXJhXCJcbiAgICAgKlxuICAgICAqIE1vYmlsZSB2ZXJzaW9ucyBvZiBzb21lIGJyb3dzZXJzIGhhdmUgXCJNb2JpbGVcIiBhcHBlbmRlZCB0byB0aGVpciBuYW1lOlxuICAgICAqIGVnLiBcIkNocm9tZSBNb2JpbGVcIiwgXCJGaXJlZm94IE1vYmlsZVwiLCBcIklFIE1vYmlsZVwiIGFuZCBcIk9wZXJhIE1vYmlsZVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm5hbWUgPSBuYW1lO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFscGhhL2JldGEgcmVsZWFzZSBpbmRpY2F0b3IuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByZXJlbGVhc2UgPSBwcmVyZWxlYXNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QgaG9zdGluZyB0aGUgYnJvd3Nlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBwcm9kdWN0cyBpbmNsdWRlOlxuICAgICAqXG4gICAgICogXCJCbGFja0JlcnJ5XCIsIFwiR2FsYXh5IFM0XCIsIFwiTHVtaWFcIiwgXCJpUGFkXCIsIFwiaVBvZFwiLCBcImlQaG9uZVwiLCBcIktpbmRsZVwiLFxuICAgICAqIFwiS2luZGxlIEZpcmVcIiwgXCJOZXh1c1wiLCBcIk5vb2tcIiwgXCJQbGF5Qm9va1wiLCBcIlRvdWNoUGFkXCIgYW5kIFwiVHJhbnNmb3JtZXJcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcm9kdWN0ID0gcHJvZHVjdDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyJ3MgdXNlciBhZ2VudCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnVhID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS52ZXJzaW9uID0gbmFtZSAmJiB2ZXJzaW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5vcyA9IG9zIHx8IHtcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZSB0aGUgT1MgaXMgYnVpbHQgZm9yLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgbnVtYmVyfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2FyY2hpdGVjdHVyZSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIGZhbWlseSBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQ29tbW9uIHZhbHVlcyBpbmNsdWRlOlxuICAgICAgICogXCJXaW5kb3dzXCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCBSMiAvIDdcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IC8gVmlzdGFcIixcbiAgICAgICAqIFwiV2luZG93cyBYUFwiLCBcIk9TIFhcIiwgXCJVYnVudHVcIiwgXCJEZWJpYW5cIiwgXCJGZWRvcmFcIiwgXCJSZWQgSGF0XCIsIFwiU3VTRVwiLFxuICAgICAgICogXCJBbmRyb2lkXCIsIFwiaU9TXCIgYW5kIFwiV2luZG93cyBQaG9uZVwiXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAnZmFtaWx5JzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAndmVyc2lvbic6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogUmV0dXJucyB0aGUgT1Mgc3RyaW5nLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIE9TIHN0cmluZy5cbiAgICAgICAqL1xuICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7IHJldHVybiAnbnVsbCc7IH1cbiAgICB9O1xuXG4gICAgcGxhdGZvcm0ucGFyc2UgPSBwYXJzZTtcbiAgICBwbGF0Zm9ybS50b1N0cmluZyA9IHRvU3RyaW5nUGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0udmVyc2lvbikge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCh2ZXJzaW9uKTtcbiAgICB9XG4gICAgaWYgKHBsYXRmb3JtLm5hbWUpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuICAgIGlmIChvcyAmJiBuYW1lICYmICEob3MgPT0gU3RyaW5nKG9zKS5zcGxpdCgnICcpWzBdICYmIChvcyA9PSBuYW1lLnNwbGl0KCcgJylbMF0gfHwgcHJvZHVjdCkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKHByb2R1Y3QgPyAnKCcgKyBvcyArICcpJyA6ICdvbiAnICsgb3MpO1xuICAgIH1cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLmpvaW4oJyAnKTtcbiAgICB9XG4gICAgcmV0dXJuIHBsYXRmb3JtO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IHBsYXRmb3JtLlxuICB2YXIgcGxhdGZvcm0gPSBwYXJzZSgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMsIGxpa2Ugci5qcywgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEV4cG9zZSBwbGF0Zm9ybSBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIHBsYXRmb3JtIGlzXG4gICAgLy8gbG9hZGVkIGJ5IGEgc2NyaXB0IHRhZyBpbiB0aGUgcHJlc2VuY2Ugb2YgYW4gQU1EIGxvYWRlci5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvIHBsYXRmb3JtIGNhbiBiZSBhbGlhc2VkIHRocm91Z2ggcGF0aCBtYXBwaW5nLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBhbiBgZXhwb3J0c2Agb2JqZWN0LlxuICBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZvck93bihwbGF0Zm9ybSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgZnJlZUV4cG9ydHNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJ2YXIgdjEgPSByZXF1aXJlKCcuL3YxJyk7XG52YXIgdjQgPSByZXF1aXJlKCcuL3Y0Jyk7XG5cbnZhciB1dWlkID0gdjQ7XG51dWlkLnYxID0gdjE7XG51dWlkLnY0ID0gdjQ7XG5cbm1vZHVsZS5leHBvcnRzID0gdXVpZDtcbiIsIi8qKlxuICogQ29udmVydCBhcnJheSBvZiAxNiBieXRlIHZhbHVlcyB0byBVVUlEIHN0cmluZyBmb3JtYXQgb2YgdGhlIGZvcm06XG4gKiBYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFhcbiAqL1xudmFyIGJ5dGVUb0hleCA9IFtdO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICBieXRlVG9IZXhbaV0gPSAoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpO1xufVxuXG5mdW5jdGlvbiBieXRlc1RvVXVpZChidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IG9mZnNldCB8fCAwO1xuICB2YXIgYnRoID0gYnl0ZVRvSGV4O1xuICByZXR1cm4gYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJ5dGVzVG9VdWlkO1xuIiwiLy8gVW5pcXVlIElEIGNyZWF0aW9uIHJlcXVpcmVzIGEgaGlnaCBxdWFsaXR5IHJhbmRvbSAjIGdlbmVyYXRvci4gIEluIHRoZVxuLy8gYnJvd3NlciB0aGlzIGlzIGEgbGl0dGxlIGNvbXBsaWNhdGVkIGR1ZSB0byB1bmtub3duIHF1YWxpdHkgb2YgTWF0aC5yYW5kb20oKVxuLy8gYW5kIGluY29uc2lzdGVudCBzdXBwb3J0IGZvciB0aGUgYGNyeXB0b2AgQVBJLiAgV2UgZG8gdGhlIGJlc3Qgd2UgY2FuIHZpYVxuLy8gZmVhdHVyZS1kZXRlY3Rpb25cblxuLy8gZ2V0UmFuZG9tVmFsdWVzIG5lZWRzIHRvIGJlIGludm9rZWQgaW4gYSBjb250ZXh0IHdoZXJlIFwidGhpc1wiIGlzIGEgQ3J5cHRvIGltcGxlbWVudGF0aW9uLlxudmFyIGdldFJhbmRvbVZhbHVlcyA9ICh0eXBlb2YoY3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQoY3J5cHRvKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAodHlwZW9mKG1zQ3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChtc0NyeXB0bykpO1xuaWYgKGdldFJhbmRvbVZhbHVlcykge1xuICAvLyBXSEFUV0cgY3J5cHRvIFJORyAtIGh0dHA6Ly93aWtpLndoYXR3Zy5vcmcvd2lraS9DcnlwdG9cbiAgdmFyIHJuZHM4ID0gbmV3IFVpbnQ4QXJyYXkoMTYpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB3aGF0d2dSTkcoKSB7XG4gICAgZ2V0UmFuZG9tVmFsdWVzKHJuZHM4KTtcbiAgICByZXR1cm4gcm5kczg7XG4gIH07XG59IGVsc2Uge1xuICAvLyBNYXRoLnJhbmRvbSgpLWJhc2VkIChSTkcpXG4gIC8vXG4gIC8vIElmIGFsbCBlbHNlIGZhaWxzLCB1c2UgTWF0aC5yYW5kb20oKS4gIEl0J3MgZmFzdCwgYnV0IGlzIG9mIHVuc3BlY2lmaWVkXG4gIC8vIHF1YWxpdHkuXG4gIHZhciBybmRzID0gbmV3IEFycmF5KDE2KTtcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1hdGhSTkcoKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIHI7IGkgPCAxNjsgaSsrKSB7XG4gICAgICBpZiAoKGkgJiAweDAzKSA9PT0gMCkgciA9IE1hdGgucmFuZG9tKCkgKiAweDEwMDAwMDAwMDtcbiAgICAgIHJuZHNbaV0gPSByID4+PiAoKGkgJiAweDAzKSA8PCAzKSAmIDB4ZmY7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJuZHM7XG4gIH07XG59XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG4vLyAqKmB2MSgpYCAtIEdlbmVyYXRlIHRpbWUtYmFzZWQgVVVJRCoqXG4vL1xuLy8gSW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL0xpb3NLL1VVSUQuanNcbi8vIGFuZCBodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvdXVpZC5odG1sXG5cbnZhciBfbm9kZUlkO1xudmFyIF9jbG9ja3NlcTtcblxuLy8gUHJldmlvdXMgdXVpZCBjcmVhdGlvbiB0aW1lXG52YXIgX2xhc3RNU2VjcyA9IDA7XG52YXIgX2xhc3ROU2VjcyA9IDA7XG5cbi8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYnJvb2ZhL25vZGUtdXVpZCBmb3IgQVBJIGRldGFpbHNcbmZ1bmN0aW9uIHYxKG9wdGlvbnMsIGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gYnVmICYmIG9mZnNldCB8fCAwO1xuICB2YXIgYiA9IGJ1ZiB8fCBbXTtcblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgdmFyIG5vZGUgPSBvcHRpb25zLm5vZGUgfHwgX25vZGVJZDtcbiAgdmFyIGNsb2Nrc2VxID0gb3B0aW9ucy5jbG9ja3NlcSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jbG9ja3NlcSA6IF9jbG9ja3NlcTtcblxuICAvLyBub2RlIGFuZCBjbG9ja3NlcSBuZWVkIHRvIGJlIGluaXRpYWxpemVkIHRvIHJhbmRvbSB2YWx1ZXMgaWYgdGhleSdyZSBub3RcbiAgLy8gc3BlY2lmaWVkLiAgV2UgZG8gdGhpcyBsYXppbHkgdG8gbWluaW1pemUgaXNzdWVzIHJlbGF0ZWQgdG8gaW5zdWZmaWNpZW50XG4gIC8vIHN5c3RlbSBlbnRyb3B5LiAgU2VlICMxODlcbiAgaWYgKG5vZGUgPT0gbnVsbCB8fCBjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgdmFyIHNlZWRCeXRlcyA9IHJuZygpO1xuICAgIGlmIChub2RlID09IG51bGwpIHtcbiAgICAgIC8vIFBlciA0LjUsIGNyZWF0ZSBhbmQgNDgtYml0IG5vZGUgaWQsICg0NyByYW5kb20gYml0cyArIG11bHRpY2FzdCBiaXQgPSAxKVxuICAgICAgbm9kZSA9IF9ub2RlSWQgPSBbXG4gICAgICAgIHNlZWRCeXRlc1swXSB8IDB4MDEsXG4gICAgICAgIHNlZWRCeXRlc1sxXSwgc2VlZEJ5dGVzWzJdLCBzZWVkQnl0ZXNbM10sIHNlZWRCeXRlc1s0XSwgc2VlZEJ5dGVzWzVdXG4gICAgICBdO1xuICAgIH1cbiAgICBpZiAoY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuMi4yLCByYW5kb21pemUgKDE0IGJpdCkgY2xvY2tzZXFcbiAgICAgIGNsb2Nrc2VxID0gX2Nsb2Nrc2VxID0gKHNlZWRCeXRlc1s2XSA8PCA4IHwgc2VlZEJ5dGVzWzddKSAmIDB4M2ZmZjtcbiAgICB9XG4gIH1cblxuICAvLyBVVUlEIHRpbWVzdGFtcHMgYXJlIDEwMCBuYW5vLXNlY29uZCB1bml0cyBzaW5jZSB0aGUgR3JlZ29yaWFuIGVwb2NoLFxuICAvLyAoMTU4Mi0xMC0xNSAwMDowMCkuICBKU051bWJlcnMgYXJlbid0IHByZWNpc2UgZW5vdWdoIGZvciB0aGlzLCBzb1xuICAvLyB0aW1lIGlzIGhhbmRsZWQgaW50ZXJuYWxseSBhcyAnbXNlY3MnIChpbnRlZ2VyIG1pbGxpc2Vjb25kcykgYW5kICduc2VjcydcbiAgLy8gKDEwMC1uYW5vc2Vjb25kcyBvZmZzZXQgZnJvbSBtc2Vjcykgc2luY2UgdW5peCBlcG9jaCwgMTk3MC0wMS0wMSAwMDowMC5cbiAgdmFyIG1zZWNzID0gb3B0aW9ucy5tc2VjcyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5tc2VjcyA6IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuXG4gIC8vIFBlciA0LjIuMS4yLCB1c2UgY291bnQgb2YgdXVpZCdzIGdlbmVyYXRlZCBkdXJpbmcgdGhlIGN1cnJlbnQgY2xvY2tcbiAgLy8gY3ljbGUgdG8gc2ltdWxhdGUgaGlnaGVyIHJlc29sdXRpb24gY2xvY2tcbiAgdmFyIG5zZWNzID0gb3B0aW9ucy5uc2VjcyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5uc2VjcyA6IF9sYXN0TlNlY3MgKyAxO1xuXG4gIC8vIFRpbWUgc2luY2UgbGFzdCB1dWlkIGNyZWF0aW9uIChpbiBtc2VjcylcbiAgdmFyIGR0ID0gKG1zZWNzIC0gX2xhc3RNU2VjcykgKyAobnNlY3MgLSBfbGFzdE5TZWNzKS8xMDAwMDtcblxuICAvLyBQZXIgNC4yLjEuMiwgQnVtcCBjbG9ja3NlcSBvbiBjbG9jayByZWdyZXNzaW9uXG4gIGlmIChkdCA8IDAgJiYgb3B0aW9ucy5jbG9ja3NlcSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgY2xvY2tzZXEgPSBjbG9ja3NlcSArIDEgJiAweDNmZmY7XG4gIH1cblxuICAvLyBSZXNldCBuc2VjcyBpZiBjbG9jayByZWdyZXNzZXMgKG5ldyBjbG9ja3NlcSkgb3Igd2UndmUgbW92ZWQgb250byBhIG5ld1xuICAvLyB0aW1lIGludGVydmFsXG4gIGlmICgoZHQgPCAwIHx8IG1zZWNzID4gX2xhc3RNU2VjcykgJiYgb3B0aW9ucy5uc2VjcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbnNlY3MgPSAwO1xuICB9XG5cbiAgLy8gUGVyIDQuMi4xLjIgVGhyb3cgZXJyb3IgaWYgdG9vIG1hbnkgdXVpZHMgYXJlIHJlcXVlc3RlZFxuICBpZiAobnNlY3MgPj0gMTAwMDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3V1aWQudjEoKTogQ2FuXFwndCBjcmVhdGUgbW9yZSB0aGFuIDEwTSB1dWlkcy9zZWMnKTtcbiAgfVxuXG4gIF9sYXN0TVNlY3MgPSBtc2VjcztcbiAgX2xhc3ROU2VjcyA9IG5zZWNzO1xuICBfY2xvY2tzZXEgPSBjbG9ja3NlcTtcblxuICAvLyBQZXIgNC4xLjQgLSBDb252ZXJ0IGZyb20gdW5peCBlcG9jaCB0byBHcmVnb3JpYW4gZXBvY2hcbiAgbXNlY3MgKz0gMTIyMTkyOTI4MDAwMDA7XG5cbiAgLy8gYHRpbWVfbG93YFxuICB2YXIgdGwgPSAoKG1zZWNzICYgMHhmZmZmZmZmKSAqIDEwMDAwICsgbnNlY3MpICUgMHgxMDAwMDAwMDA7XG4gIGJbaSsrXSA9IHRsID4+PiAyNCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiAxNiAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdGwgJiAweGZmO1xuXG4gIC8vIGB0aW1lX21pZGBcbiAgdmFyIHRtaCA9IChtc2VjcyAvIDB4MTAwMDAwMDAwICogMTAwMDApICYgMHhmZmZmZmZmO1xuICBiW2krK10gPSB0bWggPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bWggJiAweGZmO1xuXG4gIC8vIGB0aW1lX2hpZ2hfYW5kX3ZlcnNpb25gXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMjQgJiAweGYgfCAweDEwOyAvLyBpbmNsdWRlIHZlcnNpb25cbiAgYltpKytdID0gdG1oID4+PiAxNiAmIDB4ZmY7XG5cbiAgLy8gYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgIChQZXIgNC4yLjIgLSBpbmNsdWRlIHZhcmlhbnQpXG4gIGJbaSsrXSA9IGNsb2Nrc2VxID4+PiA4IHwgMHg4MDtcblxuICAvLyBgY2xvY2tfc2VxX2xvd2BcbiAgYltpKytdID0gY2xvY2tzZXEgJiAweGZmO1xuXG4gIC8vIGBub2RlYFxuICBmb3IgKHZhciBuID0gMDsgbiA8IDY7ICsrbikge1xuICAgIGJbaSArIG5dID0gbm9kZVtuXTtcbiAgfVxuXG4gIHJldHVybiBidWYgPyBidWYgOiBieXRlc1RvVXVpZChiKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2MTtcbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbmZ1bmN0aW9uIHY0KG9wdGlvbnMsIGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gYnVmICYmIG9mZnNldCB8fCAwO1xuXG4gIGlmICh0eXBlb2Yob3B0aW9ucykgPT0gJ3N0cmluZycpIHtcbiAgICBidWYgPSBvcHRpb25zID09PSAnYmluYXJ5JyA/IG5ldyBBcnJheSgxNikgOiBudWxsO1xuICAgIG9wdGlvbnMgPSBudWxsO1xuICB9XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBybmRzID0gb3B0aW9ucy5yYW5kb20gfHwgKG9wdGlvbnMucm5nIHx8IHJuZykoKTtcblxuICAvLyBQZXIgNC40LCBzZXQgYml0cyBmb3IgdmVyc2lvbiBhbmQgYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgXG4gIHJuZHNbNl0gPSAocm5kc1s2XSAmIDB4MGYpIHwgMHg0MDtcbiAgcm5kc1s4XSA9IChybmRzWzhdICYgMHgzZikgfCAweDgwO1xuXG4gIC8vIENvcHkgYnl0ZXMgdG8gYnVmZmVyLCBpZiBwcm92aWRlZFxuICBpZiAoYnVmKSB7XG4gICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IDE2OyArK2lpKSB7XG4gICAgICBidWZbaSArIGlpXSA9IHJuZHNbaWldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWYgfHwgYnl0ZXNUb1V1aWQocm5kcyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjQ7XG4iLCIvKlxyXG5XaWxkRW1pdHRlci5qcyBpcyBhIHNsaW0gbGl0dGxlIGV2ZW50IGVtaXR0ZXIgYnkgQGhlbnJpa2pvcmV0ZWcgbGFyZ2VseSBiYXNlZFxyXG5vbiBAdmlzaW9ubWVkaWEncyBFbWl0dGVyIGZyb20gVUkgS2l0LlxyXG5cclxuV2h5PyBJIHdhbnRlZCBpdCBzdGFuZGFsb25lLlxyXG5cclxuSSBhbHNvIHdhbnRlZCBzdXBwb3J0IGZvciB3aWxkY2FyZCBlbWl0dGVycyBsaWtlIHRoaXM6XHJcblxyXG5lbWl0dGVyLm9uKCcqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgb3RoZXIsIGV2ZW50LCBwYXlsb2Fkcykge1xyXG5cclxufSk7XHJcblxyXG5lbWl0dGVyLm9uKCdzb21lbmFtZXNwYWNlKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcblBsZWFzZSBub3RlIHRoYXQgY2FsbGJhY2tzIHRyaWdnZXJlZCBieSB3aWxkY2FyZCByZWdpc3RlcmVkIGV2ZW50cyBhbHNvIGdldFxyXG50aGUgZXZlbnQgbmFtZSBhcyB0aGUgZmlyc3QgYXJndW1lbnQuXHJcbiovXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IFdpbGRFbWl0dGVyO1xyXG5cclxuZnVuY3Rpb24gV2lsZEVtaXR0ZXIoKSB7IH1cclxuXHJcbldpbGRFbWl0dGVyLm1peGluID0gZnVuY3Rpb24gKGNvbnN0cnVjdG9yKSB7XHJcbiAgICB2YXIgcHJvdG90eXBlID0gY29uc3RydWN0b3IucHJvdG90eXBlIHx8IGNvbnN0cnVjdG9yO1xyXG5cclxuICAgIHByb3RvdHlwZS5pc1dpbGRFbWl0dGVyPSB0cnVlO1xyXG5cclxuICAgIC8vIExpc3RlbiBvbiB0aGUgZ2l2ZW4gYGV2ZW50YCB3aXRoIGBmbmAuIFN0b3JlIGEgZ3JvdXAgbmFtZSBpZiBwcmVzZW50LlxyXG4gICAgcHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXHJcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcclxuICAgICAgICBmdW5jLl9ncm91cE5hbWUgPSBncm91cDtcclxuICAgICAgICAodGhpcy5jYWxsYmFja3NbZXZlbnRdID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdIHx8IFtdKS5wdXNoKGZ1bmMpO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBBZGRzIGFuIGBldmVudGAgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBzaW5nbGVcclxuICAgIC8vIHRpbWUgdGhlbiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQuXHJcbiAgICBwcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xyXG4gICAgICAgIHZhciBzZWxmID0gdGhpcyxcclxuICAgICAgICAgICAgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXHJcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcclxuICAgICAgICBmdW5jdGlvbiBvbigpIHtcclxuICAgICAgICAgICAgc2VsZi5vZmYoZXZlbnQsIG9uKTtcclxuICAgICAgICAgICAgZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLm9uKGV2ZW50LCBncm91cCwgb24pO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBVbmJpbmRzIGFuIGVudGlyZSBncm91cFxyXG4gICAgcHJvdG90eXBlLnJlbGVhc2VHcm91cCA9IGZ1bmN0aW9uIChncm91cE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLCBpLCBsZW4sIGhhbmRsZXJzO1xyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBoYW5kbGVycyA9IHRoaXMuY2FsbGJhY2tzW2l0ZW1dO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBoYW5kbGVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICAgICAgICAgICAgaWYgKGhhbmRsZXJzW2ldLl9ncm91cE5hbWUgPT09IGdyb3VwTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coJ3JlbW92aW5nJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0IGFuZCBzaG9ydGVuIHRoZSBhcnJheSB3ZSdyZSBsb29waW5nIHRocm91Z2hcclxuICAgICAgICAgICAgICAgICAgICBoYW5kbGVycy5zcGxpY2UoaSwgMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaS0tO1xyXG4gICAgICAgICAgICAgICAgICAgIGxlbi0tO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBSZW1vdmUgdGhlIGdpdmVuIGNhbGxiYWNrIGZvciBgZXZlbnRgIG9yIGFsbFxyXG4gICAgLy8gcmVnaXN0ZXJlZCBjYWxsYmFja3MuXHJcbiAgICBwcm90b3R5cGUub2ZmID0gZnVuY3Rpb24gKGV2ZW50LCBmbikge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcclxuICAgICAgICAgICAgaTtcclxuXHJcbiAgICAgICAgaWYgKCFjYWxsYmFja3MpIHJldHVybiB0aGlzO1xyXG5cclxuICAgICAgICAvLyByZW1vdmUgYWxsIGhhbmRsZXJzXHJcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcclxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyByZW1vdmUgc3BlY2lmaWMgaGFuZGxlclxyXG4gICAgICAgIGkgPSBjYWxsYmFja3MuaW5kZXhPZihmbik7XHJcbiAgICAgICAgY2FsbGJhY2tzLnNwbGljZShpLCAxKTtcclxuICAgICAgICBpZiAoY2FsbGJhY2tzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8vIEVtaXQgYGV2ZW50YCB3aXRoIHRoZSBnaXZlbiBhcmdzLlxyXG4gICAgLy8gYWxzbyBjYWxscyBhbnkgYCpgIGhhbmRsZXJzXHJcbiAgICBwcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIChldmVudCkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXHJcbiAgICAgICAgICAgIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcclxuICAgICAgICAgICAgc3BlY2lhbENhbGxiYWNrcyA9IHRoaXMuZ2V0V2lsZGNhcmRDYWxsYmFja3MoZXZlbnQpLFxyXG4gICAgICAgICAgICBpLFxyXG4gICAgICAgICAgICBsZW4sXHJcbiAgICAgICAgICAgIGl0ZW0sXHJcbiAgICAgICAgICAgIGxpc3RlbmVycztcclxuXHJcbiAgICAgICAgaWYgKGNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBjYWxsYmFja3Muc2xpY2UoKTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoc3BlY2lhbENhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBsZW4gPSBzcGVjaWFsQ2FsbGJhY2tzLmxlbmd0aDtcclxuICAgICAgICAgICAgbGlzdGVuZXJzID0gc3BlY2lhbENhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgW2V2ZW50XS5jb25jYXQoYXJncykpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gSGVscGVyIGZvciBmb3IgZmluZGluZyBzcGVjaWFsIHdpbGRjYXJkIGV2ZW50IGhhbmRsZXJzIHRoYXQgbWF0Y2ggdGhlIGV2ZW50XHJcbiAgICBwcm90b3R5cGUuZ2V0V2lsZGNhcmRDYWxsYmFja3MgPSBmdW5jdGlvbiAoZXZlbnROYW1lKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaXRlbSxcclxuICAgICAgICAgICAgc3BsaXQsXHJcbiAgICAgICAgICAgIHJlc3VsdCA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgc3BsaXQgPSBpdGVtLnNwbGl0KCcqJyk7XHJcbiAgICAgICAgICAgIGlmIChpdGVtID09PSAnKicgfHwgKHNwbGl0Lmxlbmd0aCA9PT0gMiAmJiBldmVudE5hbWUuc2xpY2UoMCwgc3BsaXRbMF0ubGVuZ3RoKSA9PT0gc3BsaXRbMF0pKSB7XHJcbiAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KHRoaXMuY2FsbGJhY2tzW2l0ZW1dKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfTtcclxuXHJcbn07XHJcblxyXG5XaWxkRW1pdHRlci5taXhpbihXaWxkRW1pdHRlcik7XHJcbiIsIi8qIVxuICogRXZlbnRFbWl0dGVyIHY1LjIuNCAtIGdpdC5pby9lZVxuICogVW5saWNlbnNlIC0gaHR0cDovL3VubGljZW5zZS5vcmcvXG4gKiBPbGl2ZXIgQ2FsZHdlbGwgLSBodHRwOi8vb2xpLm1lLnVrL1xuICogQHByZXNlcnZlXG4gKi9cblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuICAgICd1c2Ugc3RyaWN0JztcblxuICAgIC8qKlxuICAgICAqIENsYXNzIGZvciBtYW5hZ2luZyBldmVudHMuXG4gICAgICogQ2FuIGJlIGV4dGVuZGVkIHRvIHByb3ZpZGUgZXZlbnQgZnVuY3Rpb25hbGl0eSBpbiBvdGhlciBjbGFzc2VzLlxuICAgICAqXG4gICAgICogQGNsYXNzIEV2ZW50RW1pdHRlciBNYW5hZ2VzIGV2ZW50IHJlZ2lzdGVyaW5nIGFuZCBlbWl0dGluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7fVxuXG4gICAgLy8gU2hvcnRjdXRzIHRvIGltcHJvdmUgc3BlZWQgYW5kIHNpemVcbiAgICB2YXIgcHJvdG8gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlO1xuICAgIHZhciBvcmlnaW5hbEdsb2JhbFZhbHVlID0gZXhwb3J0cy5FdmVudEVtaXR0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyB0aGUgaW5kZXggb2YgdGhlIGxpc3RlbmVyIGZvciB0aGUgZXZlbnQgaW4gaXRzIHN0b3JhZ2UgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IGxpc3RlbmVycyBBcnJheSBvZiBsaXN0ZW5lcnMgdG8gc2VhcmNoIHRocm91Z2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGxvb2sgZm9yLlxuICAgICAqIEByZXR1cm4ge051bWJlcn0gSW5kZXggb2YgdGhlIHNwZWNpZmllZCBsaXN0ZW5lciwgLTEgaWYgbm90IGZvdW5kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVycywgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzW2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFsaWFzIGEgbWV0aG9kIHdoaWxlIGtlZXBpbmcgdGhlIGNvbnRleHQgY29ycmVjdCwgdG8gYWxsb3cgZm9yIG92ZXJ3cml0aW5nIG9mIHRhcmdldCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGFsaWFzZWQgbWV0aG9kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWxpYXMobmFtZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gYWxpYXNDbG9zdXJlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbbmFtZV0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBsaXN0ZW5lciBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaWxsIGluaXRpYWxpc2UgdGhlIGV2ZW50IG9iamVjdCBhbmQgbGlzdGVuZXIgYXJyYXlzIGlmIHJlcXVpcmVkLlxuICAgICAqIFdpbGwgcmV0dXJuIGFuIG9iamVjdCBpZiB5b3UgdXNlIGEgcmVnZXggc2VhcmNoLiBUaGUgb2JqZWN0IGNvbnRhaW5zIGtleXMgZm9yIGVhY2ggbWF0Y2hlZCBldmVudC4gU28gL2JhW3J6XS8gbWlnaHQgcmV0dXJuIGFuIG9iamVjdCBjb250YWluaW5nIGJhciBhbmQgYmF6LiBCdXQgb25seSBpZiB5b3UgaGF2ZSBlaXRoZXIgZGVmaW5lZCB0aGVtIHdpdGggZGVmaW5lRXZlbnQgb3IgYWRkZWQgc29tZSBsaXN0ZW5lcnMgdG8gdGhlbS5cbiAgICAgKiBFYWNoIHByb3BlcnR5IGluIHRoZSBvYmplY3QgcmVzcG9uc2UgaXMgYW4gYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfE9iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgdGhlIGV2ZW50LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldExpc3RlbmVycyhldnQpIHtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmV0dXJuIGEgY29uY2F0ZW5hdGVkIGFycmF5IG9mIGFsbCBtYXRjaGluZyBldmVudHMgaWZcbiAgICAgICAgLy8gdGhlIHNlbGVjdG9yIGlzIGEgcmVndWxhciBleHByZXNzaW9uLlxuICAgICAgICBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2Vba2V5XSA9IGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0gZXZlbnRzW2V2dF0gfHwgKGV2ZW50c1tldnRdID0gW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGxpc3Qgb2YgbGlzdGVuZXIgb2JqZWN0cyBhbmQgZmxhdHRlbnMgaXQgaW50byBhIGxpc3Qgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3RbXX0gbGlzdGVuZXJzIFJhdyBsaXN0ZW5lciBvYmplY3RzLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW119IEp1c3QgdGhlIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKi9cbiAgICBwcm90by5mbGF0dGVuTGlzdGVuZXJzID0gZnVuY3Rpb24gZmxhdHRlbkxpc3RlbmVycyhsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGZsYXRMaXN0ZW5lcnMgPSBbXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgZmxhdExpc3RlbmVycy5wdXNoKGxpc3RlbmVyc1tpXS5saXN0ZW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmxhdExpc3RlbmVycztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgcmVxdWVzdGVkIGxpc3RlbmVycyB2aWEgZ2V0TGlzdGVuZXJzIGJ1dCB3aWxsIGFsd2F5cyByZXR1cm4gdGhlIHJlc3VsdHMgaW5zaWRlIGFuIG9iamVjdC4gVGhpcyBpcyBtYWlubHkgZm9yIGludGVybmFsIHVzZSBidXQgb3RoZXJzIG1heSBmaW5kIGl0IHVzZWZ1bC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciBhbiBldmVudCBpbiBhbiBvYmplY3QuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzQXNPYmplY3QgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnNBc09iamVjdChldnQpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBpZiAobGlzdGVuZXJzIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICByZXNwb25zZVtldnRdID0gbGlzdGVuZXJzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlIHx8IGxpc3RlbmVycztcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gaXNWYWxpZExpc3RlbmVyIChsaXN0ZW5lcikge1xuICAgICAgICBpZiAodHlwZW9mIGxpc3RlbmVyID09PSAnZnVuY3Rpb24nIHx8IGxpc3RlbmVyIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9IGVsc2UgaWYgKGxpc3RlbmVyICYmIHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIubGlzdGVuZXIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBsaXN0ZW5lciBmdW5jdGlvbiB0byB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFRoZSBsaXN0ZW5lciB3aWxsIG5vdCBiZSBhZGRlZCBpZiBpdCBpcyBhIGR1cGxpY2F0ZS5cbiAgICAgKiBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGl0IGlzIGNhbGxlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSB0aGVuIHRoZSBsaXN0ZW5lciB3aWxsIGJlIGFkZGVkIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICghaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJJc1dyYXBwZWQgPSB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnB1c2gobGlzdGVuZXJJc1dyYXBwZWQgPyBsaXN0ZW5lciA6IHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgICAgICAgICBvbmNlOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZExpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub24gPSBhbGlhcygnYWRkTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIFNlbWktYWxpYXMgb2YgYWRkTGlzdGVuZXIuIEl0IHdpbGwgYWRkIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlXG4gICAgICogYXV0b21hdGljYWxseSByZW1vdmVkIGFmdGVyIGl0cyBmaXJzdCBleGVjdXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZE9uY2VMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZE9uY2VMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZExpc3RlbmVyKGV2dCwge1xuICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgb25jZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkT25jZUxpc3RlbmVyLlxuICAgICAqL1xuICAgIHByb3RvLm9uY2UgPSBhbGlhcygnYWRkT25jZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmVzIGFuIGV2ZW50IG5hbWUuIFRoaXMgaXMgcmVxdWlyZWQgaWYgeW91IHdhbnQgdG8gdXNlIGEgcmVnZXggdG8gYWRkIGEgbGlzdGVuZXIgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIElmIHlvdSBkb24ndCBkbyB0aGlzIHRoZW4gaG93IGRvIHlvdSBleHBlY3QgaXQgdG8ga25vdyB3aGF0IGV2ZW50IHRvIGFkZCB0bz8gU2hvdWxkIGl0IGp1c3QgYWRkIHRvIGV2ZXJ5IHBvc3NpYmxlIG1hdGNoIGZvciBhIHJlZ2V4PyBOby4gVGhhdCBpcyBzY2FyeSBhbmQgYmFkLlxuICAgICAqIFlvdSBuZWVkIHRvIHRlbGwgaXQgd2hhdCBldmVudCBuYW1lcyBzaG91bGQgYmUgbWF0Y2hlZCBieSBhIHJlZ2V4LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBjcmVhdGUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnQgPSBmdW5jdGlvbiBkZWZpbmVFdmVudChldnQpIHtcbiAgICAgICAgdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFVzZXMgZGVmaW5lRXZlbnQgdG8gZGVmaW5lIG11bHRpcGxlIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nW119IGV2dHMgQW4gYXJyYXkgb2YgZXZlbnQgbmFtZXMgdG8gZGVmaW5lLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50cyA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50cyhldnRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXZ0cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgdGhpcy5kZWZpbmVFdmVudChldnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIGZyb20gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaGVuIHBhc3NlZCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSwgaXQgd2lsbCByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byByZW1vdmUgZnJvbSB0aGUgZXZlbnQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBpbmRleDtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcik7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUxpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub2ZmID0gYWxpYXMoJ3JlbW92ZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBhZGQgdGhlIGFycmF5IG9mIGxpc3RlbmVycyB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICogWWVhaCwgdGhpcyBmdW5jdGlvbiBkb2VzIHF1aXRlIGEgYml0LiBUaGF0J3MgcHJvYmFibHkgYSBiYWQgdGhpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyhmYWxzZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byByZW1vdmUgdGhlIGxpc3RlbmVycyBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byByZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXJzID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnModHJ1ZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBFZGl0cyBsaXN0ZW5lcnMgaW4gYnVsay4gVGhlIGFkZExpc3RlbmVycyBhbmQgcmVtb3ZlTGlzdGVuZXJzIG1ldGhvZHMgYm90aCB1c2UgdGhpcyB0byBkbyB0aGVpciBqb2IuIFlvdSBzaG91bGQgcmVhbGx5IHVzZSB0aG9zZSBpbnN0ZWFkLCB0aGlzIGlzIGEgbGl0dGxlIGxvd2VyIGxldmVsLlxuICAgICAqIFRoZSBmaXJzdCBhcmd1bWVudCB3aWxsIGRldGVybWluZSBpZiB0aGUgbGlzdGVuZXJzIGFyZSByZW1vdmVkICh0cnVlKSBvciBhZGRlZCAoZmFsc2UpLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHlvdSBjYW4gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkL3JlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gbWFuaXB1bGF0ZSB0aGUgbGlzdGVuZXJzIG9mIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVtb3ZlIFRydWUgaWYgeW91IHdhbnQgdG8gcmVtb3ZlIGxpc3RlbmVycywgZmFsc2UgaWYgeW91IHdhbnQgdG8gYWRkLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkL3JlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5tYW5pcHVsYXRlTGlzdGVuZXJzID0gZnVuY3Rpb24gbWFuaXB1bGF0ZUxpc3RlbmVycyhyZW1vdmUsIGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgdmFsdWU7XG4gICAgICAgIHZhciBzaW5nbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVyIDogdGhpcy5hZGRMaXN0ZW5lcjtcbiAgICAgICAgdmFyIG11bHRpcGxlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lcnMgOiB0aGlzLmFkZExpc3RlbmVycztcblxuICAgICAgICAvLyBJZiBldnQgaXMgYW4gb2JqZWN0IHRoZW4gcGFzcyBlYWNoIG9mIGl0cyBwcm9wZXJ0aWVzIHRvIHRoaXMgbWV0aG9kXG4gICAgICAgIGlmICh0eXBlb2YgZXZ0ID09PSAnb2JqZWN0JyAmJiAhKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgICAgICAgIGZvciAoaSBpbiBldnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZ0Lmhhc093blByb3BlcnR5KGkpICYmICh2YWx1ZSA9IGV2dFtpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGFzcyB0aGUgc2luZ2xlIGxpc3RlbmVyIHN0cmFpZ2h0IHRocm91Z2ggdG8gdGhlIHNpbmd1bGFyIG1ldGhvZFxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgcGFzcyBiYWNrIHRvIHRoZSBtdWx0aXBsZSBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBTbyBldnQgbXVzdCBiZSBhIHN0cmluZ1xuICAgICAgICAgICAgLy8gQW5kIGxpc3RlbmVycyBtdXN0IGJlIGFuIGFycmF5IG9mIGxpc3RlbmVyc1xuICAgICAgICAgICAgLy8gTG9vcCBvdmVyIGl0IGFuZCBwYXNzIGVhY2ggb25lIHRvIHRoZSBtdWx0aXBsZSBtZXRob2RcbiAgICAgICAgICAgIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGV2dCwgbGlzdGVuZXJzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgZnJvbSBhIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBJZiB5b3UgZG8gbm90IHNwZWNpZnkgYW4gZXZlbnQgdGhlbiBhbGwgbGlzdGVuZXJzIHdpbGwgYmUgcmVtb3ZlZC5cbiAgICAgKiBUaGF0IG1lYW5zIGV2ZXJ5IGV2ZW50IHdpbGwgYmUgZW1wdGllZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ2V4IHRvIHJlbW92ZSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IFtldnRdIE9wdGlvbmFsIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvci4gV2lsbCByZW1vdmUgZnJvbSBldmVyeSBldmVudCBpZiBub3QgcGFzc2VkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24gcmVtb3ZlRXZlbnQoZXZ0KSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mIGV2dDtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJlbW92ZSBkaWZmZXJlbnQgdGhpbmdzIGRlcGVuZGluZyBvbiB0aGUgc3RhdGUgb2YgZXZ0XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbZXZ0XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgZXZlbnRzIG1hdGNoaW5nIHRoZSByZWdleC5cbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBpbiBhbGwgZXZlbnRzXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUV2ZW50LlxuICAgICAqXG4gICAgICogQWRkZWQgdG8gbWlycm9yIHRoZSBub2RlIEFQSS5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBhbGlhcygncmVtb3ZlRXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGFuIGV2ZW50IG9mIHlvdXIgY2hvaWNlLlxuICAgICAqIFdoZW4gZW1pdHRlZCwgZXZlcnkgbGlzdGVuZXIgYXR0YWNoZWQgdG8gdGhhdCBldmVudCB3aWxsIGJlIGV4ZWN1dGVkLlxuICAgICAqIElmIHlvdSBwYXNzIHRoZSBvcHRpb25hbCBhcmd1bWVudCBhcnJheSB0aGVuIHRob3NlIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCB0byBldmVyeSBsaXN0ZW5lciB1cG9uIGV4ZWN1dGlvbi5cbiAgICAgKiBCZWNhdXNlIGl0IHVzZXMgYGFwcGx5YCwgeW91ciBhcnJheSBvZiBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgYXMgaWYgeW91IHdyb3RlIHRoZW0gb3V0IHNlcGFyYXRlbHkuXG4gICAgICogU28gdGhleSB3aWxsIG5vdCBhcnJpdmUgd2l0aGluIHRoZSBhcnJheSBvbiB0aGUgb3RoZXIgc2lkZSwgdGhleSB3aWxsIGJlIHNlcGFyYXRlLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthcmdzXSBPcHRpb25hbCBhcnJheSBvZiBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdEV2ZW50ID0gZnVuY3Rpb24gZW1pdEV2ZW50KGV2dCwgYXJncykge1xuICAgICAgICB2YXIgbGlzdGVuZXJzTWFwID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJzO1xuICAgICAgICB2YXIgbGlzdGVuZXI7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzTWFwKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzTWFwLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnNNYXBba2V5XS5zbGljZSgwKTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHNoYWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkIGVpdGhlciB3aXRoIGEgYmFzaWMgY2FsbCBvciBhbiBhcHBseSBpZiB0aGVyZSBpcyBhbiBhcmdzIGFycmF5XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChsaXN0ZW5lci5vbmNlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBsaXN0ZW5lci5saXN0ZW5lci5hcHBseSh0aGlzLCBhcmdzIHx8IFtdKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgPT09IHRoaXMuX2dldE9uY2VSZXR1cm5WYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGVtaXRFdmVudFxuICAgICAqL1xuICAgIHByb3RvLnRyaWdnZXIgPSBhbGlhcygnZW1pdEV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBTdWJ0bHkgZGlmZmVyZW50IGZyb20gZW1pdEV2ZW50IGluIHRoYXQgaXQgd2lsbCBwYXNzIGl0cyBhcmd1bWVudHMgb24gdG8gdGhlIGxpc3RlbmVycywgYXMgb3Bwb3NlZCB0byB0YWtpbmcgYSBzaW5nbGUgYXJyYXkgb2YgYXJndW1lbnRzIHRvIHBhc3Mgb24uXG4gICAgICogQXMgd2l0aCBlbWl0RXZlbnQsIHlvdSBjYW4gcGFzcyBhIHJlZ2V4IGluIHBsYWNlIG9mIHRoZSBldmVudCBuYW1lIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gT3B0aW9uYWwgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdCA9IGZ1bmN0aW9uIGVtaXQoZXZ0KSB7XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW1pdEV2ZW50KGV2dCwgYXJncyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmIGFcbiAgICAgKiBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhlIG9uZSBzZXQgaGVyZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZFxuICAgICAqIGFmdGVyIGV4ZWN1dGlvbi4gVGhpcyB2YWx1ZSBkZWZhdWx0cyB0byB0cnVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbmV3IHZhbHVlIHRvIGNoZWNrIGZvciB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uc2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gc2V0T25jZVJldHVyblZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX29uY2VSZXR1cm5WYWx1ZSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWZcbiAgICAgKiB0aGUgbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoaXMgb25lIHRoZW4gaXQgc2hvdWxkIGJlIHJlbW92ZWRcbiAgICAgKiBhdXRvbWF0aWNhbGx5LiBJdCB3aWxsIHJldHVybiB0cnVlIGJ5IGRlZmF1bHQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHsqfEJvb2xlYW59IFRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGZvciBvciB0aGUgZGVmYXVsdCwgdHJ1ZS5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gX2dldE9uY2VSZXR1cm5WYWx1ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkoJ19vbmNlUmV0dXJuVmFsdWUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29uY2VSZXR1cm5WYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGV2ZW50cyBvYmplY3QgYW5kIGNyZWF0ZXMgb25lIGlmIHJlcXVpcmVkLlxuICAgICAqXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgZXZlbnRzIHN0b3JhZ2Ugb2JqZWN0LlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRFdmVudHMgPSBmdW5jdGlvbiBfZ2V0RXZlbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXZlbnRzIHx8ICh0aGlzLl9ldmVudHMgPSB7fSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJldmVydHMgdGhlIGdsb2JhbCB7QGxpbmsgRXZlbnRFbWl0dGVyfSB0byBpdHMgcHJldmlvdXMgdmFsdWUgYW5kIHJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhpcyB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IE5vbiBjb25mbGljdGluZyBFdmVudEVtaXR0ZXIgY2xhc3MuXG4gICAgICovXG4gICAgRXZlbnRFbWl0dGVyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiBub0NvbmZsaWN0KCkge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IG9yaWdpbmFsR2xvYmFsVmFsdWU7XG4gICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgfTtcblxuICAgIC8vIEV4cG9zZSB0aGUgY2xhc3MgZWl0aGVyIHZpYSBBTUQsIENvbW1vbkpTIG9yIHRoZSBnbG9iYWwgb2JqZWN0XG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKXtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG59KHRoaXMgfHwge30pKTtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdS9PcGVuVmlkdSc7XG5cbmlmICh3aW5kb3cpIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICB3aW5kb3dbJ09wZW5WaWR1J10gPSBPcGVuVmlkdTtcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmRlYnVnKCghIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCcgOiAnUmVtb3RlJyksICdjYW5kaWRhdGUgZm9yJyxcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkLCBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcblxuICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ29uSWNlQ2FuZGlkYXRlJywge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJ1xuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0UmVtb3RlU3RyZWFtcyhvcHRpb25zOiBTdHJlYW1PcHRpb25zU2VydmVyW10pOiB2b2lkIHtcblxuICAgICAgICAvLyBUaGlzIGlzIHJlYWR5IGZvciBzdXBwb3J0aW5nIG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb24gb2JqZWN0LiBSaWdodCBub3cgdGhlIGxvb3Agd2lsbCBhbHdheXMgcnVuIGp1c3Qgb25jZVxuICAgICAgICAvLyB0aGlzLnN0cmVhbSBzaG91bGQgYWxzbyBiZSByZXBsYWNlZCBieSBhIGNvbGxlY3Rpb24gb2Ygc3RyZWFtcyB0byBzdXBwb3J0IG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb25cbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IG9wdHMuaWQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogdGhpcyxcbiAgICAgICAgICAgICAgICBmcmFtZVJhdGU6IG9wdHMuZnJhbWVSYXRlLFxuICAgICAgICAgICAgICAgIHJlY3ZBdWRpbzogb3B0cy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICByZWN2VmlkZW86IG9wdHMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyZWFtKHRoaXMuc2Vzc2lvbiwgc3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgIHRoaXMuYWRkU3RyZWFtKHN0cmVhbSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnQ29ubmVjdGlvbicgd2l0aCAnY29ubmVjdGlvbklkJyBbXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArICddIGlzIG5vdyBjb25maWd1cmVkIGZvciByZWNlaXZpbmcgU3RyZWFtcyB3aXRoIG9wdGlvbnM6ICcsIHRoaXMuc3RyZWFtLmluYm91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkU3RyZWFtKHN0cmVhbTogU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5jb25uZWN0aW9uID0gdGhpcztcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZVN0cmVhbShzdHJlYW1JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IExvY2FsUmVjb3JkZXJTdGF0ZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmRlY2xhcmUgdmFyIE1lZGlhUmVjb3JkZXI6IGFueTtcblxuXG4vKipcbiAqIEVhc3kgcmVjb3JkaW5nIG9mIFtbU3RyZWFtXV0gb2JqZWN0cyBzdHJhaWdodGF3YXkgZnJvbSB0aGUgYnJvd3Nlci5cbiAqXG4gKiA+IFdBUk5JTkc6IFBlcmZvcm1pbmcgYnJvd3NlciBsb2NhbCByZWNvcmRpbmcgb2YgKipyZW1vdGUgc3RyZWFtcyoqIG1heSBjYXVzZSBzb21lIHRyb3VibGVzLiBBIGxvbmcgd2FpdGluZyB0aW1lIG1heSBiZSByZXF1aXJlZCBhZnRlciBjYWxsaW5nIF9Mb2NhbFJlY29yZGVyLnN0b3AoKV8gaW4gdGhpcyBjYXNlXG4gKi9cbmV4cG9ydCBjbGFzcyBMb2NhbFJlY29yZGVyIHtcblxuICAgIHN0YXRlOiBMb2NhbFJlY29yZGVyU3RhdGU7XG5cbiAgICBwcml2YXRlIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuICAgIHByaXZhdGUgbWVkaWFSZWNvcmRlcjogYW55O1xuICAgIHByaXZhdGUgY2h1bmtzOiBhbnlbXSA9IFtdO1xuICAgIHByaXZhdGUgYmxvYjogQmxvYjtcbiAgICBwcml2YXRlIGNvdW50ID0gMDtcbiAgICBwcml2YXRlIGlkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXdTcmM6IHN0cmluZztcbiAgICBwcml2YXRlIGh0bWxQYXJlbnRFbGVtZW50SWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlldzogSFRNTFZpZGVvRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gKCEhdGhpcy5zdHJlYW0uY29ubmVjdGlvbikgPyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA6ICdkZWZhdWx0LWNvbm5lY3Rpb24nO1xuICAgICAgICB0aGlzLmlkID0gdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXycgKyB0aGlzLmNvbm5lY3Rpb25JZCArICdfbG9jYWxyZWNvcmQnO1xuICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU3RhcnRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQURZYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdGFydGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZWNvcmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdHJ5IHtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlY29yZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQURZXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuY2xlYW4oKVxcJyBvciBpbml0IGEgbmV3IExvY2FsUmVjb3JkZXIgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIlN0YXJ0aW5nIGxvY2FsIHJlY29yZGluZyBvZiBzdHJlYW0gJ1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyBcIicgb2YgY29ubmVjdGlvbiAnXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArIFwiJ1wiKTtcblxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgb3B0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDknKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz12cDknIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JyB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDgnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz12cDgnIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1VzaW5nIG1pbWVUeXBlICcgKyBvcHRpb25zLm1pbWVUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIodGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdpc1R5cGVTdXBwb3J0ZWQgaXMgbm90IHN1cHBvcnRlZCwgdXNpbmcgZGVmYXVsdCBjb2RlY3MgZm9yIGJyb3dzZXInKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIodGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXJ0KDEwKTtcblxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmRhdGFhdmFpbGFibGUgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY2h1bmtzLnB1c2goZS5kYXRhKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmVycm9yID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIGVycm9yOiAnLCBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0YXJ0ID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0YXJ0ZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnBhdXNlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHBhdXNlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25yZXN1bWUgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcmVzdW1lZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub253YXJuaW5nID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciB3YXJuaW5nOiAnICsgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIHJlc29sdmUoKTtcblxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEVuZHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYCBvciBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgRklOSVNIRURgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0b3BwZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHN0b3AoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIG9yIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0b3AoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUGF1c2VzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2AuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFBBVVNFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyB3YXMgc3VjY2Vzc2Z1bGx5IHBhdXNlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcGF1c2UoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC5wYXVzZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgb3IgXFwnTG9jYWxSZWNvcmRlci5yZXN1bWUoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5wYXVzZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXN1bWVzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFBBVVNFRGAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyB3YXMgc3VjY2Vzc2Z1bGx5IHJlc3VtZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlc3VtZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlc3VtZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnBhdXNlKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucmVzdW1lKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHJldmlld3MgdGhlIHJlY29yZGluZywgYXBwZW5kaW5nIGEgbmV3IEhUTUxWaWRlb0VsZW1lbnQgdG8gZWxlbWVudCB3aXRoIGlkIGBwYXJlbnRJZGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBwcmV2aWV3KHBhcmVudEVsZW1lbnQpOiBIVE1MVmlkZW9FbGVtZW50IHtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnByZXZpZXcoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuaWQgPSB0aGlzLmlkO1xuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5hdXRvcGxheSA9IHRydWU7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBwYXJlbnRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhpcy5odG1sUGFyZW50RWxlbWVudElkID0gcGFyZW50RWxlbWVudDtcblxuICAgICAgICAgICAgY29uc3QgcGFyZW50RWxlbWVudERvbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBhcmVudEVsZW1lbnQpO1xuICAgICAgICAgICAgaWYgKHBhcmVudEVsZW1lbnREb20pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnREb20uYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5odG1sUGFyZW50RWxlbWVudElkID0gcGFyZW50RWxlbWVudC5pZDtcbiAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5zcmMgPSB0aGlzLnZpZGVvUHJldmlld1NyYztcblxuICAgICAgICByZXR1cm4gdGhpcy52aWRlb1ByZXZpZXc7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBHcmFjZWZ1bGx5IHN0b3BzIGFuZCBjbGVhbnMgdGhlIGN1cnJlbnQgcmVjb3JkaW5nIChXQVJOSU5HOiBpdCBpcyBjb21wbGV0ZWx5IGRpc21pc3NlZCkuIFNldHMgW1tzdGF0ZV1dIHRvIGBSRUFEWWAgc28gdGhlIHJlY29yZGluZyBjYW4gc3RhcnQgYWdhaW5cbiAgICAgKi9cbiAgICBjbGVhbigpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZiA9ICgpID0+IHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmJsb2I7XG4gICAgICAgICAgICB0aGlzLmNodW5rcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IDA7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tZWRpYVJlY29yZGVyO1xuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkcgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgdGhpcy5zdG9wKCkudGhlbigoKSA9PiBmKCkpLmNhdGNoKCgpID0+IGYoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIERvd25sb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gdGhyb3VnaCB0aGUgYnJvd3Nlci4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIGRvd25sb2FkKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLmRvd25sb2FkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgYTogSFRNTEFuY2hvckVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICAgICAgICBhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xuXG4gICAgICAgICAgICBjb25zdCB1cmwgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgYS5ocmVmID0gdXJsO1xuICAgICAgICAgICAgYS5kb3dubG9hZCA9IHRoaXMuaWQgKyAnLndlYm0nO1xuICAgICAgICAgICAgYS5jbGljaygpO1xuICAgICAgICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcblxuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHJhdyBCbG9iIGZpbGUuIE1ldGhvZHMgcHJldmlldywgZG93bmxvYWQsIHVwbG9hZEFzQmluYXJ5IGFuZCB1cGxvYWRBc011bHRpcGFydGZpbGUgdXNlIHRoaXMgc2FtZSBmaWxlIHRvIHBlcmZvcm0gdGhlaXIgc3BlY2lmaWMgYWN0aW9ucy4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIGdldEJsb2IoKTogQmxvYiB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignQ2FsbCBcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgYmVmb3JlIGdldHRpbmcgQmxvYiBmaWxlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmxvYjtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBsb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gYXMgYSBiaW5hcnkgZmlsZSBwZXJmb3JtaW5nIGFuIEhUVFAvUE9TVCBvcGVyYXRpb24gdG8gVVJMIGBlbmRwb2ludGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGAuIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBjYW4gYmUgcGFzc2VkIGFzIHNlY29uZCBwYXJhbWV0ZXIuIEZvciBleGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHZhciBoZWFkZXJzID0ge1xuICAgICAqICBcIkNvb2tpZVwiOiBcIiRWZXJzaW9uPTE7IFNraW49bmV3O1wiLFxuICAgICAqICBcIkF1dGhvcml6YXRpb25cIjpcIkJhc2ljIFFXeGhaR3BianB1SUhObGN0WlE9PVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB3aXRoIHRoZSBgaHR0cC5yZXNwb25zZVRleHRgIGZyb20gc2VydmVyIGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggdGhlIGZhaWxlZCBgaHR0cC5zdGF0dXNgIGlmIG5vdFxuICAgICAqL1xuICAgIHVwbG9hZEFzQmluYXJ5KGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNCaW5hcnkoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoaHR0cC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBodHRwLnNlbmQodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIG11bHRpcGFydCBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90OlxuICAgICAqL1xuICAgIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzZW5kYWJsZSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgICAgIHNlbmRhYmxlLmFwcGVuZCgnZmlsZScsIHRoaXMuYmxvYiwgdGhpcy5pZCArICcud2VibScpO1xuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoaHR0cC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGh0dHAuc2VuZChzZW5kYWJsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIG9uU3RvcERlZmF1bHQoKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0b3BwZWQgIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcblxuICAgICAgICB0aGlzLmJsb2IgPSBuZXcgQmxvYih0aGlzLmNodW5rcywgeyB0eXBlOiAndmlkZW8vd2VibScgfSk7XG4gICAgICAgIHRoaXMuY2h1bmtzID0gW107XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXdTcmMgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTCh0aGlzLmJsb2IpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQ7XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IExvY2FsUmVjb3JkZXIgfSBmcm9tICcuL0xvY2FsUmVjb3JkZXInO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBEZXZpY2UgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0RldmljZSc7XG5pbXBvcnQgeyBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IHsgUHVibGlzaGVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvUHVibGlzaGVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmdBdXRvIGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8nO1xuaW1wb3J0ICogYXMgc2NyZWVuU2hhcmluZyBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZyc7XG5cbmltcG9ydCBScGNCdWlsZGVyID0gcmVxdWlyZSgnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbi8qKlxuICogRW50cnlwb2ludCBvZiBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKiBVc2UgaXQgdG8gaW5pdGlhbGl6ZSBvYmplY3RzIG9mIHR5cGUgW1tTZXNzaW9uXV0sIFtbUHVibGlzaGVyXV0gYW5kIFtbTG9jYWxSZWNvcmRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgcHJpdmF0ZSBqc29uUnBjQ2xpZW50OiBhbnk7XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlc3Npb246IFNlc3Npb247XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICB3c1VyaTogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VjcmV0ID0gJyc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByZWNvcmRlciA9IGZhbHNlO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaWNlU2VydmVyczogUlRDSWNlU2VydmVyW107XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByb2xlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBhZHZhbmNlZENvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uID0ge307XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgY29uc29sZS5pbmZvKFwiJ09wZW5WaWR1JyBpbml0aWFsaXplZFwiKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgbmV3IHNlc3Npb25cbiAgICovXG4gIGluaXRTZXNzaW9uKCk6IFNlc3Npb24ge1xuICAgIHRoaXMuc2Vzc2lvbiA9IG5ldyBTZXNzaW9uKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnNlc3Npb247XG4gIH1cblxuXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcblxuICAvKipcbiAgICogUmV0dXJucyBhIG5ldyBwdWJsaXNoZXJcbiAgICpcbiAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzRGlhbG9nT3BlbmVkYCBldmVudCwgb25seSBpZiB0aGUgcG9wLXVwIHNob3duIGJ5IHRoZSBicm93c2VyIHRvIHJlcXVlc3QgcGVybWlzc2lvbnMgZm9yIHRoZSBjYW1lcmEgaXMgb3BlbmVkLiBZb3UgY2FuIHVzZSB0aGlzIGV2ZW50IHRvIGFsZXJ0IHRoZSB1c2VyIGFib3V0IGdyYW50aW5nIHBlcm1pc3Npb25zXG4gICAqIGZvciB5b3VyIHdlYnNpdGUuIEFuIGBhY2Nlc3NEaWFsb2dDbG9zZWRgIGV2ZW50IHdpbGwgYWxzbyBiZSBkaXNwYXRjaGVkIGFmdGVyIHVzZXIgY2xpY2tzIG9uIFwiQWxsb3dcIiBvciBcIkJsb2NrXCIgaW4gdGhlIHBvcC11cC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGBhY2Nlc3NEZW5pZWRgIGV2ZW50IG9uY2UgaXQgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSBhIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2AgZXZlbnQgb25jZSB0aGUgbG9jYWwgc3RyZWFtcyBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgIEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSkuIElmICpudWxsKiBvciAqdW5kZWZpbmVkKiBubyBkZWZhdWx0IHZpZGVvIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBQdWJsaXNoZXIuXG4gICAqIFlvdSBjYW4gYWx3YXlzIGNhbGwgbWV0aG9kIFtbUHVibGlzaGVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24pXG4gICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBpbml0UHVibGlzaGVyYCBzdWNjZWVkcywgYW5kIGlzIGRlZmluZWQgaWYgaXQgZmFpbHMuXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICBgY29tcGxldGlvbkhhbmRsZXJgIGZ1bmN0aW9uIGlzIGNhbGxlZCBiZWZvcmUgdGhlIFB1Ymxpc2hlciBkaXNwYXRjaGVzIGFuIGBhY2Nlc3NBbGxvd2VkYCBvciBhbiBgYWNjZXNzRGVuaWVkYCBldmVudFxuICAgKi9cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcGFyYW0yPywgcGFyYW0zPyk6IFB1Ymxpc2hlciB7XG5cbiAgICBsZXQgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcztcblxuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiAhPT0gJ2Z1bmN0aW9uJykpIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzKScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0gKDxQdWJsaXNoZXJQcm9wZXJ0aWVzPnBhcmFtMik7XG5cbiAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGF1ZGlvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgOiB1bmRlZmluZWQsXG4gICAgICAgIGZyYW1lUmF0ZTogdGhpcy5pc01lZGlhU3RyZWFtVHJhY2socHJvcGVydGllcy52aWRlb1NvdXJjZSkgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5mcmFtZVJhdGUgOiB1bmRlZmluZWQpLFxuICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSAhPT0gJ3VuZGVmaW5lZCcpID8gKCh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlID09PSAnc3RyaW5nJykgPyBWaWRlb0luc2VydE1vZGVbcHJvcGVydGllcy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6ICh0eXBlb2YgcHJvcGVydGllcy5taXJyb3IgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMubWlycm9yIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaEF1ZGlvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaEF1ZGlvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMucmVzb2x1dGlvbiAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5yZXNvbHV0aW9uIDogJzY0MHg0ODAnKSxcbiAgICAgICAgdmlkZW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy52aWRlb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy52aWRlb1NvdXJjZSA6IHVuZGVmaW5lZFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogdHJ1ZSxcbiAgICAgICAgcHVibGlzaEF1ZGlvOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246ICc2NDB4NDgwJ1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBwdWJsaXNoZXI6IFB1Ymxpc2hlciA9IG5ldyBQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgdGhpcyk7XG5cbiAgICBsZXQgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTI7XG4gICAgfSBlbHNlIGlmICghIXBhcmFtMykge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTM7XG4gICAgfVxuXG4gICAgcHVibGlzaGVyLmluaXRpYWxpemUoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzQWxsb3dlZCcsIFtdKTtcbiAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnLCBbXSk7XG4gICAgICB9KTtcblxuICAgIHJldHVybiBwdWJsaXNoZXI7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBQcm9taXNpZmllZCB2ZXJzaW9uIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqXG4gICAqID4gV0FSTklORzogZXZlbnRzIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGFuZCBgYWNjZXNzRGlhbG9nQ2xvc2VkYCB3aWxsIG5vdCBiZSBkaXNwYXRjaGVkIGlmIHVzaW5nIHRoaXMgbWV0aG9kIGluc3RlYWQgb2YgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICovXG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFByb21pc2U8UHVibGlzaGVyPjtcbiAgaW5pdFB1Ymxpc2hlckFzeW5jKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+O1xuXG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQcm9taXNlPFB1Ymxpc2hlcj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxQdWJsaXNoZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgbGV0IHB1Ymxpc2hlcjogUHVibGlzaGVyO1xuXG4gICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUocHVibGlzaGVyKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICBwdWJsaXNoZXIgPSB0aGlzLmluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgbG9jYWwgcmVjb3JkZXIgZm9yIHJlY29yZGluZyBzdHJlYW1zIHN0cmFpZ2h0IGF3YXkgZnJvbSB0aGUgYnJvd3NlclxuICAgKiBAcGFyYW0gc3RyZWFtICBTdHJlYW0gdG8gcmVjb3JkXG4gICAqL1xuICBpbml0TG9jYWxSZWNvcmRlcihzdHJlYW06IFN0cmVhbSk6IExvY2FsUmVjb3JkZXIge1xuICAgIHJldHVybiBuZXcgTG9jYWxSZWNvcmRlcihzdHJlYW0pO1xuICB9XG5cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1XG4gICAqIEByZXR1cm5zIDEgaWYgdGhlIGJyb3dzZXIgc3VwcG9ydHMgT3BlblZpZHUsIDAgb3RoZXJ3aXNlXG4gICAqL1xuICBjaGVja1N5c3RlbVJlcXVpcmVtZW50cygpOiBudW1iZXIge1xuICAgIGNvbnN0IGJyb3dzZXIgPSBwbGF0Zm9ybS5uYW1lO1xuICAgIGNvbnN0IHZlcnNpb24gPSBwbGF0Zm9ybS52ZXJzaW9uO1xuXG4gICAgaWYgKChicm93c2VyICE9PSAnQ2hyb21lJykgJiYgKGJyb3dzZXIgIT09ICdDaHJvbWUgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnRmlyZWZveCcpICYmIChicm93c2VyICE9PSAnRmlyZWZveCBNb2JpbGUnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggZm9yIGlPUycpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ09wZXJhJykgJiYgKGJyb3dzZXIgIT09ICdPcGVyYSBNb2JpbGUnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdTYWZhcmknKSkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIENvbGxlY3RzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtZWRpYSBpbnB1dCBkZXZpY2VzIGF2YWlsYWJsZSBvbiB0aGUgc3lzdGVtLiBZb3UgY2FuIHBhc3MgcHJvcGVydHkgYGRldmljZUlkYCBvZiBhIFtbRGV2aWNlXV0gb2JqZWN0IGFzIHZhbHVlIG9mIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgKi9cbiAgZ2V0RGV2aWNlcygpOiBQcm9taXNlPERldmljZVtdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPERldmljZVtdPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKS50aGVuKChkZXZpY2VJbmZvcykgPT4ge1xuICAgICAgICBjb25zdCBkZXZpY2VzOiBEZXZpY2VbXSA9IFtdO1xuICAgICAgICBkZXZpY2VJbmZvcy5mb3JFYWNoKGRldmljZUluZm8gPT4ge1xuICAgICAgICAgIGlmIChkZXZpY2VJbmZvLmtpbmQgPT09ICdhdWRpb2lucHV0JyB8fCBkZXZpY2VJbmZvLmtpbmQgPT09ICd2aWRlb2lucHV0Jykge1xuICAgICAgICAgICAgZGV2aWNlcy5wdXNoKHtcbiAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICBkZXZpY2VJZDogZGV2aWNlSW5mby5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgbGFiZWw6IGRldmljZUluZm8ubGFiZWxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc29sdmUoZGV2aWNlcyk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZ2V0dGluZyBkZXZpY2VzJywgZXJyb3IpO1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBHZXQgYSBNZWRpYVN0cmVhbSBvYmplY3QgdGhhdCB5b3UgY2FuIGN1c3RvbWl6ZSBiZWZvcmUgY2FsbGluZyBbW2luaXRQdWJsaXNoZXJdXSAocGFzcyBfTWVkaWFTdHJlYW1UcmFja18gcHJvcGVydHkgb2YgdGhlIF9NZWRpYVN0cmVhbV8gdmFsdWUgcmVzb2x2ZWQgYnkgdGhlIFByb21pc2UgYXMgYGF1ZGlvU291cmNlYCBvciBgdmlkZW9Tb3VyY2VgIHByb3BlcnRpZXMgaW4gW1tpbml0UHVibGlzaGVyXV0pXG4gICAqXG4gICAqIFBhcmFtZXRlciBgb3B0aW9uc2AgaXMgdGhlIHNhbWUgYXMgaW4gW1tpbml0UHVibGlzaGVyXV0gc2Vjb25kIHBhcmFtZXRlciAob2YgdHlwZSBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSksIGJ1dCBvbmx5IHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyB3aWxsIGJlIGFwcGxpZWQ6IGBhdWRpb1NvdXJjZWAsIGB2aWRlb1NvdXJjZWAsIGBmcmFtZVJhdGVgLCBgcmVzb2x1dGlvbmBcbiAgICpcbiAgICogVG8gY3VzdG9taXplIHRoZSBQdWJsaXNoZXIncyB2aWRlbywgdGhlIEFQSSBmb3IgSFRNTENhbnZhc0VsZW1lbnQgaXMgdmVyeSB1c2VmdWwuIEZvciBleGFtcGxlLCB0byBnZXQgYSBibGFjay1hbmQtd2hpdGUgdmlkZW8gYXQgMTAgZnBzIGFuZCBIRCByZXNvbHV0aW9uIHdpdGggbm8gc291bmQ6XG4gICAqIGBgYFxuICAgKiB2YXIgT1YgPSBuZXcgT3BlblZpZHUoKTtcbiAgICogdmFyIEZSQU1FX1JBVEUgPSAxMDtcbiAgICpcbiAgICogT1YuZ2V0VXNlck1lZGlhKHtcbiAgICogICAgYXVkaW9Tb3VyY2U6IGZhbHNlO1xuICAgKiAgICB2aWRlb1NvdXJjZTogdW5kZWZpbmVkLFxuICAgKiAgICByZXNvbHV0aW9uOiAnMTI4MHg3MjAnLFxuICAgKiAgICBmcmFtZVJhdGU6IEZSQU1FX1JBVEVcbiAgICogfSlcbiAgICogLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgKlxuICAgKiAgICB2YXIgdmlkZW9UcmFjayA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAqICAgIHZpZGVvLnNyY09iamVjdCA9IG5ldyBNZWRpYVN0cmVhbShbdmlkZW9UcmFja10pO1xuICAgKlxuICAgKiAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAqICAgIHZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICogICAgY3R4LmZpbHRlciA9ICdncmF5c2NhbGUoMTAwJSknO1xuICAgKlxuICAgKiAgICB2aWRlby5hZGRFdmVudExpc3RlbmVyKCdwbGF5JywgKCkgPT4ge1xuICAgKiAgICAgIHZhciBsb29wID0gKCkgPT4ge1xuICAgKiAgICAgICAgaWYgKCF2aWRlby5wYXVzZWQgJiYgIXZpZGVvLmVuZGVkKSB7XG4gICAqICAgICAgICAgIGN0eC5kcmF3SW1hZ2UodmlkZW8sIDAsIDAsIDMwMCwgMTcwKTtcbiAgICogICAgICAgICAgc2V0VGltZW91dChsb29wLCAxMDAwLyBGUkFNRV9SQVRFKTsgLy8gRHJhd2luZyBhdCAxMCBmcHNcbiAgICogICAgICAgIH1cbiAgICogICAgICB9O1xuICAgKiAgICAgIGxvb3AoKTtcbiAgICogICAgfSk7XG4gICAqICAgIHZpZGVvLnBsYXkoKTtcbiAgICpcbiAgICogICAgdmFyIGdyYXlWaWRlb1RyYWNrID0gY2FudmFzLmNhcHR1cmVTdHJlYW0oRlJBTUVfUkFURSkuZ2V0VmlkZW9UcmFja3MoKVswXTtcbiAgICogICAgdmFyIHB1Ymxpc2hlciA9IHRoaXMuT1YuaW5pdFB1Ymxpc2hlcihcbiAgICogICAgICBteUh0bWxUYXJnZXQsXG4gICAqICAgICAge1xuICAgKiAgICAgICAgYXVkaW9Tb3VyY2U6IGZhbHNlLFxuICAgKiAgICAgICAgdmlkZW9Tb3VyY2U6IGdyYXlWaWRlb1RyYWNrXG4gICAqICAgICAgfSk7XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGdldFVzZXJNZWRpYShvcHRpb25zOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxNZWRpYVN0cmVhbT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5nZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMob3B0aW9ucylcbiAgICAgICAgLnRoZW4oY29uc3RyYWludHMgPT4ge1xuICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKVxuICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICBsZXQgZXJyb3JOYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKCEob3B0aW9ucy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbicpKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoZXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG5cbiAgLyogdHNsaW50OmRpc2FibGU6bm8tZW1wdHkgKi9cbiAgLyoqXG4gICAqIERpc2FibGUgYWxsIGxvZ2dpbmcgZXhjZXB0IGVycm9yIGxldmVsXG4gICAqL1xuICBlbmFibGVQcm9kTW9kZSgpOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmRlYnVnID0gKCkgPT4geyB9O1xuICAgIGNvbnNvbGUuaW5mbyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLndhcm4gPSAoKSA9PiB7IH07XG4gIH1cbiAgLyogdHNsaW50OmVuYWJsZTpuby1lbXB0eSAqL1xuXG5cbiAgLyoqXG4gICAqIFNldCBPcGVuVmlkdSBhZHZhbmNlZCBjb25maWd1cmF0aW9uIG9wdGlvbnMuIEN1cnJlbnRseSBgY29uZmlndXJhdGlvbmAgaXMgYW4gb2JqZWN0IHdpdGggdGhlIGZvbGxvd2luZyBvcHRpb25hbCBwcm9wZXJ0aWVzIChzZWUgW1tPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbl1dIGZvciBtb3JlIGRldGFpbHMpOlxuICAgKiAtIGBpY2VTZXJ2ZXJzYDogc2V0IGN1c3RvbSBTVFVOL1RVUk4gc2VydmVycyB0byBiZSB1c2VkIGJ5IE9wZW5WaWR1IEJyb3dzZXJcbiAgICogLSBgc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb25gOiB1cmwgdG8gYSBjdXN0b20gc2NyZWVuIHNoYXJlIGV4dGVuc2lvbiBmb3IgQ2hyb21lIHRvIGJlIHVzZWQgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBvbmUsIGJhc2VkIG9uIG91cnMgW2h0dHBzOi8vZ2l0aHViLmNvbS9PcGVuVmlkdS9vcGVudmlkdS1zY3JlZW4tc2hhcmluZy1jaHJvbWUtZXh0ZW5zaW9uXShodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbilcbiAgICogLSBgcHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zYDogY3VzdG9tIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBbW1B1Ymxpc2hlclNwZWFraW5nRXZlbnRdXSBmZWF0dXJlXG4gICAqL1xuICBzZXRBZHZhbmNlZENvbmZpZ3VyYXRpb24oY29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24pOiB2b2lkIHtcbiAgICB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb247XG4gIH1cblxuXG4gIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyhwdWJsaXNoZXJQcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPE1lZGlhU3RyZWFtQ29uc3RyYWludHM+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGxldCBhdWRpbywgdmlkZW87XG5cbiAgICAgIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBudWxsIHx8IHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgPT09IGZhbHNlKSB7XG4gICAgICAgIGF1ZGlvID0gZmFsc2U7XG4gICAgICB9IGVsc2UgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBhdWRpbyA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhdWRpbyA9IHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBudWxsIHx8IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09IGZhbHNlKSB7XG4gICAgICAgIHZpZGVvID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2aWRlbyA9IHtcbiAgICAgICAgICBoZWlnaHQ6IHtcbiAgICAgICAgICAgIGlkZWFsOiA0ODBcbiAgICAgICAgICB9LFxuICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICBpZGVhbDogNjQwXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtZWRpYUNvbnN0cmFpbnRzOiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbyxcbiAgICAgICAgdmlkZW9cbiAgICAgIH07XG5cbiAgICAgIGlmICh0eXBlb2YgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA9IHsgZGV2aWNlSWQ6IHsgZXhhY3Q6IG1lZGlhQ29uc3RyYWludHMuYXVkaW8gfSB9O1xuICAgICAgfVxuXG4gICAgICBpZiAobWVkaWFDb25zdHJhaW50cy52aWRlbykge1xuXG4gICAgICAgIGlmICghIXB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbikge1xuICAgICAgICAgIGNvbnN0IHdpZHRoQW5kSGVpZ2h0ID0gcHVibGlzaGVyUHJvcGVydGllcy5yZXNvbHV0aW9uLnRvTG93ZXJDYXNlKCkuc3BsaXQoJ3gnKTtcbiAgICAgICAgICBjb25zdCB3aWR0aCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFswXSk7XG4gICAgICAgICAgY29uc3QgaGVpZ2h0ID0gTnVtYmVyKHdpZHRoQW5kSGVpZ2h0WzFdKTtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLndpZHRoLmlkZWFsID0gd2lkdGg7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS5oZWlnaHQuaWRlYWwgPSBoZWlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZSkge1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuZnJhbWVSYXRlID0geyBpZGVhbDogcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghIXB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgJiYgdHlwZW9mIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzdHJpbmcnKSB7XG5cbiAgICAgICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbicpIHtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUgIT09ICdDaHJvbWUnICYmIHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVELCAnWW91IGNhbiBvbmx5IHNjcmVlbiBzaGFyZSBpbiBkZXNrdG9wIENocm9tZSBhbmQgRmlyZWZveC4gRGV0ZWN0ZWQgYnJvd3NlcjogJyArIHBsYXRmb3JtLm5hbWUpO1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gJiYgIShwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSkge1xuXG4gICAgICAgICAgICAgICAgLy8gQ3VzdG9tIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lXG5cbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldFNjcmVlbkNvbnN0cmFpbnRzKChlcnJvciwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yIHx8ICEhc2NyZWVuQ29uc3RyYWludHMubWFuZGF0b3J5ICYmIHNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZSA9PT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnIHx8IGVycm9yID09PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25JZCA9IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIS5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbklkLCAoc3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICg8c3RyaW5nPnRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWZhdWx0IHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lXG5cbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nQXV0by5nZXRTY3JlZW5JZCgoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25VcmwgPSAhIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uID8gdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gOlxuICAgICAgICAgICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2hyb21lLmdvb2dsZS5jb20vd2Vic3RvcmUvZGV0YWlsL29wZW52aWR1LXNjcmVlbnNoYXJpbmcvbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCBleHRlbnNpb25VcmwpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdpbnN0YWxsZWQtZGlzYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9ICdzY3JlZW4nO1xuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zdHJpbmctbGl0ZXJhbFxuICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlb1snZGV2aWNlSWQnXSA9IHsgZXhhY3Q6IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgfTtcbiAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc3RhcnRXcyhvbkNvbm5lY3RTdWNjZXM6IChlcnJvcjogRXJyb3IpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSB7XG4gICAgICBoZWFydGJlYXQ6IDUwMDAsXG4gICAgICBzZW5kQ2xvc2VNZXNzYWdlOiBmYWxzZSxcbiAgICAgIHdzOiB7XG4gICAgICAgIHVyaTogdGhpcy53c1VyaSxcbiAgICAgICAgdXNlU29ja0pTOiBmYWxzZSxcbiAgICAgICAgb25jb25uZWN0ZWQ6IG9uQ29ubmVjdFN1Y2NlcyxcbiAgICAgICAgb25kaXNjb25uZWN0OiB0aGlzLmRpc2Nvbm5lY3RDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBvbnJlY29ubmVjdGluZzogdGhpcy5yZWNvbm5lY3RpbmdDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBvbnJlY29ubmVjdGVkOiB0aGlzLnJlY29ubmVjdGVkQ2FsbGJhY2suYmluZCh0aGlzKVxuICAgICAgfSxcbiAgICAgIHJwYzoge1xuICAgICAgICByZXF1ZXN0VGltZW91dDogMTAwMDAsXG4gICAgICAgIHBhcnRpY2lwYW50Sm9pbmVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEpvaW5lZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50UHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50VW5wdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50VW5wdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudExlZnQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50TGVmdC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50RXZpY3RlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRFdmljdGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RhcnRlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RhcnRlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0b3BwZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0b3BwZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzZW5kTWVzc2FnZTogdGhpcy5zZXNzaW9uLm9uTmV3TWVzc2FnZS5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5cbi8qKlxuICogUGFja3MgbG9jYWwgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGNhbiBwdWJsaXNoIGl0IHRvIGEgc2Vzc2lvbi4gSW5pdGlhbGl6ZWQgd2l0aCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAqL1xuZXhwb3J0IGNsYXNzIFB1Ymxpc2hlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgUHVibGlzaGVyIGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3RcbiAgICAgKi9cbiAgICBhY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHlvdSBoYXZlIGNhbGxlZCBbW1B1Ymxpc2hlci5zdWJzY3JpYmVUb1JlbW90ZV1dIHdpdGggdmFsdWUgYHRydWVgIG9yIGBmYWxzZWAgKCpmYWxzZSogYnkgZGVmYXVsdClcbiAgICAgKi9cbiAgICBpc1N1YnNjcmliZWRUb1JlbW90ZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIHRvIHdoaWNoIHRoZSBQdWJsaXNoZXIgYmVsb25nc1xuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247IC8vIEluaXRpYWxpemVkIGJ5IFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpXG5cbiAgICBwcml2YXRlIGFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcztcbiAgICBwcml2YXRlIHBlcm1pc3Npb25EaWFsb2dUaW1lb3V0OiBOb2RlSlMuVGltZXI7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgcHJpdmF0ZSBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uZWUub24oJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQtYnktZGlzY29ubmVjdCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgYXVkaW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIGF1ZGlvIHN0cmVhbScpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gcHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVucHVibGlzaCBpdFxuICAgICAqL1xuICAgIHB1Ymxpc2hWaWRlbyh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIENhbGwgdGhpcyBtZXRob2QgYmVmb3JlIFtbU2Vzc2lvbi5wdWJsaXNoXV0gdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBQdWJsaXNoZXIge1xuICAgICAgICBzdXBlci5vbmNlKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbUNyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHRoaXMuc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUub25jZSgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgZXJyb3JDYWxsYmFjayA9IChvcGVuVmlkdUVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJlamVjdChvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmlzTWVkaWFTdHJlYW1UcmFjayh0aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjaygoPE1lZGlhU3RyZWFtVHJhY2s+dGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQXBwbHkgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW8gYW5kIFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvXG4gICAgICAgICAgICAgICAgaWYgKCEhbWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdLmVuYWJsZWQgPSAhIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCEhbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSAhIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBzdWJzY3JpYmVkIHRvIG91ciByZW1vdGUgd2UgZG9uJ3Qgc3RpbGwgc2V0IHRoZSBNZWRpYVN0cmVhbSBvYmplY3QgaW4gdGhlIHZpZGVvIGVsZW1lbnRzIHRvXG4gICAgICAgICAgICAgICAgICAgIC8vIGF2b2lkIGVhcmx5ICdzdHJlYW1QbGF5aW5nJyBldmVudFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS51cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcblxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuZmlyc3RWaWRlb0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVWaWRlb0VsZW1lbnQodGhpcy5maXJzdFZpZGVvRWxlbWVudC50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnRoaXMucHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyh0aGlzLnByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgLnRoZW4oY29uc3RyYWludHMgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG91dGJvdW5kU3RyZWFtT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IGNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyUHJvcGVydGllczogdGhpcy5wcm9wZXJ0aWVzXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHNBdXg6IE1lZGlhU3RyZWFtQ29uc3RyYWludHMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGltZUZvckRpYWxvZ0V2ZW50ID0gMTI1MDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kVmlkZW8oKSB8fCB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZpbmVkQXVkaW9Db25zdHJhaW50ID0gKChjb25zdHJhaW50cy5hdWRpbyA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiBjb25zdHJhaW50cy5hdWRpbyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gZmFsc2UgOiBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBjb25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIodGltZUZvckRpYWxvZ0V2ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHNBdXgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgJiYgdGhpcy5zdHJlYW0uaXNTZW5kQXVkaW8oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiBnZXR0aW5nIGRlc2t0b3AgYXMgdXNlciBtZWRpYSBhdWRpbyBjb25zdHJhaW50IG11c3QgYmUgZmFsc2UuIE5vdyB3ZSBjYW4gYXNrIGZvciBpdCBpZiByZXF1aXJlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXguYXVkaW8gPSBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihhdWRpb09ubHlTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soYXVkaW9Pbmx5U3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWUsIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnb3ZlcmNvbnN0cmFpbmVkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlBVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWUsIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogY29uc3RyYWludHMudmlkZW9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEIDogT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ1wiICsgKDxDb25zdHJhaW5ET01TdHJpbmdQYXJhbWV0ZXJzPig8TWVkaWFUcmFja0NvbnN0cmFpbnRzPmNvbnN0cmFpbnRzLmF1ZGlvKS5kZXZpY2VJZCEhKS5leGFjdCArIFwiJyBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IHRoZSB2YWx1ZSBwYXNzZWQgZm9yIGNvbnN0cmFpbnQgJ1wiICsgZXJyb3IuY29uc3RyYWludCArIFwiJ1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiVmlkZW8gaW5wdXQgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ1wiICsgKDxDb25zdHJhaW5ET01TdHJpbmdQYXJhbWV0ZXJzPig8TWVkaWFUcmFja0NvbnN0cmFpbnRzPmNvbnN0cmFpbnRzLnZpZGVvKS5kZXZpY2VJZCEhKS5leGFjdCArIFwiJyBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IHRoZSB2YWx1ZSBwYXNzZWQgZm9yIGNvbnN0cmFpbnQgJ1wiICsgZXJyb3IuY29uc3RyYWludCArIFwiJ1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk5PX0lOUFVUX1NPVVJDRV9TRVQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJQcm9wZXJ0aWVzICdhdWRpb1NvdXJjZScgYW5kICd2aWRlb1NvdXJjZScgY2Fubm90IGJlIHNldCB0byBmYWxzZSBvciBudWxsIGF0IHRoZSBzYW1lIHRpbWUgd2hlbiBjYWxsaW5nICdPcGVuVmlkdS5pbml0UHVibGlzaGVyJ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVTZXNzaW9uKHNlc3Npb246IFNlc3Npb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbiA9IHNlc3Npb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWVzdGFibGlzaFN0cmVhbVBsYXlpbmdFdmVudCgpIHtcbiAgICAgICAgaWYgKHRoaXMuZWUuZ2V0TGlzdGVuZXJzKCdzdHJlYW1QbGF5aW5nJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5hZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIHNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih3YWl0VGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEaWFsb2dPcGVuZWQnLCBbXSk7XG4gICAgICAgIH0sIHdhaXRUaW1lKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZTogbnVtYmVyLCB3YWl0VGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0KTtcbiAgICAgICAgaWYgKChEYXRlLm5vdygpIC0gc3RhcnRUaW1lKSA+IHdhaXRUaW1lKSB7XG4gICAgICAgICAgICAvLyBQZXJtaXNzaW9uIGRpYWxvZyB3YXMgc2hvd24gYW5kIG5vdyBpcyBjbG9zZWRcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEaWFsb2dDbG9zZWQnLCBbXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4vUHVibGlzaGVyJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU3Vic2NyaWJlciB9IGZyb20gJy4vU3Vic2NyaWJlcic7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTaWduYWxPcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TaWduYWxPcHRpb25zJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0Nvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IE9iak1hcCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL09iak1hcCc7XG5pbXBvcnQgeyBTZXNzaW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL1Nlc3Npb25PcHRpb25zJztcbmltcG9ydCB7IENvbm5lY3Rpb25FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0Nvbm5lY3Rpb25FdmVudCc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5pbXBvcnQgeyBSZWNvcmRpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1JlY29yZGluZ0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudCc7XG5pbXBvcnQgeyBTaWduYWxFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50JztcbmltcG9ydCB7IFN0cmVhbUV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLy8gVGhpcyBtYXAgaXMgb25seSB1c2VkIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gJ2pvaW5Sb29tJyByZXNwb25zZSBhbmQgJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnIG5vdGlmaWNhdGlvblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVTdHJlYW1zQ3JlYXRlZDogT2JqTWFwPGJvb2xlYW4+ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE9iak1hcDxDb25uZWN0aW9uPiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcml6ZWQgZm9ybWF0XG4gICAgICogYXMgSlNPTiBvciBYTUwgaXMgYSBnb29kIGlkZWEpLCB0aGUgb25seSByZXN0cmljdGlvbiBpcyBhIG1heGltdW0gbGVuZ3RoIG9mIDEwMDAwIGNoYXJzLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRhZGF0YSBpcyBub3QgY29uc2lkZXJlZCBzZWN1cmUsIGFzIGl0IGlzIGdlbmVyYXRlZCBpbiB0aGUgY2xpZW50IHNpZGUuIFRvIHBhc3Mgc2VjdXJpemVkIGRhdGEsIGFkZCBpdCBhcyBhIHBhcmFtZXRlciBpbiB0aGVcbiAgICAgKiB0b2tlbiBnZW5lcmF0aW9uIG9wZXJhdGlvbiAodGhyb3VnaCB0aGUgQVBJIFJFU1QsIG9wZW52aWR1LWphdmEtY2xpZW50IG9yIG9wZW52aWR1LW5vZGUtY2xpZW50KS5cbiAgICAgKlxuICAgICAqIE9ubHkgYWZ0ZXIgdGhlIHJldHVybmVkIFByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gb2JqZWN0IHdpbGwgYmUgYXZhaWxhYmxlIGFuZCBwcm9wZXJseSBkZWZpbmVkLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBmaXJzdCBkaXNwYXRjaCBvbmUgb3IgbW9yZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cyB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2Q6XG4gICAgICogLSBGaXJzdCBvbmUgZm9yIHlvdXIgb3duIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0LCBzbyB5b3UgY2FuIHJldHJpZXZlIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gcHJvcGVydHkuXG4gICAgICogLSBUaGVuIG9uZSBmb3IgZWFjaCByZW1vdGUgQ29ubmVjdGlvbiBwcmV2aW91c2x5IGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiwgaWYgYW55LiBBbnkgb3RoZXIgcmVtb3RlIHVzZXIgY29ubmVjdGluZyB0byB0aGUgU2Vzc2lvbiBhZnRlciB5b3UgaGF2ZVxuICAgICAqIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCB3aGVuIHRoZXkgZG8gc28uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgZm9yIGVhY2ggcmVtb3RlIGFjdGl2ZSBbW1B1Ymxpc2hlcl1dIHRoYXQgd2FzIGFscmVhZHkgc3RyZWFtaW5nXG4gICAgICogd2hlbiBjb25uZWN0aW5nLCBqdXN0IGFmdGVyIGRpc3BhdGNoaW5nIGFsbCByZW1vdGUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0byB3aGljaCB5b3UgbXVzdCBzdWJzY3JpYmUgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqXG4gICAgICovXG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YT86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1Rva2VuKHRva2VuKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIEVhcmx5IGNvbmZpZ3VyYXRpb24gdG8gZGVhY3RpdmF0ZSBhdXRvbWF0aWMgc3Vic2NyaXB0aW9uIHRvIHN0cmVhbXNcbiAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRva2VuLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISFtZXRhZGF0YSA/IHRoaXMuc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGEpIDogJydcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdEF1eCh0b2tlbikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBwbGF0Zm9ybS5uYW1lICsgJyAnICsgcGxhdGZvcm0udmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGVhdmVzIHRoZSBzZXNzaW9uLCBkZXN0cm95aW5nIGFsbCBzdHJlYW1zIGFuZCBkZWxldGluZyB0aGUgdXNlciBhcyBhIHBhcnRpY2lwYW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBlYWNoIFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgdG8gYXZvaWQgdGhpcyBiZWhhdmlvdXIgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24gKHRvIGRvIHNvIGl0IGlzIGEgbWFuZGF0b3J5IHJlcXVpcmVtZW50IHRvIGNhbGwgYFNlc3Npb24udW5wdWJsaXNoKClgXG4gICAgICogb3IvYW5kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaW4gdGhlIHByZXZpb3VzIHNlc3Npb24pLiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZGlzY29ubmVjdGVkIHBhcnRpY2lwYW50IHdhcyBwdWJsaXNoaW5nLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvdXIgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgaW4gYW55IGNhc2UuIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sZWF2ZShmYWxzZSwgJ2Rpc2Nvbm5lY3QnKTtcbiAgICB9XG5cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgYHN0cmVhbWAsIGFkZGluZyBhIG5ldyBIVE1MIHZpZGVvIGVsZW1lbnQgdG8gRE9NIHdpdGggYHN1YnNjcmliZXJQcm9wZXJ0aWVzYCBzZXR0aW5ncy4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWQgaW4gdGhlIGNhbGxiYWNrIG9mIGBzdHJlYW1DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliaW5nIHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZCA9IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAndW5zdWJzY3JpYmVGcm9tVmlkZW8nLFxuICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHVuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcykgYW5kXG4gICAgICogZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsJywgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0uY29ubmVjdGlvbiAhPT0gdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5wdWJsaXNoaW5nIGxvY2FsIG1lZGlhICgnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyknKTtcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyBvbmUgc2lnbmFsLiBgc2lnbmFsYCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiBgYGBqc29uXG4gICAgICoge2RhdGE6c3RyaW5nLCB0bzpDb25uZWN0aW9uW10sIHR5cGU6c3RyaW5nfVxuICAgICAqIGBgYFxuICAgICAqIEFsbCB1c2VycyBzdWJzY3JpYmVkIHRvIHRoYXQgc2lnbmFsIChgc2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCAuLi4pYCBvciBgc2Vzc2lvbi5vbignc2lnbmFsJywgLi4uKWAgZm9yIGFsbCBzaWduYWxzKSBhbmQgd2hvc2UgQ29ubmVjdGlvbiBvYmplY3RzIGFyZSBpbiBgdG9gIGFycmF5IHdpbGwgcmVjZWl2ZSBpdC4gVGhlaXIgbG9jYWxcbiAgICAgKiBTZXNzaW9uIG9iamVjdHMgd2lsbCBkaXNwYXRjaCBhIGBzaWduYWxgIG9yIGBzaWduYWw6dHlwZWAgZXZlbnQuIFNlZSBbW1NpZ25hbEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgbWVzc2FnZSBzdWNjZXNzZnVsbHkgcmVhY2hlZCBvcGVudmlkdS1zZXJ2ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdC4gX1RoaXMgZG9lc24ndFxuICAgICAqIG1lYW4gdGhhdCBvcGVudmlkdS1zZXJ2ZXIgY291bGQgcmVzZW5kIHRoZSBtZXNzYWdlIHRvIGFsbCB0aGUgbGlzdGVkIHJlY2VpdmVycy5fXG4gICAgICovXG4gICAgLyogdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cbiAgICBzaWduYWwoc2lnbmFsOiBTaWduYWxPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsTWVzc2FnZSA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWRzLnB1c2goY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogSlNPTi5zdHJpbmdpZnkoc2lnbmFsTWVzc2FnZSlcbiAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qIHRzbGludDplbmFibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayAnc3BlYWtpbmcnIGV2ZW50IGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGRpc2FibGFlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhIXN0ci5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24ocmVzcG9uc2UuaWQsICcnKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Nvbm5lY3Rpb24gJyArIHJlc3BvbnNlLmlkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tyZXNwb25zZS5pZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5uYW1lLCAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIG1zZy5uYW1lICsgXCIgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50TGVmdCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBzdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGFmdGVyQ29ubmVjdGlvbkZvdW5kID0gKGNvbm5lY3Rpb24pID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSkge1xuICAgICAgICAgICAgICAgIC8vIEF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gc3RyZWFtLnN1YnNjcmliZSgpIGluIFwib25QYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGFuZCBpbiBcImpvaW5Sb29tXCIgcnBjIGNhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBjb25kaXRpb24gaXMgZmFsc2UgaWYgb3BlbnZpZHUtc2VydmVyIHNlbmRzIFwicGFydGljaXBhbnRQdWJsaXNoZWRcIiBldmVudCB0byBhIHN1YnNjcmliZXIgcGFydGljaXBhbnQgdGhhdCBoYXNcbiAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IHN1YnNjcmliZWQgdG8gY2VydGFpbiBzdHJlYW0gaW4gdGhlIGNhbGxiYWNrIG9mIFwiam9pblJvb21cIiBtZXRob2RcblxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBHZXQgdGhlIGV4aXN0aW5nIENvbm5lY3Rpb24gY3JlYXRlZCBvbiAnb25QYXJ0aWNpcGFudEpvaW5lZCcgZm9yXG4gICAgICAgIC8vIGV4aXN0aW5nIHBhcnRpY2lwYW50cyBvciBjcmVhdGUgYSBuZXcgb25lIGZvciBuZXcgcGFydGljaXBhbnRzXG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24ocmVzcG9uc2UuaWQsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgcmVzcG9uc2UuaWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50UHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29uID0+IHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgZXhpc3RpbmcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBjb247XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UubWV0YWRhdGEgPSBjb24uZGF0YTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLm9wdGlvbnMgPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlLnN0cmVhbXMpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgbmV3IENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5uYW1lLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIG1zZy5uYW1lICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgY29ubmVjdGlvbi5zdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuXG4gICAgICAgICAgICAgICAgLy8gRGVsZXRpbmcgdGhlIHJlbW90ZSBzdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZDogc3RyaW5nID0gY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ucmVtb3ZlU3RyZWFtKHN0cmVhbUlkKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50RXZpY3RlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgLyp0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLm5hbWUgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgJ2ZvcmNlRGlzY29ubmVjdCcpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5kaXNwb3NlKCk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgJ2ZvcmNlRGlzY29ubmVjdCcpXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTsqL1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk5ld01lc3NhZ2UobXNnKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgc2lnbmFsOiAnICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG5cbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKG1zZy5mcm9tLCBcIkNvbm5lY3Rpb24gJ1wiICsgbXNnLmZyb20gKyBcIicgdW5rbm93IHdoZW4gJ29uTmV3TWVzc2FnZScuIEV4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogXCJcbiAgICAgICAgICAgICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpICsgJy4gRXhpc3RpbmcgbG9jYWwgY29ubmVjdGlvbjogJyArIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWwnLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsOicgKyBtc2cudHlwZSwgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVjdkljZUNhbmRpZGF0ZShtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY2FuZGlkYXRlID0ge1xuICAgICAgICAgICAgY2FuZGlkYXRlOiBtc2cuY2FuZGlkYXRlLFxuICAgICAgICAgICAgc2RwTWlkOiBtc2cuc2RwTWlkLFxuICAgICAgICAgICAgc2RwTUxpbmVJbmRleDogbXNnLnNkcE1MaW5lSW5kZXgsXG4gICAgICAgICAgICB0b0pTT046ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKG1zZy5lbmRwb2ludE5hbWUsICdDb25uZWN0aW9uIG5vdCBmb3VuZCBmb3IgZW5kcG9pbnQgJyArIG1zZy5lbmRwb2ludE5hbWUgKyAnLiBJY2UgY2FuZGlkYXRlIHdpbGwgYmUgaWdub3JlZDogJyArIGNhbmRpZGF0ZSlcbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgIHN0cmVhbS5nZXRXZWJSdGNQZWVyKCkuYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBhZGRpbmcgY2FuZGlkYXRlIGZvciAnICsgc3RyZWFtLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblNlc3Npb25DbG9zZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnU2Vzc2lvbiBjbG9zZWQ6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcbiAgICAgICAgY29uc3QgcyA9IG1zZy5yb29tO1xuICAgICAgICBpZiAocyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbi1jbG9zZWQnLCBbe1xuICAgICAgICAgICAgICAgIHNlc3Npb246IHNcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWQnLCBtc2cpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTG9zdENvbm5lY3Rpb24oKTogdm9pZCB7XG5cbiAgICAgICAgLyppZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0qL1xuXG4gICAgICAgIGNvbnNvbGUud2FybignTG9zdCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgdGhpcy5sZWF2ZSh0cnVlLCAnbmV0d29ya0Rpc2Nvbm5lY3QnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk1lZGlhRXJyb3IocGFyYW1zKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWEgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgY29uc3QgZXJyID0gcGFyYW1zLmVycm9yO1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnZXJyb3ItbWVkaWEnLCBbe1xuICAgICAgICAgICAgICAgIGVycm9yOiBlcnJcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignUmVjZWl2ZWQgdW5kZWZpbmVkIG1lZGlhIGVycm9yLiBQYXJhbXM6JywgcGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0YXJ0ZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0YXJ0ZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdGFydGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3JkaW5nU3RvcHBlZChyZXNwb25zZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVjb3JkaW5nU3RvcHBlZCcsIFtuZXcgUmVjb3JkaW5nRXZlbnQodGhpcywgJ3JlY29yZGluZ1N0b3BwZWQnLCByZXNwb25zZS5pZCwgcmVzcG9uc2UubmFtZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxlYXZlKGZvcmNlZDogYm9vbGVhbiwgcmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBmb3JjZWQgPSAhIWZvcmNlZDtcbiAgICAgICAgY29uc29sZS5pbmZvKCdMZWF2aW5nIFNlc3Npb24gKGZvcmNlZD0nICsgZm9yY2VkICsgJyknKTtcblxuICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkICYmICFmb3JjZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdsZWF2ZVJvb20nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVlLmVtaXRFdmVudCgnbG9jYWwtc3RyZWFtLWRlc3Ryb3llZC1ieS1kaXNjb25uZWN0JywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBNYWtlIFNlc3Npb24gb2JqZWN0IGRpc3BhdGNoICdzZXNzaW9uRGlzY29ubmVjdGVkJyBldmVudCAoaWYgaXQgaXMgbm90IGFscmVhZHkgZGlzcG9zZWQpXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudCA9IG5ldyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQodGhpcywgcmVhc29uKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcsIFtzZXNzaW9uRGlzY29ubmVjdEV2ZW50XSk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3Ugd2VyZSBub3QgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0QXV4KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zdGFydFdzKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBqb2luUGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46ICghIXRva2VuKSA/IHRva2VuIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdqb2luUm9vbScsIGpvaW5QYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGF0YSA9IHJlc3BvbnNlLm1ldGFkYXRhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSByZW1vdGUgQ29ubmVjdGlvbnMgd2l0aCB2YWx1ZSByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25zOiBuZXcgQXJyYXk8Q29ubmVjdGlvbj4oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJ0aWNpcGFudHM6IENvbm5lY3Rpb25PcHRpb25zW10gPSByZXNwb25zZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50cy5mb3JFYWNoKHBhcnRpY2lwYW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMucHVzaChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLnB1c2goY29ubmVjdGlvbi5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCB0aGlzLmNvbm5lY3Rpb24sICcnKV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggZXhpc3RpbmcgY29ubmVjdGlvbiBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ3N0cmVhbUNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGFjdGl2ZSBzdHJlYW0gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5mb3JFYWNoKHN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBzdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW1vdGVDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIGNvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodG9rZW4pO1xuICAgICAgICB0aGlzLnNlc3Npb25JZCA9IDxzdHJpbmc+dXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Nlc3Npb25JZCcpO1xuICAgICAgICBjb25zdCBzZWNyZXQgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnc2VjcmV0Jyk7XG4gICAgICAgIGNvbnN0IHJlY29yZGVyID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3JlY29yZGVyJyk7XG4gICAgICAgIGNvbnN0IHR1cm5Vc2VybmFtZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0dXJuVXNlcm5hbWUnKTtcbiAgICAgICAgY29uc3QgdHVybkNyZWRlbnRpYWwgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVybkNyZWRlbnRpYWwnKTtcbiAgICAgICAgY29uc3Qgcm9sZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyb2xlJyk7XG5cbiAgICAgICAgaWYgKCEhc2VjcmV0KSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyZWNvcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdHVyblVzZXJuYW1lICYmICEhdHVybkNyZWRlbnRpYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0dW5VcmwgPSAnc3R1bjonICsgdXJsLmhvc3RuYW1lICsgJzozNDc4JztcbiAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMiA9IHR1cm5VcmwxICsgJz90cmFuc3BvcnQ9dGNwJztcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtcbiAgICAgICAgICAgICAgICB7IHVybHM6IFtzdHVuVXJsXSB9LFxuICAgICAgICAgICAgICAgIHsgdXJsczogW3R1cm5VcmwxLCB0dXJuVXJsMl0sIHVzZXJuYW1lOiB0dXJuVXNlcm5hbWUsIGNyZWRlbnRpYWw6IHR1cm5DcmVkZW50aWFsIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnVFVSTiB0ZW1wIGNyZWRlbnRpYWxzIFsnICsgdHVyblVzZXJuYW1lICsgJzonICsgdHVybkNyZWRlbnRpYWwgKyAnXScpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcm9sZSkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yb2xlID0gcm9sZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub3BlbnZpZHUud3NVcmkgPSAnd3NzOi8vJyArIHVybC5ob3N0ICsgJy9vcGVudmlkdSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBXZWJSdGNQZWVyLCBXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlclNlbmRyZWN2IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNQZWVyL1dlYlJ0Y1BlZXInO1xuaW1wb3J0IHsgV2ViUnRjU3RhdHMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1N0YXRzL1dlYlJ0Y1N0YXRzJztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5pbXBvcnQgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKTtcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIG1lZGlhIHN0cmVhbXMgYXZhaWxhYmxlIGluIE9wZW5WaWR1IFNlcnZlciBmb3IgY2VydGFpbiBzZXNzaW9uLlxuICogRWFjaCBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBoYXMgYW4gYXR0cmlidXRlIG9mIHR5cGUgU3RyZWFtLCBhcyB0aGV5IGdpdmUgYWNjZXNzXG4gKiB0byBvbmUgb2YgdGhlbSAoc2VuZGluZyBhbmQgcmVjZWl2aW5nIGl0LCByZXNwZWN0aXZlbHkpXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW0ge1xuXG4gICAgLyoqXG4gICAgICogVGhlIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgaXMgcHVibGlzaGluZyB0aGUgc3RyZWFtXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZyYW1lIHJhdGUgb2YgdGhlIHZpZGVvIGluIGZyYW1lcyBwZXIgc2Vjb25kLiBUaGlzIHByb3BlcnR5IGlzIG9ubHkgZGVmaW5lZCBpZiB0aGUgW1tQdWJsaXNoZXJdXSBvZlxuICAgICAqIHRoZSBzdHJlYW0gd2FzIGluaXRpYWxpemVkIHBhc3NpbmcgYSBfZnJhbWVSYXRlXyBwcm9wZXJ0eSBvbiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICAgKi9cbiAgICBmcmFtZVJhdGU/OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIGEgdmlkZW8gdHJhY2sgb3Igbm90XG4gICAgICovXG4gICAgaGFzVmlkZW86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIGFuIGF1ZGlvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc0F1ZGlvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIHN0cmVhbUlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBgXCJDQU1FUkFcImAgb3IgYFwiU0NSRUVOXCJgLiAqdW5kZWZpbmVkKiBpZiBzdHJlYW0gaXMgYXVkaW8tb25seVxuICAgICAqL1xuICAgIHR5cGVPZlZpZGVvPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtTWFuYWdlciBvYmplY3QgKFtbUHVibGlzaGVyXV0gb3IgW1tTdWJzY3JpYmVyXV0pIGluIGNoYXJnZSBvZiBkaXNwbGF5aW5nIHRoaXMgc3RyZWFtIGluIHRoZSBET01cbiAgICAgKi9cbiAgICBzdHJlYW1NYW5hZ2VyOiBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNQZWVyOiBXZWJSdGNQZWVyO1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5ib3VuZFN0cmVhbU9wdHM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3BlZWNoRXZlbnQ6IGFueTtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlc3Npb246IFNlc3Npb24sIG9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zIHwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIHwge30pIHtcblxuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCdpZCcpKSB7XG4gICAgICAgICAgICAvLyBJbmJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBTdWJzY3JpYmVyXG4gICAgICAgICAgICB0aGlzLmluYm91bmRTdHJlYW1PcHRzID0gPEluYm91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICdTQ1JFRU4nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAnQ0FNRVJBJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMudHlwZU9mVmlkZW87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pc1NlbmRBdWRpbygpO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaXNTZW5kVmlkZW8oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gbWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWwoKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGluYm91bmQgb3B0aW9ucyB1bmRlZmluZWQgYW5kIG91dGJvdW5kIG9wdGlvbnMgZGVmaW5lZFxuICAgICAgICByZXR1cm4gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzICYmICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5nZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlcG9ydCA9PiByZXNvbHZlKHJlcG9ydCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpOiBSVENJY2VDYW5kaWRhdGVbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclNlbmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgdXNlck1lZGlhQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pc1NlbmRWaWRlbygpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3B1Ymxpc2hWaWRlbycsIHtcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW0sXG4gICAgICAgICAgICAgICAgICAgIGRvTG9vcGJhY2s6IHRoaXMuZGlzcGxheU15UmVtb3RlKCkgfHwgZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvQWN0aXZlOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiB0aGlzLmlzU2VuZFZpZGVvKCksXG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiAoKHRoaXMuaXNTZW5kVmlkZW8oKSkgPyAodGhpcy5pc1NlbmRTY3JlZW4oKSA/ICdTQ1JFRU4nIDogJ0NBTUVSQScpIDogJycpLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xXG4gICAgICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnRXJyb3Igb24gcHVibGlzaFZpZGVvOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0xvY2FsU3RyZWFtUHVibGlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlUGVlclN1Y2Nlc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKCkudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclJlY2VpdmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgb2ZmZXJDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5yZWN2QXVkaW8sXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMucmVjdlZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWQuIENvbnN0cmFpbnRzIG9mIGdlbmVyYXRlIFNEUCBvZmZlclwiLFxuICAgICAgICAgICAgICAgIG9mZmVyQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gc3Vic2NyaWJlIHRvICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3JlY2VpdmVWaWRlb0Zyb20nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gcmVjdlZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNmdWxseUVzdGFibGlzaGVkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclJlY3Zvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKVxuICAgICAgICAgICAgICAgIC50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbW90ZVBlZXJTdWNjZXNmdWxseUVzdGFibGlzaGVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gdGhpcy53ZWJSdGNQZWVyLnBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnUGVlciByZW1vdGUgc3RyZWFtJywgdGhpcy5tZWRpYVN0cmVhbSk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSAmJiAhIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAmJiB0aGlzLnNlc3Npb24uc3BlYWtpbmdFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMgPSBuZXcgV2ViUnRjU3RhdHModGhpcyk7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wV2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMud2ViUnRjU3RhdHMgJiYgdGhpcy53ZWJSdGNTdGF0cy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5zdG9wV2ViUnRjU3RhdHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SWNlU2VydmVyc0NvbmYoKTogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgcmV0dXJuVmFsdWU7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMgPT09ICdmcmVlaWNlJyA/XG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGB2aWRlb2AgZWxlbWVudCBwYXJhbWV0ZXIgZGlzcGxheSB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IGFyZVxuICAgICAqIFttYW5hZ2luZyB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd25dKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpXG4gICAgICpcbiAgICAgKiBDYWxsaW5nIHRoaXMgbWV0aG9kIHdpdGggYSB2aWRlbyBhbHJlYWR5IGFkZGVkIHRvIG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgY2F1c2UgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYmVcbiAgICAgKiBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBwcmV2aW91cyBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgdG8gYmUgYXNzb2NpYXRlZCB0byB0aGlzIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIDEgaWYgdGhlIHZpZGVvIHdhc24ndCBhc3NvY2lhdGVkIHRvIGFueSBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqIDAgaWYgdGhlIHZpZGVvIHdhcyBhbHJlYWR5IGFkZGVkIHRvIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXIuIC0xIGlmIHRoZSB2aWRlbyB3YXMgcHJldmlvdXNseSBhc3NvY2lhdGVkIHRvIGFueSBvdGhlclxuICAgICAqIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgb25lIGFuZCBwcm9wZXJseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKi9cbiAgICBhZGRWaWRlb0VsZW1lbnQodmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgLy8gSWYgdGhlIHZpZGVvIGVsZW1lbnQgaXMgYWxyZWFkeSBwYXJ0IG9mIHRoaXMgU3RyZWFtTWFuYWdlciBkbyBub3RoaW5nXG4gICAgICAgIGZvciAoY29uc3QgdiBvZiB0aGlzLnZpZGVvcykge1xuICAgICAgICAgICAgaWYgKHYudmlkZW8gPT09IHZpZGVvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmV0dXJuTnVtYmVyID0gMTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3Muc2xpY2UoKS5yZXZlcnNlKCkuZm9yRWFjaCgoc3RyZWFtTWFuYWdlclZpZGVvLCBpbmRleCwgdmlkZW9zKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgb25jYW5wbGF5IGV2ZW50IGxpc3RlbmVyIChvbmx5IE9wZW5WaWR1IGJyb3dzZXIgb25lLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICAgICAgaWYgKCEhc3RyZWFtTWFuYWdlclZpZGVvLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbW92ZSB2aWRlb3MgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyICh0aG9zZSBnZW5lcmF0ZWQgYnkgcGFzc2luZyBhIHZhbGlkIHRhcmdldEVsZW1lbnQgaW4gT3BlblZpZHUuaW5pdFB1Ymxpc2hlciBhbmQgU2Vzc2lvbi5zdWJzY3JpYmVcbiAgICAgICAgICAgICAgICAvLyBvciB0aG9zZSBjcmVhdGVkIGJ5IFN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KS4gVGhlc2UgYXJlIGFsc28gdGhlIHZpZGVvcyB0aGF0IHRyaWdnZXJlZCBhIHZpZGVvRWxlbWVudENyZWF0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucGFyZW50Tm9kZSEucmVtb3ZlQ2hpbGQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50RGVzdHJveWVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZSh2aWRlb3MubGVuZ3RoIC0gMSAtIGluZGV4LCAxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHNyY09iamVjdCBpbiBhbGwgdmlkZW9zIG1hbmFnZWQgYnkgdGhlIHVzZXJcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwcG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gY2FwdHVyZSBzb21lIGRlc2t0b3Agc2NyZWVuIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBoYXMgYmVlbiBjYWxsZWQgd2l0aCBwcm9wZXJ0aWVzIGB2aWRlb1NvdXJjZWAgYW5kIGBhdWRpb1NvdXJjZWAgb2ZcbiAgICAgKiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBwYXJhbWV0ZXIgYm90aCBzZXQgdG8gKmZhbHNlKiBvciAqbnVsbCpcbiAgICAgKi9cbiAgICBOT19JTlBVVF9TT1VSQ0VfU0VUID0gJ05PX0lOUFVUX1NPVVJDRV9TRVQnLFxuXG4gICAgLyoqXG4gICAgICogU29tZSBtZWRpYSBwcm9wZXJ0eSBvZiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBzdWNoIGFzIGBmcmFtZVJhdGVgIG9yIGByZXNvbHV0aW9uYCBpcyBub3Qgc3VwcG9ydGVkXG4gICAgICogYnkgdGhlIGlucHV0IGRldmljZXMgKHdoZW5ldmVyIGl0IGlzIHBvc3NpYmxlIHRoZXkgYXJlIGF1dG9tYXRpY2FsbHkgYWRqdXN0ZWQgdG8gdGhlIG1vc3Qgc2ltaWxhciB2YWx1ZSkuXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEID0gJ09QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuLyoqXG4gKiBTaW1wbGUgb2JqZWN0IHRvIGlkZW50aWZ5IHJ1bnRpbWUgZXJyb3JzIG9uIHRoZSBjbGllbnQgc2lkZVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHVFcnJvciB7XG5cbiAgICBuYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBIb3cgdGhlIHZpZGVvIHdpbGwgYmUgaW5zZXJ0ZWQgaW4gdGhlIERPTSBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuIFNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dIGFuZCBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXVxuICovXG5leHBvcnQgZW51bSBWaWRlb0luc2VydE1vZGUge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHRhcmdldCBlbGVtZW50IChhcyBuZXh0IHNpYmxpbmcpXG4gICAgICovXG4gICAgQUZURVIgPSAnQUZURVInLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGxhc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgQVBQRU5EID0gJ0FQUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYmVmb3JlIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgcHJldmlvdXMgc2libGluZylcbiAgICAgKi9cbiAgICBCRUZPUkUgPSAnQkVGT1JFJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBmaXJzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBQUkVQRU5EID0gJ1BSRVBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIHJlcGxhY2VzIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUkVQTEFDRSA9ICdSRVBMQUNFJ1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYGNvbm5lY3Rpb25DcmVhdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgY29ubmVjdGlvbkRlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgd2FzIGNyZWF0ZWQgb3IgZGVzdHJveWVkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZvciAnY29ubmVjdGlvbkRlc3Ryb3llZCcgZXZlbnQ6XG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3VyIHRoYXQgbWF5IGJlIHByZXZlbnRlZCBieSBjYWxsaW5nIFtbRXZlbnQucHJldmVudERlZmF1bHRdXVxuICAgICAqL1xuICAgIGNhbmNlbGFibGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0IHRoYXQgZGlzcGF0Y2hlZCB0aGUgZXZlbnRcbiAgICAgKi9cbiAgICB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHR5cGUgb2YgZXZlbnQuIFRoaXMgaXMgdGhlIHNhbWUgc3RyaW5nIHlvdSBwYXNzIGFzIGZpcnN0IHBhcmFtZXRlciB3aGVuIGNhbGxpbmcgbWV0aG9kIGBvbigpYCBvZiBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBbW0V2ZW50RGlzcGF0Y2hlcl1dIGludGVyZmFjZVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIHByaXZhdGUgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvdXI6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvdXIgPSAoKSA9PiB7IH07XG4gICAgICAgIHRoaXMuaGFzQmVlblByZXZlbnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHJlY29yZGluZ1N0YXJ0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGByZWNvcmRpbmdTdG9wcGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIElEIGdlbmVyYXRlZCBpbiBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlY29yZGluZyBuYW1lIHlvdSBzdXBwbGllZCB0byBvcGVudmlkdS1zZXJ2ZXIuIEZvciBleGFtcGxlLCB0byBuYW1lIHlvdXIgcmVjb3JkaW5nIGZpbGUgTVlfUkVDT1JESU5HOlxuICAgICAqIC0gV2l0aCAqKkFQSSBSRVNUKio6IFBPU1QgdG8gYC9hcGkvcmVjb3JkaW5ncy9zdGFydGAgcGFzc2luZyBKU09OIGJvZHkgYHtcInNlc3Npb25cIjpcInNlc3Npb25JZFwiLFwibmFtZVwiOlwiTVlfUkVDT1JESU5HXCJ9YFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LWphdmEtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIE1ZX1JFQ09SRElORylgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKE1ZX1JFQ09SRElORykuYnVpbGQoKSlgXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtbm9kZS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgTVlfUkVDT1JESU5HKWAgb3IgYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgbmV3IFJlY29yZGluZ1Byb3BlcnRpZXMuQnVpbGRlcigpLm5hbWUoTVlfUkVDT1JESU5HKS5idWlsZCgpKWBcbiAgICAgKlxuICAgICAqIElmIG5vIG5hbWUgaXMgc3VwcGxpZWQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSB1bmRlZmluZWQgYW5kIHRoZSByZWNvcmRlZCBmaWxlIHdpbGwgYmUgbmFtZWQgYWZ0ZXIgcHJvcGVydHkgW1tpZF1dXG4gICAgICovXG4gICAgbmFtZT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIGlmIChuYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogeW91IGhhdmUgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogeW91ciBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHRydWUsIHRhcmdldCwgJ3Nlc3Npb25EaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkNhbGxpbmcgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvdXIoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEZvciAnc3RyZWFtRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwidW5wdWJsaXNoXCI6IG1ldGhvZCBgU2Vzc2lvbi51bnB1Ymxpc2goKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogbWV0aG9kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcIm5ldHdvcmtEaXNjb25uZWN0XCI6IHRoZSB1c2VyJ3MgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ3N0cmVhbUNyZWF0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFB1Ymxpc2hlciwgdHlwZTogc3RyaW5nLCBzdHJlYW06IFN0cmVhbSwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgUHVibGlzaGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9jYWwgU3RyZWFtXG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW91ciB1cG9uICdcIiArIHRoaXMudHlwZSArIFwiJyBldmVudCBkaXNwYXRjaGVkIGJ5ICdQdWJsaXNoZXInXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHZpZGVvRWxlbWVudENyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuIFNlZVxuICogW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uLlxuICogLSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSB3aGVuZXZlciBhbiBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWRlb0VsZW1lbnRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGVsZW1lbnQgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBlbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQsIHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiZnVuY3Rpb24gTWFwcGVyKClcbntcbiAgdmFyIHNvdXJjZXMgPSB7fTtcblxuXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKVxuICB7XG4gICAgZm9yKHZhciBrZXkgaW4gc291cmNlcylcbiAgICB7XG4gICAgICB2YXIgc291cmNlID0gc291cmNlc1trZXldO1xuXG4gICAgICBmb3IodmFyIGtleTIgaW4gc291cmNlKVxuICAgICAgICBjYWxsYmFjayhzb3VyY2Vba2V5Ml0pO1xuICAgIH07XG4gIH07XG5cbiAgdGhpcy5nZXQgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBpZHNbaWRdO1xuICB9O1xuXG4gIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcblxuICAgIGRlbGV0ZSBpZHNbaWRdO1xuXG4gICAgLy8gQ2hlY2sgaXQncyBlbXB0eVxuICAgIGZvcih2YXIgaSBpbiBpZHMpe3JldHVybiBmYWxzZX1cblxuICAgIGRlbGV0ZSBzb3VyY2VzW3NvdXJjZV07XG4gIH07XG5cbiAgdGhpcy5zZXQgPSBmdW5jdGlvbih2YWx1ZSwgaWQsIHNvdXJjZSlcbiAge1xuICAgIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHNvdXJjZXNbc291cmNlXSA9IGlkcyA9IHt9O1xuXG4gICAgaWRzW2lkXSA9IHZhbHVlO1xuICB9O1xufTtcblxuXG5NYXBwZXIucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG57XG4gIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGlkLCBzb3VyY2UpO1xuICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICByZXR1cm4gdmFsdWU7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gTWFwcGVyO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBKc29uUnBjQ2xpZW50ICA9IHJlcXVpcmUoJy4vanNvbnJwY2NsaWVudCcpO1xuXG5cbmV4cG9ydHMuSnNvblJwY0NsaWVudCAgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uLycpO1xudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5EYXRlLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiArbmV3IERhdGU7XG59O1xuXG52YXIgUElOR19JTlRFUlZBTCA9IDUwMDA7XG5cbnZhciBSRUNPTk5FQ1RJTkcgPSAnUkVDT05ORUNUSU5HJztcbnZhciBDT05ORUNURUQgPSAnQ09OTkVDVEVEJztcbnZhciBESVNDT05ORUNURUQgPSAnRElTQ09OTkVDVEVEJztcblxudmFyIExvZ2dlciA9IGNvbnNvbGU7XG5cbi8qKlxuICpcbiAqIGhlYXJ0YmVhdDogaW50ZXJ2YWwgaW4gbXMgZm9yIGVhY2ggaGVhcnRiZWF0IG1lc3NhZ2UsXG4gKiBzZW5kQ2xvc2VNZXNzYWdlIDogdHJ1ZSAvIGZhbHNlLCBiZWZvcmUgY2xvc2luZyB0aGUgY29ubmVjdGlvbiwgaXQgc2VuZHMgYSBjbG9zZVNlc3Npb24gbWVzc2FnZVxuICogPHByZT5cbiAqIHdzIDoge1xuICogXHR1cmkgOiBVUkkgdG8gY29ubnRlY3QgdG8sXG4gKiAgdXNlU29ja0pTIDogdHJ1ZSAodXNlIFNvY2tKUykgLyBmYWxzZSAodXNlIFdlYlNvY2tldCkgYnkgZGVmYXVsdCxcbiAqIFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuICogXHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcbiAqIFx0b25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG4gKiBcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbiAqIFx0b25lcnJvciA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGVyZSBpcyBhbiBlcnJvclxuICogfSxcbiAqIHJwYyA6IHtcbiAqIFx0cmVxdWVzdFRpbWVvdXQgOiB0aW1lb3V0IGZvciBhIHJlcXVlc3QsXG4gKiBcdHNlc3Npb25TdGF0dXNDaGFuZ2VkOiBjYWxsYmFjayBtZXRob2QgZm9yIGNoYW5nZXMgaW4gc2Vzc2lvbiBzdGF0dXMsXG4gKiBcdG1lZGlhUmVuZWdvdGlhdGlvbjogbWVkaWFSZW5lZ290aWF0aW9uXG4gKiB9XG4gKiA8L3ByZT5cbiAqL1xuZnVuY3Rpb24gSnNvblJwY0NsaWVudChjb25maWd1cmF0aW9uKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgd3NDb25maWcgPSBjb25maWd1cmF0aW9uLndzO1xuXG4gICAgdmFyIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSAtMTtcblxuICAgIHZhciBwaW5nTmV4dE51bSA9IDA7XG4gICAgdmFyIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgdmFyIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgIHZhciBwaW5nSW50ZXJ2YWw7XG5cbiAgICB2YXIgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgdmFyIG9ucmVjb25uZWN0aW5nID0gd3NDb25maWcub25yZWNvbm5lY3Rpbmc7XG4gICAgdmFyIG9ucmVjb25uZWN0ZWQgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGVkO1xuICAgIHZhciBvbmNvbm5lY3RlZCA9IHdzQ29uZmlnLm9uY29ubmVjdGVkO1xuICAgIHZhciBvbmVycm9yID0gd3NDb25maWcub25lcnJvcjtcblxuICAgIGNvbmZpZ3VyYXRpb24ucnBjLnB1bGwgPSBmdW5jdGlvbihwYXJhbXMsIHJlcXVlc3QpIHtcbiAgICAgICAgcmVxdWVzdC5yZXBseShudWxsLCBcInB1c2hcIik7XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNUSU5HIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBSRUNPTk5FQ1RJTkcpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIFJFQ09OTkVDVElORyBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVElORyBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXR1cyA9IFJFQ09OTkVDVElORztcbiAgICAgICAgaWYgKG9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9ucmVjb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uY29ubmVjdGVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05DT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVzZVBpbmcoKTtcblxuICAgICAgICBpZiAob25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9ORVJST1IgLS0tLS0tLS0tLS1cIik7XG5cbiAgICAgICAgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgICAgIGlmIChvbmVycm9yKSB7XG4gICAgICAgICAgICBvbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKHdzQ29uZmlnKTtcblxuICAgIExvZ2dlci5kZWJ1ZygnQ29ubmVjdGluZyB3ZWJzb2NrZXQgdG8gVVJJOiAnICsgd3NDb25maWcudXJpKTtcblxuICAgIHZhciBycGNCdWlsZGVyT3B0aW9ucyA9IHtcbiAgICAgICAgcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5yZXF1ZXN0VGltZW91dCxcbiAgICAgICAgcGluZ19yZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLmhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0XG4gICAgfTtcblxuICAgIHZhciBycGMgPSBuZXcgUnBjQnVpbGRlcihScGNCdWlsZGVyLnBhY2tlcnMuSnNvblJQQywgcnBjQnVpbGRlck9wdGlvbnMsIHdzLFxuICAgICAgICBmdW5jdGlvbihyZXF1ZXN0KSB7XG5cbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVjZWl2ZWQgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IGNvbmZpZ3VyYXRpb24ucnBjW3JlcXVlc3QubWV0aG9kXTtcblxuICAgICAgICAgICAgICAgIGlmIChmdW5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWV0aG9kIFwiICsgcmVxdWVzdC5tZXRob2QgKyBcIiBub3QgcmVnaXN0ZXJlZCBpbiBjbGllbnRcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyhyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKCdFeGNlcHRpb24gcHJvY2Vzc2luZyByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAobWV0aG9kICE9PSAncGluZycpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVxdWVzdDogbWV0aG9kOicgKyBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgcnBjLmVuY29kZShtZXRob2QsIHBhcmFtcywgZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1I6XCIgKyBlcnJvci5tZXNzYWdlICsgXCIgaW4gUmVxdWVzdDogbWV0aG9kOlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyBcIiByZXF1ZXN0OlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1IgREFUQTpcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yLmRhdGEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdFRpbWUgPSByZXF1ZXN0VGltZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT0gdW5kZWZpbmVkICYmIHJlc3VsdC52YWx1ZSAhPT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVzcG9uc2U6ICcgKyBKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIm5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBcIiArIHBpbmdOZXh0TnVtICsgJyAob2xkPScgK1xuICAgICAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiArICcpJyk7XG4gICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBwaW5nTmV4dE51bTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZW5kUGluZygpIHtcbiAgICAgICAgaWYgKGVuYWJsZWRQaW5ncykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG51bGw7XG4gICAgICAgICAgICBpZiAocGluZ05leHROdW0gPT0gMCB8fCBwaW5nTmV4dE51bSA9PSBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbDogY29uZmlndXJhdGlvbi5oZWFydGJlYXQgfHwgUElOR19JTlRFUlZBTFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwaW5nTmV4dE51bSsrO1xuXG4gICAgICAgICAgICBzZWxmLnNlbmQoJ3BpbmcnLCBwYXJhbXMsIChmdW5jdGlvbihwaW5nTnVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJFcnJvciBpbiBwaW5nIHJlcXVlc3QgI1wiICsgcGluZ051bSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubWVzc2FnZSArIFwiKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaW5nTnVtID4gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZXJ2ZXIgZGlkIG5vdCByZXNwb25kIHRvIHBpbmcgbWVzc2FnZSAjXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5nTnVtICsgXCIuIFJlY29ubmVjdGluZy4uLiBcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKHBpbmdOZXh0TnVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUcnlpbmcgdG8gc2VuZCBwaW5nLCBidXQgcGluZyBpcyBub3QgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgKiBJZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0IGhhcyBhbnkgdmFsdWUsIHRoZSBwaW5nLXBvbmcgd2lsbCB3b3JrIHdpdGggdGhlIGludGVydmFsXG4gICAgKiBvZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0XG4gICAgKi9cbiAgICBmdW5jdGlvbiB1c2VQaW5nKCkge1xuICAgICAgICBpZiAoIXBpbmdQb25nU3RhcnRlZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgcGluZyAoaWYgY29uZmlndXJlZClcIilcbiAgICAgICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwaW5nSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzZW5kUGluZywgY29uZmlndXJhdGlvbi5oZWFydGJlYXQpO1xuICAgICAgICAgICAgICAgIHNlbmRQaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NpbmcganNvblJwY0NsaWVudCBleHBsaWNpdGx5IGJ5IGNsaWVudFwiKTtcblxuICAgICAgICBpZiAocGluZ0ludGVydmFsICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xlYXJpbmcgcGluZyBpbnRlcnZhbFwiKTtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGNvbmZpZ3VyYXRpb24uc2VuZENsb3NlTWVzc2FnZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VuZGluZyBjbG9zZSBtZXNzYWdlXCIpXG4gICAgICAgICAgICB0aGlzLnNlbmQoJ2Nsb3NlU2Vzc2lvbicsIG51bGwsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyBjbG9zZSBtZXNzYWdlOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcblx0XHRcdHdzLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIHdzLmZvcmNlQ2xvc2UobWlsbGlzKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlY29ubmVjdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpzb25ScGNDbGllbnQ7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gID0gcmVxdWlyZSgnLi93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cblxuZXhwb3J0cy5XZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb247IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxMy0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIEJyb3dzZXJXZWJTb2NrZXQgPSBnbG9iYWwuV2ViU29ja2V0IHx8IGdsb2JhbC5Nb3pXZWJTb2NrZXQ7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqIEdldCBlaXRoZXIgdGhlIGBXZWJTb2NrZXRgIG9yIGBNb3pXZWJTb2NrZXRgIGdsb2JhbHNcbiAqIGluIHRoZSBicm93c2VyIG9yIHRyeSB0byByZXNvbHZlIFdlYlNvY2tldC1jb21wYXRpYmxlXG4gKiBpbnRlcmZhY2UgZXhwb3NlZCBieSBgd3NgIGZvciBOb2RlLWxpa2UgZW52aXJvbm1lbnQuXG4gKi9cblxuLyp2YXIgV2ViU29ja2V0ID0gQnJvd3NlcldlYlNvY2tldDtcbmlmICghV2ViU29ja2V0ICYmIHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgV2ViU29ja2V0ID0gcmVxdWlyZSgnd3MnKTtcbiAgICB9IGNhdGNoIChlKSB7IH1cbn0qL1xuXG4vL3ZhciBTb2NrSlMgPSByZXF1aXJlKCdzb2NranMtY2xpZW50Jyk7XG5cbnZhciBNQVhfUkVUUklFUyA9IDIwMDA7IC8vIEZvcmV2ZXIuLi5cbnZhciBSRVRSWV9USU1FX01TID0gMzAwMDsgLy8gRklYTUU6IEltcGxlbWVudCBleHBvbmVudGlhbCB3YWl0IHRpbWVzLi4uXG5cbnZhciBDT05ORUNUSU5HID0gMDtcbnZhciBPUEVOID0gMTtcbnZhciBDTE9TSU5HID0gMjtcbnZhciBDTE9TRUQgPSAzO1xuXG4vKlxuY29uZmlnID0ge1xuXHRcdHVyaSA6IHdzVXJpLFxuXHRcdHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG5cdFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuXHRcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuXHRcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuXHRcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYobWljcm9zb2Z0RWRnZSkge1xuICAgICAgICBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzKWNhdGNoKG9uRmFpbHVyZSk7XG4gICAgfVxufSwgJ3Bhc3Mgc2Vjb25kIHBhcmFtZXRlciBvbmx5IGlmIHlvdSB3YW50IHN5c3RlbSBhdWRpbycpO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrLCBjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKSkge1xuICAgICAgICAvLyBtaWNyb3NvZnQgZWRnZSA9PiBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSBnZXRTY3JlZW5JZDsiLCIvLyBnbG9iYWwgdmFyaWFibGVzXG52YXIgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbnZhciBzb3VyY2VJZDtcbnZhciBzY3JlZW5DYWxsYmFjaztcbnZhciBpc0ZpcmVmb3ggPSB0eXBlb2Ygd2luZG93Lkluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJztcbnZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG52YXIgaXNDaHJvbWUgPSAhIXdpbmRvdy5jaHJvbWUgJiYgIWlzT3BlcmE7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG59KTtcblxuLy8gYW5kIHRoZSBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgcmVjZWl2ZWQgbWVzc2FnZXNcbmZ1bmN0aW9uIG9uTWVzc2FnZUNhbGxiYWNrKGRhdGEpIHtcbiAgICAvLyBcImNhbmNlbFwiIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgaWYgKGRhdGEgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgaWYgKHNjcmVlbkNhbGxiYWNrKVxuICAgICAgICAgICAgcmV0dXJuIHNjcmVlbkNhbGxiYWNrKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIG5vdGlmaWVkIGhpcyBwcmVzZW5jZVxuICAgIGlmIChkYXRhID09ICdydGNtdWx0aWNvbm5lY3Rpb24tZXh0ZW5zaW9uLWxvYWRlZCcpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnZGVza3RvcCc7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBzaGFyZWQgdGVtcCBzb3VyY2VJZFxuICAgIGlmIChkYXRhLnNvdXJjZUlkICYmIHNjcmVlbkNhbGxiYWNrKSB7XG4gICAgICAgIHNjcmVlbkNhbGxiYWNrKHNvdXJjZUlkID0gZGF0YS5zb3VyY2VJZCwgZGF0YS5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9PT0gdHJ1ZSk7XG4gICAgfVxufVxuXG4vLyB0aGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiBjaHJvbWUgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCAmIGVuYWJsZWQuXG5mdW5jdGlvbiBpc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZShjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spIHJldHVybjtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKSByZXR1cm4gY2FsbGJhY2sodHJ1ZSk7XG5cbiAgICAvLyBhc2sgZXh0ZW5zaW9uIGlmIGl0IGlzIGF2YWlsYWJsZVxuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXJlLXlvdS10aGVyZScsICcqJyk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICB9IGVsc2UgY2FsbGJhY2sodHJ1ZSk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldEN1c3RvbVNvdXJjZUlkKGFyciwgY2FsbGJhY2spIHtcbiAgICBpZiAoIWFyciB8fCAhYXJyLmZvckVhY2gpIHRocm93ICdcImFyclwiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkgYW5kIGl0IG11c3QgYmUgYW4gYXJyYXkuJztcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcblxuICAgIGlmIChzb3VyY2VJZCkgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcblxuICAgIHNjcmVlbkNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgd2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgJ2dldC1jdXN0b20tc291cmNlSWQnOiBhcnJcbiAgICB9LCAnKicpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWRXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXVkaW8tcGx1cy10YWInLCAnKicpO1xufVxuXG5mdW5jdGlvbiBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMoZXh0ZW5zaW9uaWQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCdub3QtY2hyb21lJyk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggIT0gMikge1xuICAgICAgICBjYWxsYmFjayA9IGV4dGVuc2lvbmlkO1xuICAgICAgICBleHRlbnNpb25pZCA9ICdsZmNnZmVwYWZub2JkbG9lY2NobmZhY2xpYmVuam9sZCc7IC8vIGRlZmF1bHQgZXh0ZW5zaW9uLWlkXG4gICAgfVxuICAgIHZhciBpbWFnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIGltYWdlLnNyYyA9ICdjaHJvbWUtZXh0ZW5zaW9uOi8vJyArIGV4dGVuc2lvbmlkICsgJy9pY29uLnBuZyc7XG4gICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xuICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICB9LCAyMDAwKTtcbiAgICB9O1xuICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKCdub3QtaW5zdGFsbGVkJyk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgdHJ1ZSk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gZXhwbGFpbnMgaG93IHRvIHVzZSBhYm92ZSBtZXRob2RzL29iamVjdHNcbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGNhbGxiYWNrLCBjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICBzb3VyY2VJZCA9ICcnO1xuICAgIHZhciBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMgPSB7XG4gICAgICAgIG1vek1lZGlhU291cmNlOiAnd2luZG93JyxcbiAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgfTtcbiAgICBpZiAoaXNGaXJlZm94KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzKTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCBkZWZpbmVzIGdldFVzZXJNZWRpYSBjb25zdHJhaW50c1xuICAgIC8vIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGNhcHR1cmUgY29udGVudCBvZiBzY3JlZW5cbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBjaHJvbWVNZWRpYVNvdXJjZSxcbiAgICAgICAgICAgIG1heFdpZHRoOiBzY3JlZW4ud2lkdGggPiAxOTIwID8gc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgIG1heEhlaWdodDogc2NyZWVuLmhlaWdodCA+IDEwODAgPyBzY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25hbDogW11cbiAgICB9O1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IHZlcmlmaWVzIGNocm9tZSBleHRlbnNpb24gYXZhaWxhYmlsaXR5XG4gICAgLy8gaWYgaW5zdGFsbGVkIGFuZCBhdmFpbGFibGUgdGhlbiBpdCB3aWxsIGludm9rZSBleHRlbnNpb24gQVBJXG4gICAgLy8gb3RoZXJ3aXNlIGl0IHdpbGwgZmFsbGJhY2sgdG8gY29tbWFuZC1saW5lIGJhc2VkIHNjcmVlbiBjYXB0dXJpbmcgQVBJXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJyAmJiAhc291cmNlSWQpIHtcbiAgICAgICAgaWYgKGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbykge1xuICAgICAgICAgICAgZ2V0U291cmNlSWRXaXRoQXVkaW8oZnVuY3Rpb24gKHNvdXJjZUlkLCBjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCBmcmVlaWNlID0gcmVxdWlyZSgnZnJlZWljZScpO1xuaW1wb3J0IHV1aWQgPSByZXF1aXJlKCd1dWlkJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24ge1xuICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgYXVkaW86IGJvb2xlYW4sXG4gICAgICAgIHZpZGVvOiBib29sZWFuXG4gICAgfTtcbiAgICBzaW11bGNhc3Q6IGJvb2xlYW47XG4gICAgb25pY2VjYW5kaWRhdGU6IChldmVudCkgPT4gdm9pZDtcbiAgICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZDtcbiAgICBtZWRpYVN0cmVhbT86IE1lZGlhU3RyZWFtO1xuICAgIG1vZGU/OiBzdHJpbmc7IC8vIHNlbmRvbmx5LCByZWNvbmx5LCBzZW5kcmVjdlxuICAgIGlkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlciB7XG5cbiAgICBwYzogUlRDUGVlckNvbm5lY3Rpb247XG4gICAgaWQ6IHN0cmluZztcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzID0gKCEhdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiYgdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMubGVuZ3RoID4gMCkgPyB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA6IGZyZWVpY2UoKTtcblxuICAgICAgICB0aGlzLnBjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHsgaWNlU2VydmVyczogdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgfSk7XG4gICAgICAgIHRoaXMuaWQgPSAhIWNvbmZpZ3VyYXRpb24uaWQgPyBjb25maWd1cmF0aW9uLmlkIDogdXVpZC52NCgpO1xuXG4gICAgICAgIHRoaXMucGMub25pY2VjYW5kaWRhdGUgPSBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSA9IGV2ZW50LmNhbmRpZGF0ZTtcbiAgICAgICAgICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ub25pY2VjYW5kaWRhdGUoZXZlbnQuY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5wYy5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKDxSVENJY2VDYW5kaWRhdGU+dGhpcy5pY2VDYW5kaWRhdGVMaXN0LnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIHRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QgdGFraW5nIGludG8gYWNjb3VudCB0aGVcbiAgICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICAgKiBwcm9jZXNzOiBnZW5lcmF0ZXMgdGhlIFNEUCBvZmZlciBhbmQgaW52b2tlcyB0aGUgb25zZHBvZmZlciBjYWxsYmFjay4gVGhpc1xuICAgICAqIGNhbGxiYWNrIGlzIGV4cGVjdGVkIHRvIHNlbmQgdGhlIFNEUCBvZmZlciwgaW4gb3JkZXIgdG8gb2J0YWluIGFuIFNEUFxuICAgICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICAgKi9cbiAgICBzdGFydCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdUaGUgcGVlciBjb25uZWN0aW9uIG9iamVjdCBpcyBpbiBcImNsb3NlZFwiIHN0YXRlLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBhbiBpbnZvY2F0aW9uIG9mIHRoZSBkaXNwb3NlIG1ldGhvZCBiZWZvcmUgYWNjZXB0aW5nIGluIHRoZSBkaWFsb2d1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRTdHJlYW0odGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gW0hhY2tdIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDM1NThcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9PT0gJ3NlbmRvbmx5JyAmJlxuICAgICAgICAgICAgICAgIChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS52ZXJzaW9uIS50b1N0cmluZygpLnN1YnN0cmluZygwLCAyKSA9PT0gJzM5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgZnJlZXMgdGhlIHJlc291cmNlcyB1c2VkIGJ5IFdlYlJ0Y1BlZXJcbiAgICAgKi9cbiAgICBkaXNwb3NlKCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIHRoaXMucGMuZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChzdHIgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVN0b3Aoc3RyKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAgICAgICAgICAgLy8gaWYodmlkZW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbSh2aWRlb1N0cmVhbSk7XG4gICAgICAgICAgICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogMSkgRnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIG9mZmVyLCBzZXRzIGl0IGFzIGxvY2FsIGRlc2NyaXB0aW9uIGFuZCByZXR1cm5zIHRoZSBvZmZlciBwYXJhbVxuICAgICAqIHRvIHNlbmQgdG8gT3BlblZpZHUgU2VydmVyICh3aWxsIGJlIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gb2Ygb3RoZXIgcGVlcilcbiAgICAgKi9cbiAgICBnZW5lcmF0ZU9mZmVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgb2ZmZXJBdWRpbywgb2ZmZXJWaWRlbyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICBvZmZlclZpZGVvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlclZpZGVvKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUlRDUGVlckNvbm5lY3Rpb24gY29uc3RyYWludHM6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuXG4gICAgICAgICAgICB0aGlzLnBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpO1xuICAgICAgICAgICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0xvY2FsIGRlc2NyaXB0aW9uIGlzIG5vdCBkZWZpbmVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDIpIEZ1bmN0aW9uIHRvIGludm9rZSB3aGVuIGEgU0RQIG9mZmVyIGlzIHJlY2VpdmVkLiBTZXRzIGl0IGFzIHJlbW90ZSBkZXNjcmlwdGlvbixcbiAgICAgKiBnZW5lcmF0ZXMgYW5kIGFuc3dlciBhbmQgcmV0dXJucyBpdCB0byBzZW5kIGl0IHRvIE9wZW5WaWR1IFNlcnZlclxuICAgICAqL1xuICAgIHByb2Nlc3NPZmZlcihzZHBPZmZlcjogc3RyaW5nKTogUHJvbWlzZTxDb25zdHJhaW5ET01TdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBPZmZlclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU0RQIG9mZmVyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuY3JlYXRlQW5zd2VyKCk7XG4gICAgICAgICAgICAgICAgfSkudGhlbihhbnN3ZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBhbnN3ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbERlc2NyaXB0aW9uID0gdGhpcy5wYy5sb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKDxzdHJpbmc+bG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDMpIEZ1bmN0aW9uIGludm9rZWQgd2hlbiBhIFNEUCBhbnN3ZXIgaXMgcmVjZWl2ZWQuIEZpbmFsIHN0ZXAgaW4gU0RQIG5lZ290aWF0aW9uLCB0aGUgcGVlclxuICAgICAqIGp1c3QgbmVlZHMgdG8gc2V0IHRoZSBhbnN3ZXIgYXMgaXRzIHJlbW90ZSBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIHByb2Nlc3NBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnUlRDUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZS5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdGFibGUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtU3RvcChzdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHtcbiAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclJlY3Zvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRyZWN2IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRyZWN2JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzRW5hYmxlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNJbnRlcnZhbElkOiBOb2RlSlMuVGltZXI7XG4gICAgcHJpdmF0ZSBzdGF0c0ludGVydmFsID0gMTtcbiAgICBwcml2YXRlIHN0YXRzOiBhbnkgPSB7XG4gICAgICAgIGluYm91bmQ6IHtcbiAgICAgICAgICAgIGF1ZGlvOiB7XG4gICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwLFxuICAgICAgICAgICAgICAgIGZyYW1lc0RlY29kZWQ6IDAsXG4gICAgICAgICAgICAgICAgbmFja0NvdW50OiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNFbmNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHsgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWJSdGMgc3RhdHMgZW5hYmxlZCBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGNvbnN0IGluc3RydW1lbnRhdGlvbiA9IEpTT04ucGFyc2UoZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgdGhpcy5zdGF0c0ludGVydmFsID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KGluc3RydW1lbnRhdGlvbikpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRzSW50ZXJ2YWwgKiAxMDAwKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIHN0b3BwZWQgZm9yIGRpc3Bvc2VkIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLFxuICAgICAgICAgICAgICAgIChzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxvY2FsQ2FuZGlkYXRlSWQsIHJlbW90ZUNhbmRpZGF0ZUlkLCBnb29nQ2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gc3RhdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAnbG9jYWxjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlc1tzdGF0LmlkXSA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0LnR5cGUgPT09ICdyZW1vdGVjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAnZ29vZ0NhbmRpZGF0ZVBhaXInICYmIChzdGF0Lmdvb2dBY3RpdmVDb25uZWN0aW9uID09PSAndHJ1ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVJZCA9IHN0YXQubG9jYWxDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzdGF0LnJlbW90ZUNhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaW5hbExvY2FsQ2FuZGlkYXRlID0gbG9jYWxDYW5kaWRhdGVzW2xvY2FsQ2FuZGlkYXRlSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZmluYWxMb2NhbENhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwQWRkcmVzcykgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZS5yYXcgPSAhIWNhbmRbMF0gPyBjYW5kWzBdLmNhbmRpZGF0ZSA6ICdFUlJPUjogQ2Fubm90IGZpbmQgbG9jYWwgY2FuZGlkYXRlIGluIGxpc3Qgb2Ygc2VudCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSBsb2NhbCBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSByZW1vdGVDYW5kaWRhdGVzW3JlbW90ZUNhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucG9ydE51bWJlcikgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIHJlbW90ZSBjYW5kaWRhdGUgaW4gbGlzdCBvZiByZWNlaXZlZCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgcmVtb3RlIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlOiBmaW5hbExvY2FsQ2FuZGlkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZTogZmluYWxSZW1vdGVDYW5kaWRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdTZWxlY3RlZCBJQ0UgY2FuZGlkYXRlIGluZm8gb25seSBhdmFpbGFibGUgZm9yIENocm9tZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBodHRwOiBYTUxIdHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgY29uc3QgdXJsOiBzdHJpbmcgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmh0dHBFbmRwb2ludDtcbiAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIHVybCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcblxuICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7IC8vIENhbGwgYSBmdW5jdGlvbiB3aGVuIHRoZSBzdGF0ZSBjaGFuZ2VzLlxuICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQgJiYgaHR0cC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2ViUnRjIHN0YXRzIHN1Y2Nlc3NmdWxseSBzZW50IHRvICcgKyB1cmwgKyAnIGZvciBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0dHAuc2VuZChqc29uKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmID0gKHN0YXRzKSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQucmVtb3RlSWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGppdCA9IHN0YXQuaml0dGVyICogMTAwMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6IGppdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IChzdGF0LnBhY2tldHNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogJ3BhY2tldHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQubmFja0NvdW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkID0gc3RhdC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lm5hY2tDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QgPSBzdGF0LnBhY2tldHNMb3N0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChzdGF0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgaW5ib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdvdXRib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ3NzcmMnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnYnl0ZXNSZWNlaXZlZCcgaW4gc3RhdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXQubWVkaWFUeXBlID09PSAnYXVkaW8nICYmICdhdWRpb091dHB1dExldmVsJyBpbiBzdGF0KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJyAmJiAncXBTdW0nIGluIHN0YXQpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5ib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBzdGF0Lmdvb2dKaXR0ZXJCdWZmZXJNcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQuZ29vZ05hY2tzU2VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2J5dGVzU2VudCcgaW4gc3RhdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG91dGJvdW5kLXJ0cFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSwgZiwgKGVycm9yKSA9PiB7IGNvbnNvbGUubG9nKGVycm9yKTsgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZSk7XG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG5cbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2Vba2V5XSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2gocmVwb3J0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHN1Y2Nlc3NDYiwgZmFpbHVyZUNiKSB7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhudWxsKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZhaWx1cmVDYik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0sIG51bGwsIGZhaWx1cmVDYik7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iXX0= diff --git a/openvidu-hello-world/web/index.html b/openvidu-hello-world/web/index.html index 149d4147..0a7ea0e4 100644 --- a/openvidu-hello-world/web/index.html +++ b/openvidu-hello-world/web/index.html @@ -5,7 +5,7 @@ - + diff --git a/openvidu-hello-world/web/openvidu-browser-2.1.0.js b/openvidu-hello-world/web/openvidu-browser-2.1.0.js deleted file mode 100644 index 3f2f3477..00000000 --- a/openvidu-hello-world/web/openvidu-browser-2.1.0.js +++ /dev/null @@ -1,10290 +0,0 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - // At least give some kind of context to the user - var err = new Error('Unhandled "error" event. (' + er + ')'); - err.context = er; - throw err; - } - return false; - } - - handler = events[type]; - - if (!handler) - return false; - - var isFn = typeof handler === 'function'; - len = arguments.length; - switch (len) { - // fast cases - case 1: - emitNone(handler, isFn, this); - break; - case 2: - emitOne(handler, isFn, this, arguments[1]); - break; - case 3: - emitTwo(handler, isFn, this, arguments[1], arguments[2]); - break; - case 4: - emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); - break; - // slower - default: - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - emitMany(handler, isFn, this, args); - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = target._events; - if (!events) { - events = target._events = objectCreate(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener) { - target.emit('newListener', type, - listener.listener ? listener.listener : listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (!existing) { - // Optimize the case of one listener. Don't need the extra array object. - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - } else { - // If we've already got an array, just append. - if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - } - - // Check for listener leak - if (!existing.warned) { - m = $getMaxListeners(target); - if (m && m > 0 && existing.length > m) { - existing.warned = true; - var w = new Error('Possible EventEmitter memory leak detected. ' + - existing.length + ' "' + String(type) + '" listeners ' + - 'added. Use emitter.setMaxListeners() to ' + - 'increase limit.'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - if (typeof console === 'object' && console.warn) { - console.warn('%s: %s', w.name, w.message); - } - } - } - } - - return target; -} - -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - switch (arguments.length) { - case 0: - return this.listener.call(this.target); - case 1: - return this.listener.call(this.target, arguments[0]); - case 2: - return this.listener.call(this.target, arguments[0], arguments[1]); - case 3: - return this.listener.call(this.target, arguments[0], arguments[1], - arguments[2]); - default: - var args = new Array(arguments.length); - for (var i = 0; i < args.length; ++i) - args[i] = arguments[i]; - this.listener.apply(this.target, args); - } - } -} - -function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; - var wrapped = bind.call(onceWrapper, state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -EventEmitter.prototype.once = function once(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - -// Emits a 'removeListener' event if and only if the listener was removed. -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - var list, events, position, i, originalListener; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = this._events; - if (!events) - return this; - - list = events[type]; - if (!list) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - position = -1; - - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else - spliceOne(list, position); - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener) - this.emit('removeListener', type, originalListener || listener); - } - - return this; - }; - -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - var listeners, events, i; - - events = this._events; - if (!events) - return this; - - // not listening for removeListener, no need to emit - if (!events.removeListener) { - if (arguments.length === 0) { - this._events = objectCreate(null); - this._eventsCount = 0; - } else if (events[type]) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else - delete events[type]; - } - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - var keys = objectKeys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = objectCreate(null); - this._eventsCount = 0; - return this; - } - - listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - var events = target._events; - - if (!events) - return []; - - var evlistener = events[type]; - if (!evlistener) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); -} - -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } -}; - -EventEmitter.prototype.listenerCount = listenerCount; -function listenerCount(type) { - var events = this._events; - - if (events) { - var evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener) { - return evlistener.length; - } - } - - return 0; -} - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; -}; - -// About 1.5x faster than the two-arg version of Array#splice(). -function spliceOne(list, index) { - for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) - list[i] = list[k]; - list.pop(); -} - -function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) - copy[i] = arr[i]; - return copy; -} - -function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; -} - -function objectCreatePolyfill(proto) { - var F = function() {}; - F.prototype = proto; - return new F; -} -function objectKeysPolyfill(obj) { - var keys = []; - for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { - keys.push(k); - } - return k; -} -function functionBindPolyfill(context) { - var fn = this; - return function () { - return fn.apply(context, arguments); - }; -} - -},{}],2:[function(require,module,exports){ -/* jshint node: true */ -'use strict'; - -var normalice = require('normalice'); - -/** - # freeice - - The `freeice` module is a simple way of getting random STUN or TURN server - for your WebRTC application. The list of servers (just STUN at this stage) - were sourced from this [gist](https://gist.github.com/zziuni/3741933). - - ## Example Use - - The following demonstrates how you can use `freeice` with - [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): - - <<< examples/quickconnect.js - - As the `freeice` module generates ice servers in a list compliant with the - WebRTC spec you will be able to use it with raw `RTCPeerConnection` - constructors and other WebRTC libraries. - - ## Hey, don't use my STUN/TURN server! - - If for some reason your free STUN or TURN server ends up in the - list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or - [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) - that is used in this module, you can feel - free to open an issue on this repository and those servers will be removed - within 24 hours (or sooner). This is the quickest and probably the most - polite way to have something removed (and provides us some visibility - if someone opens a pull request requesting that a server is added). - - ## Please add my server! - - If you have a server that you wish to add to the list, that's awesome! I'm - sure I speak on behalf of a whole pile of WebRTC developers who say thanks. - To get it into the list, feel free to either open a pull request or if you - find that process a bit daunting then just create an issue requesting - the addition of the server (make sure you provide all the details, and if - you have a Terms of Service then including that in the PR/issue would be - awesome). - - ## I know of a free server, can I add it? - - Sure, if you do your homework and make sure it is ok to use (I'm currently - in the process of reviewing the terms of those STUN servers included from - the original list). If it's ok to go, then please see the previous entry - for how to add it. - - ## Current List of Servers - - * current as at the time of last `README.md` file generation - - ### STUN - - <<< stun.json - - ### TURN - - <<< turn.json - -**/ - -var freeice = module.exports = function(opts) { - // if a list of servers has been provided, then use it instead of defaults - var servers = { - stun: (opts || {}).stun || require('./stun.json'), - turn: (opts || {}).turn || require('./turn.json') - }; - - var stunCount = (opts || {}).stunCount || 2; - var turnCount = (opts || {}).turnCount || 0; - var selected; - - function getServers(type, count) { - var out = []; - var input = [].concat(servers[type]); - var idx; - - while (input.length && out.length < count) { - idx = (Math.random() * input.length) | 0; - out = out.concat(input.splice(idx, 1)); - } - - return out.map(function(url) { - //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up - if ((typeof url !== 'string') && (! (url instanceof String))) { - return url; - } else { - return normalice(type + ':' + url); - } - }); - } - - // add stun servers - selected = [].concat(getServers('stun', stunCount)); - - if (turnCount) { - selected = selected.concat(getServers('turn', turnCount)); - } - - return selected; -}; - -},{"./stun.json":3,"./turn.json":4,"normalice":8}],3:[function(require,module,exports){ -module.exports=[ - "stun.l.google.com:19302", - "stun1.l.google.com:19302", - "stun2.l.google.com:19302", - "stun3.l.google.com:19302", - "stun4.l.google.com:19302", - "stun.ekiga.net", - "stun.ideasip.com", - "stun.schlund.de", - "stun.stunprotocol.org:3478", - "stun.voiparound.com", - "stun.voipbuster.com", - "stun.voipstunt.com", - "stun.voxgratia.org", - "stun.services.mozilla.com" -] - -},{}],4:[function(require,module,exports){ -module.exports=[] - -},{}],5:[function(require,module,exports){ -var WildEmitter = require('wildemitter'); - -function getMaxVolume (analyser, fftBins) { - var maxVolume = -Infinity; - analyser.getFloatFrequencyData(fftBins); - - for(var i=4, ii=fftBins.length; i < ii; i++) { - if (fftBins[i] > maxVolume && fftBins[i] < 0) { - maxVolume = fftBins[i]; - } - }; - - return maxVolume; -} - - -var audioContextType; -if (typeof window !== 'undefined') { - audioContextType = window.AudioContext || window.webkitAudioContext; -} -// use a single audio context due to hardware limits -var audioContext = null; -module.exports = function(stream, options) { - var harker = new WildEmitter(); - - - // make it not break in non-supported browsers - if (!audioContextType) return harker; - - //Config - var options = options || {}, - smoothing = (options.smoothing || 0.1), - interval = (options.interval || 50), - threshold = options.threshold, - play = options.play, - history = options.history || 10, - running = true; - - //Setup Audio Context - if (!audioContext) { - audioContext = new audioContextType(); - } - var sourceNode, fftBins, analyser; - - analyser = audioContext.createAnalyser(); - analyser.fftSize = 512; - analyser.smoothingTimeConstant = smoothing; - fftBins = new Float32Array(analyser.frequencyBinCount); - - if (stream.jquery) stream = stream[0]; - if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { - //Audio Tag - sourceNode = audioContext.createMediaElementSource(stream); - if (typeof play === 'undefined') play = true; - threshold = threshold || -50; - } else { - //WebRTC Stream - sourceNode = audioContext.createMediaStreamSource(stream); - threshold = threshold || -50; - } - - sourceNode.connect(analyser); - if (play) analyser.connect(audioContext.destination); - - harker.speaking = false; - - harker.suspend = function() { - audioContext.suspend(); - } - harker.resume = function() { - audioContext.resume(); - } - Object.defineProperty(harker, 'state', { get: function() { - return audioContext.state; - }}); - audioContext.onstatechange = function() { - harker.emit('state_change', audioContext.state); - } - - harker.setThreshold = function(t) { - threshold = t; - }; - - harker.setInterval = function(i) { - interval = i; - }; - - harker.stop = function() { - running = false; - harker.emit('volume_change', -100, threshold); - if (harker.speaking) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - analyser.disconnect(); - sourceNode.disconnect(); - }; - harker.speakingHistory = []; - for (var i = 0; i < history; i++) { - harker.speakingHistory.push(0); - } - - // Poll the analyser node to determine if speaking - // and emit events if changed - var looper = function() { - setTimeout(function() { - - //check if stop has been called - if(!running) { - return; - } - - var currentVolume = getMaxVolume(analyser, fftBins); - - harker.emit('volume_change', currentVolume, threshold); - - var history = 0; - if (currentVolume > threshold && !harker.speaking) { - // trigger quickly, short history - for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history >= 2) { - harker.speaking = true; - harker.emit('speaking'); - } - } else if (currentVolume < threshold && harker.speaking) { - for (var i = 0; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history == 0) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - } - harker.speakingHistory.shift(); - harker.speakingHistory.push(0 + (currentVolume > threshold)); - - looper(); - }, interval); - }; - looper(); - - - return harker; -} - -},{"wildemitter":24}],6:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],7:[function(require,module,exports){ -/*! - * @name JavaScript/NodeJS Merge v1.2.0 - * @author yeikos - * @repository https://github.com/yeikos/js.merge - - * Copyright 2014 yeikos - MIT license - * https://raw.github.com/yeikos/js.merge/master/LICENSE - */ - -;(function(isNode) { - - /** - * Merge one or more objects - * @param bool? clone - * @param mixed,... arguments - * @return object - */ - - var Public = function(clone) { - - return merge(clone === true, false, arguments); - - }, publicName = 'merge'; - - /** - * Merge two or more objects recursively - * @param bool? clone - * @param mixed,... arguments - * @return object - */ - - Public.recursive = function(clone) { - - return merge(clone === true, true, arguments); - - }; - - /** - * Clone the input removing any reference - * @param mixed input - * @return mixed - */ - - Public.clone = function(input) { - - var output = input, - type = typeOf(input), - index, size; - - if (type === 'array') { - - output = []; - size = input.length; - - for (index=0;index 1) { - url = parts[1]; - parts = parts[0].split(':'); - - // add the output credential and username - output.username = parts[0]; - output.credential = (input || {}).credential || parts[1] || ''; - } - - output.url = protocol + url; - output.urls = [ output.url ]; - - return output; -}; - -},{}],9:[function(require,module,exports){ -(function (global){ -/*! - * Platform.js - * Copyright 2014-2018 Benjamin Tan - * Copyright 2011-2013 John-David Dalton - * Available under MIT license - */ -;(function() { - 'use strict'; - - /** Used to determine if values are of the language type `Object`. */ - var objectTypes = { - 'function': true, - 'object': true - }; - - /** Used as a reference to the global object. */ - var root = (objectTypes[typeof window] && window) || this; - - /** Backup possible global object. */ - var oldRoot = root; - - /** Detect free variable `exports`. */ - var freeExports = objectTypes[typeof exports] && exports; - - /** Detect free variable `module`. */ - var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; - - /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ - var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; - if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { - root = freeGlobal; - } - - /** - * Used as the maximum length of an array-like object. - * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) - * for more details. - */ - var maxSafeInteger = Math.pow(2, 53) - 1; - - /** Regular expression to detect Opera. */ - var reOpera = /\bOpera/; - - /** Possible global object. */ - var thisBinding = this; - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** Used to check for own properties of an object. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Used to resolve the internal `[[Class]]` of values. */ - var toString = objectProto.toString; - - /*--------------------------------------------------------------------------*/ - - /** - * Capitalizes a string value. - * - * @private - * @param {string} string The string to capitalize. - * @returns {string} The capitalized string. - */ - function capitalize(string) { - string = String(string); - return string.charAt(0).toUpperCase() + string.slice(1); - } - - /** - * A utility function to clean up the OS name. - * - * @private - * @param {string} os The OS name to clean up. - * @param {string} [pattern] A `RegExp` pattern matching the OS name. - * @param {string} [label] A label for the OS. - */ - function cleanupOS(os, pattern, label) { - // Platform tokens are defined at: - // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - var data = { - '10.0': '10', - '6.4': '10 Technical Preview', - '6.3': '8.1', - '6.2': '8', - '6.1': 'Server 2008 R2 / 7', - '6.0': 'Server 2008 / Vista', - '5.2': 'Server 2003 / XP 64-bit', - '5.1': 'XP', - '5.01': '2000 SP1', - '5.0': '2000', - '4.0': 'NT', - '4.90': 'ME' - }; - // Detect Windows version from platform tokens. - if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && - (data = data[/[\d.]+$/.exec(os)])) { - os = 'Windows ' + data; - } - // Correct character case and cleanup string. - os = String(os); - - if (pattern && label) { - os = os.replace(RegExp(pattern, 'i'), label); - } - - os = format( - os.replace(/ ce$/i, ' CE') - .replace(/\bhpw/i, 'web') - .replace(/\bMacintosh\b/, 'Mac OS') - .replace(/_PowerPC\b/i, ' OS') - .replace(/\b(OS X) [^ \d]+/i, '$1') - .replace(/\bMac (OS X)\b/, '$1') - .replace(/\/(\d)/, ' $1') - .replace(/_/g, '.') - .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') - .replace(/\bx86\.64\b/gi, 'x86_64') - .replace(/\b(Windows Phone) OS\b/, '$1') - .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') - .split(' on ')[0] - ); - - return os; - } - - /** - * An iteration utility for arrays and objects. - * - * @private - * @param {Array|Object} object The object to iterate over. - * @param {Function} callback The function called per iteration. - */ - function each(object, callback) { - var index = -1, - length = object ? object.length : 0; - - if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { - while (++index < length) { - callback(object[index], index, object); - } - } else { - forOwn(object, callback); - } - } - - /** - * Trim and conditionally capitalize string values. - * - * @private - * @param {string} string The string to format. - * @returns {string} The formatted string. - */ - function format(string) { - string = trim(string); - return /^(?:webOS|i(?:OS|P))/.test(string) - ? string - : capitalize(string); - } - - /** - * Iterates over an object's own properties, executing the `callback` for each. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} callback The function executed per own property. - */ - function forOwn(object, callback) { - for (var key in object) { - if (hasOwnProperty.call(object, key)) { - callback(object[key], key, object); - } - } - } - - /** - * Gets the internal `[[Class]]` of a value. - * - * @private - * @param {*} value The value. - * @returns {string} The `[[Class]]`. - */ - function getClassOf(value) { - return value == null - ? capitalize(value) - : toString.call(value).slice(8, -1); - } - - /** - * Host objects can return type values that are different from their actual - * data type. The objects we are concerned with usually return non-primitive - * types of "object", "function", or "unknown". - * - * @private - * @param {*} object The owner of the property. - * @param {string} property The property to check. - * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. - */ - function isHostType(object, property) { - var type = object != null ? typeof object[property] : 'number'; - return !/^(?:boolean|number|string|undefined)$/.test(type) && - (type == 'object' ? !!object[property] : true); - } - - /** - * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. - * - * @private - * @param {string} string The string to qualify. - * @returns {string} The qualified string. - */ - function qualify(string) { - return String(string).replace(/([ -])(?!$)/g, '$1?'); - } - - /** - * A bare-bones `Array#reduce` like utility function. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {*} The accumulated result. - */ - function reduce(array, callback) { - var accumulator = null; - each(array, function(value, index) { - accumulator = callback(accumulator, value, index, array); - }); - return accumulator; - } - - /** - * Removes leading and trailing whitespace from a string. - * - * @private - * @param {string} string The string to trim. - * @returns {string} The trimmed string. - */ - function trim(string) { - return String(string).replace(/^ +| +$/g, ''); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Creates a new platform object. - * - * @memberOf platform - * @param {Object|string} [ua=navigator.userAgent] The user agent string or - * context object. - * @returns {Object} A platform object. - */ - function parse(ua) { - - /** The environment context object. */ - var context = root; - - /** Used to flag when a custom context is provided. */ - var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; - - // Juggle arguments. - if (isCustomContext) { - context = ua; - ua = null; - } - - /** Browser navigator object. */ - var nav = context.navigator || {}; - - /** Browser user agent string. */ - var userAgent = nav.userAgent || ''; - - ua || (ua = userAgent); - - /** Used to flag when `thisBinding` is the [ModuleScope]. */ - var isModuleScope = isCustomContext || thisBinding == oldRoot; - - /** Used to detect if browser is like Chrome. */ - var likeChrome = isCustomContext - ? !!nav.likeChrome - : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); - - /** Internal `[[Class]]` value shortcuts. */ - var objectClass = 'Object', - airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', - enviroClass = isCustomContext ? objectClass : 'Environment', - javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), - phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; - - /** Detect Java environments. */ - var java = /\bJava/.test(javaClass) && context.java; - - /** Detect Rhino. */ - var rhino = java && getClassOf(context.environment) == enviroClass; - - /** A character to represent alpha. */ - var alpha = java ? 'a' : '\u03b1'; - - /** A character to represent beta. */ - var beta = java ? 'b' : '\u03b2'; - - /** Browser document object. */ - var doc = context.document || {}; - - /** - * Detect Opera browser (Presto-based). - * http://www.howtocreate.co.uk/operaStuff/operaObject.html - * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini - */ - var opera = context.operamini || context.opera; - - /** Opera `[[Class]]`. */ - var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) - ? operaClass - : (opera = null); - - /*------------------------------------------------------------------------*/ - - /** Temporary variable used over the script's lifetime. */ - var data; - - /** The CPU architecture. */ - var arch = ua; - - /** Platform description array. */ - var description = []; - - /** Platform alpha/beta indicator. */ - var prerelease = null; - - /** A flag to indicate that environment features should be used to resolve the platform. */ - var useFeatures = ua == userAgent; - - /** The browser/environment version. */ - var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); - - /** A flag to indicate if the OS ends with "/ Version" */ - var isSpecialCasedOS; - - /* Detectable layout engines (order is important). */ - var layout = getLayout([ - { 'label': 'EdgeHTML', 'pattern': 'Edge' }, - 'Trident', - { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, - 'iCab', - 'Presto', - 'NetFront', - 'Tasman', - 'KHTML', - 'Gecko' - ]); - - /* Detectable browser names (order is important). */ - var name = getName([ - 'Adobe AIR', - 'Arora', - 'Avant Browser', - 'Breach', - 'Camino', - 'Electron', - 'Epiphany', - 'Fennec', - 'Flock', - 'Galeon', - 'GreenBrowser', - 'iCab', - 'Iceweasel', - 'K-Meleon', - 'Konqueror', - 'Lunascape', - 'Maxthon', - { 'label': 'Microsoft Edge', 'pattern': 'Edge' }, - 'Midori', - 'Nook Browser', - 'PaleMoon', - 'PhantomJS', - 'Raven', - 'Rekonq', - 'RockMelt', - { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' }, - 'SeaMonkey', - { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Sleipnir', - 'SlimBrowser', - { 'label': 'SRWare Iron', 'pattern': 'Iron' }, - 'Sunrise', - 'Swiftfox', - 'Waterfox', - 'WebPositive', - 'Opera Mini', - { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, - 'Opera', - { 'label': 'Opera', 'pattern': 'OPR' }, - 'Chrome', - { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, - { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, - { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' }, - { 'label': 'IE', 'pattern': 'IEMobile' }, - { 'label': 'IE', 'pattern': 'MSIE' }, - 'Safari' - ]); - - /* Detectable products (order is important). */ - var product = getProduct([ - { 'label': 'BlackBerry', 'pattern': 'BB10' }, - 'BlackBerry', - { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, - { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, - { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, - { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, - { 'label': 'Galaxy S5', 'pattern': 'SM-G900' }, - { 'label': 'Galaxy S6', 'pattern': 'SM-G920' }, - { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' }, - { 'label': 'Galaxy S7', 'pattern': 'SM-G930' }, - { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' }, - 'Google TV', - 'Lumia', - 'iPad', - 'iPod', - 'iPhone', - 'Kindle', - { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Nexus', - 'Nook', - 'PlayBook', - 'PlayStation Vita', - 'PlayStation', - 'TouchPad', - 'Transformer', - { 'label': 'Wii U', 'pattern': 'WiiU' }, - 'Wii', - 'Xbox One', - { 'label': 'Xbox 360', 'pattern': 'Xbox' }, - 'Xoom' - ]); - - /* Detectable manufacturers. */ - var manufacturer = getManufacturer({ - 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, - 'Archos': {}, - 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, - 'Asus': { 'Transformer': 1 }, - 'Barnes & Noble': { 'Nook': 1 }, - 'BlackBerry': { 'PlayBook': 1 }, - 'Google': { 'Google TV': 1, 'Nexus': 1 }, - 'HP': { 'TouchPad': 1 }, - 'HTC': {}, - 'LG': {}, - 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, - 'Motorola': { 'Xoom': 1 }, - 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, - 'Nokia': { 'Lumia': 1 }, - 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, - 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 } - }); - - /* Detectable operating systems (order is important). */ - var os = getOS([ - 'Windows Phone', - 'Android', - 'CentOS', - { 'label': 'Chrome OS', 'pattern': 'CrOS' }, - 'Debian', - 'Fedora', - 'FreeBSD', - 'Gentoo', - 'Haiku', - 'Kubuntu', - 'Linux Mint', - 'OpenBSD', - 'Red Hat', - 'SuSE', - 'Ubuntu', - 'Xubuntu', - 'Cygwin', - 'Symbian OS', - 'hpwOS', - 'webOS ', - 'webOS', - 'Tablet OS', - 'Tizen', - 'Linux', - 'Mac OS X', - 'Macintosh', - 'Mac', - 'Windows 98;', - 'Windows ' - ]); - - /*------------------------------------------------------------------------*/ - - /** - * Picks the layout engine from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected layout engine. - */ - function getLayout(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the manufacturer from an array of guesses. - * - * @private - * @param {Array} guesses An object of guesses. - * @returns {null|string} The detected manufacturer. - */ - function getManufacturer(guesses) { - return reduce(guesses, function(result, value, key) { - // Lookup the manufacturer by product or scan the UA for the manufacturer. - return result || ( - value[product] || - value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || - RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) - ) && key; - }); - } - - /** - * Picks the browser name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected browser name. - */ - function getName(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the OS name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected OS name. - */ - function getOS(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) - )) { - result = cleanupOS(result, pattern, guess.label || guess); - } - return result; - }); - } - - /** - * Picks the product name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected product name. - */ - function getProduct(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || - RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) || - RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) - )) { - // Split by forward slash and append product version if needed. - if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { - result[0] += ' ' + result[1]; - } - // Correct character case and cleanup string. - guess = guess.label || guess; - result = format(result[0] - .replace(RegExp(pattern, 'i'), guess) - .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') - .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); - } - return result; - }); - } - - /** - * Resolves the version using an array of UA patterns. - * - * @private - * @param {Array} patterns An array of UA patterns. - * @returns {null|string} The detected version. - */ - function getVersion(patterns) { - return reduce(patterns, function(result, pattern) { - return result || (RegExp(pattern + - '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; - }); - } - - /** - * Returns `platform.description` when the platform object is coerced to a string. - * - * @name toString - * @memberOf platform - * @returns {string} Returns `platform.description` if available, else an empty string. - */ - function toStringPlatform() { - return this.description || ''; - } - - /*------------------------------------------------------------------------*/ - - // Convert layout to an array so we can add extra details. - layout && (layout = [layout]); - - // Detect product names that contain their manufacturer's name. - if (manufacturer && !product) { - product = getProduct([manufacturer]); - } - // Clean up Google TV. - if ((data = /\bGoogle TV\b/.exec(product))) { - product = data[0]; - } - // Detect simulators. - if (/\bSimulator\b/i.test(ua)) { - product = (product ? product + ' ' : '') + 'Simulator'; - } - // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. - if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { - description.push('running in Turbo/Uncompressed mode'); - } - // Detect IE Mobile 11. - if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) { - data = parse(ua.replace(/like iPhone OS/, '')); - manufacturer = data.manufacturer; - product = data.product; - } - // Detect iOS. - else if (/^iP/.test(product)) { - name || (name = 'Safari'); - os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) - ? ' ' + data[1].replace(/_/g, '.') - : ''); - } - // Detect Kubuntu. - else if (name == 'Konqueror' && !/buntu/i.test(os)) { - os = 'Kubuntu'; - } - // Detect Android browsers. - else if ((manufacturer && manufacturer != 'Google' && - ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) || - (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) { - name = 'Android Browser'; - os = /\bAndroid\b/.test(os) ? os : 'Android'; - } - // Detect Silk desktop/accelerated modes. - else if (name == 'Silk') { - if (!/\bMobi/i.test(ua)) { - os = 'Android'; - description.unshift('desktop mode'); - } - if (/Accelerated *= *true/i.test(ua)) { - description.unshift('accelerated'); - } - } - // Detect PaleMoon identifying as Firefox. - else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { - description.push('identifying as Firefox ' + data[1]); - } - // Detect Firefox OS and products running Firefox. - else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { - os || (os = 'Firefox OS'); - product || (product = data[1]); - } - // Detect false positives for Firefox/Safari. - else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { - // Escape the `/` for Firefox 1. - if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { - // Clear name of false positives. - name = null; - } - // Reassign a generic name. - if ((data = product || manufacturer || os) && - (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { - name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; - } - } - // Add Chrome version to description for Electron. - else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) { - description.push('Chromium ' + data); - } - // Detect non-Opera (Presto-based) versions (order is important). - if (!version) { - version = getVersion([ - '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))', - 'Version', - qualify(name), - '(?:Firefox|Minefield|NetFront)' - ]); - } - // Detect stubborn layout engines. - if ((data = - layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || - /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || - /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || - !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || - layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' - )) { - layout = [data]; - } - // Detect Windows Phone 7 desktop mode. - if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { - name += ' Mobile'; - os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); - description.unshift('desktop mode'); - } - // Detect Windows Phone 8.x desktop mode. - else if (/\bWPDesktop\b/i.test(ua)) { - name = 'IE Mobile'; - os = 'Windows Phone 8.x'; - description.unshift('desktop mode'); - version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); - } - // Detect IE 11 identifying as other browsers. - else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { - if (name) { - description.push('identifying as ' + name + (version ? ' ' + version : '')); - } - name = 'IE'; - version = data[1]; - } - // Leverage environment features. - if (useFeatures) { - // Detect server-side environments. - // Rhino has a global function while others have a global object. - if (isHostType(context, 'global')) { - if (java) { - data = java.lang.System; - arch = data.getProperty('os.arch'); - os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); - } - if (rhino) { - try { - version = context.require('ringo/engine').version.join('.'); - name = 'RingoJS'; - } catch(e) { - if ((data = context.system) && data.global.system == context.system) { - name = 'Narwhal'; - os || (os = data[0].os || null); - } - } - if (!name) { - name = 'Rhino'; - } - } - else if ( - typeof context.process == 'object' && !context.process.browser && - (data = context.process) - ) { - if (typeof data.versions == 'object') { - if (typeof data.versions.electron == 'string') { - description.push('Node ' + data.versions.node); - name = 'Electron'; - version = data.versions.electron; - } else if (typeof data.versions.nw == 'string') { - description.push('Chromium ' + version, 'Node ' + data.versions.node); - name = 'NW.js'; - version = data.versions.nw; - } - } - if (!name) { - name = 'Node.js'; - arch = data.arch; - os = data.platform; - version = /[\d.]+/.exec(data.version); - version = version ? version[0] : null; - } - } - } - // Detect Adobe AIR. - else if (getClassOf((data = context.runtime)) == airRuntimeClass) { - name = 'Adobe AIR'; - os = data.flash.system.Capabilities.os; - } - // Detect PhantomJS. - else if (getClassOf((data = context.phantom)) == phantomClass) { - name = 'PhantomJS'; - version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); - } - // Detect IE compatibility modes. - else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { - // We're in compatibility mode when the Trident version + 4 doesn't - // equal the document mode. - version = [version, doc.documentMode]; - if ((data = +data[1] + 4) != version[1]) { - description.push('IE ' + version[1] + ' mode'); - layout && (layout[1] = ''); - version[1] = data; - } - version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; - } - // Detect IE 11 masking as other browsers. - else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) { - description.push('masking as ' + name + ' ' + version); - name = 'IE'; - version = '11.0'; - layout = ['Trident']; - os = 'Windows'; - } - os = os && format(os); - } - // Detect prerelease phases. - if (version && (data = - /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || - /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || - /\bMinefield\b/i.test(ua) && 'a' - )) { - prerelease = /b/i.test(data) ? 'beta' : 'alpha'; - version = version.replace(RegExp(data + '\\+?$'), '') + - (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); - } - // Detect Firefox Mobile. - if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) { - name = 'Firefox Mobile'; - } - // Obscure Maxthon's unreliable version. - else if (name == 'Maxthon' && version) { - version = version.replace(/\.[\d.]+/, '.x'); - } - // Detect Xbox 360 and Xbox One. - else if (/\bXbox\b/i.test(product)) { - if (product == 'Xbox 360') { - os = null; - } - if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { - description.unshift('mobile mode'); - } - } - // Add mobile postfix. - else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && - (os == 'Windows CE' || /Mobi/i.test(ua))) { - name += ' Mobile'; - } - // Detect IE platform preview. - else if (name == 'IE' && useFeatures) { - try { - if (context.external === null) { - description.unshift('platform preview'); - } - } catch(e) { - description.unshift('embedded'); - } - } - // Detect BlackBerry OS version. - // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp - else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = - (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || - version - )) { - data = [data, /BB10/.test(ua)]; - os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; - version = null; - } - // Detect Opera identifying/masking itself as another browser. - // http://www.opera.com/support/kb/view/843/ - else if (this != forOwn && product != 'Wii' && ( - (useFeatures && opera) || - (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || - (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || - (name == 'IE' && ( - (os && !/^Win/.test(os) && version > 5.5) || - /\bWindows XP\b/.test(os) && version > 8 || - version == 8 && !/\bTrident\b/.test(ua) - )) - ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { - // When "identifying", the UA contains both Opera and the other browser's name. - data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); - if (reOpera.test(name)) { - if (/\bIE\b/.test(data) && os == 'Mac OS') { - os = null; - } - data = 'identify' + data; - } - // When "masking", the UA contains only the other browser's name. - else { - data = 'mask' + data; - if (operaClass) { - name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); - } else { - name = 'Opera'; - } - if (/\bIE\b/.test(data)) { - os = null; - } - if (!useFeatures) { - version = null; - } - } - layout = ['Presto']; - description.push(data); - } - // Detect WebKit Nightly and approximate Chrome/Safari versions. - if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - // Correct build number for numeric comparison. - // (e.g. "532.5" becomes "532.05") - data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; - // Nightly builds are postfixed with a "+". - if (name == 'Safari' && data[1].slice(-1) == '+') { - name = 'WebKit Nightly'; - prerelease = 'alpha'; - version = data[1].slice(0, -1); - } - // Clear incorrect browser versions. - else if (version == data[1] || - version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - version = null; - } - // Use the full Chrome version when available. - data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]; - // Detect Blink layout engine. - if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { - layout = ['Blink']; - } - // Detect JavaScriptCore. - // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi - if (!useFeatures || (!likeChrome && !data[1])) { - layout && (layout[1] = 'like Safari'); - data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8'); - } else { - layout && (layout[1] = 'like Chrome'); - data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); - } - // Add the postfix of ".x" or "+" for approximate versions. - layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); - // Obscure version for some Safari 1-2 releases. - if (name == 'Safari' && (!version || parseInt(version) > 45)) { - version = data; - } - } - // Detect Opera desktop modes. - if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { - name += ' '; - description.unshift('desktop mode'); - if (data == 'zvav') { - name += 'Mini'; - version = null; - } else { - name += 'Mobile'; - } - os = os.replace(RegExp(' *' + data + '$'), ''); - } - // Detect Chrome desktop mode. - else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { - description.unshift('desktop mode'); - name = 'Chrome Mobile'; - version = null; - - if (/\bOS X\b/.test(os)) { - manufacturer = 'Apple'; - os = 'iOS 4.3+'; - } else { - os = null; - } - } - // Strip incorrect OS versions. - if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && - ua.indexOf('/' + data + '-') > -1) { - os = trim(os.replace(data, '')); - } - // Add layout engine. - if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( - /Browser|Lunascape|Maxthon/.test(name) || - name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || - /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) { - // Don't add layout details to description if they are falsey. - (data = layout[layout.length - 1]) && description.push(data); - } - // Combine contextual information. - if (description.length) { - description = ['(' + description.join('; ') + ')']; - } - // Append manufacturer to description. - if (manufacturer && product && product.indexOf(manufacturer) < 0) { - description.push('on ' + manufacturer); - } - // Append product to description. - if (product) { - description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); - } - // Parse the OS into an object. - if (os) { - data = / ([\d.+]+)$/.exec(os); - isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; - os = { - 'architecture': 32, - 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, - 'version': data ? data[1] : null, - 'toString': function() { - var version = this.version; - return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); - } - }; - } - // Add browser/OS architecture. - if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { - if (os) { - os.architecture = 64; - os.family = os.family.replace(RegExp(' *' + data), ''); - } - if ( - name && (/\bWOW64\b/i.test(ua) || - (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) - ) { - description.unshift('32-bit'); - } - } - // Chrome 39 and above on OS X is always 64-bit. - else if ( - os && /^OS X/.test(os.family) && - name == 'Chrome' && parseFloat(version) >= 39 - ) { - os.architecture = 64; - } - - ua || (ua = null); - - /*------------------------------------------------------------------------*/ - - /** - * The platform object. - * - * @name platform - * @type Object - */ - var platform = {}; - - /** - * The platform description. - * - * @memberOf platform - * @type string|null - */ - platform.description = ua; - - /** - * The name of the browser's layout engine. - * - * The list of common layout engines include: - * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit" - * - * @memberOf platform - * @type string|null - */ - platform.layout = layout && layout[0]; - - /** - * The name of the product's manufacturer. - * - * The list of manufacturers include: - * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry", - * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo", - * "Nokia", "Samsung" and "Sony" - * - * @memberOf platform - * @type string|null - */ - platform.manufacturer = manufacturer; - - /** - * The name of the browser/environment. - * - * The list of common browser names include: - * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE", - * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk", - * "Opera Mini" and "Opera" - * - * Mobile versions of some browsers have "Mobile" appended to their name: - * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile" - * - * @memberOf platform - * @type string|null - */ - platform.name = name; - - /** - * The alpha/beta release indicator. - * - * @memberOf platform - * @type string|null - */ - platform.prerelease = prerelease; - - /** - * The name of the product hosting the browser. - * - * The list of common products include: - * - * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle", - * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer" - * - * @memberOf platform - * @type string|null - */ - platform.product = product; - - /** - * The browser's user agent string. - * - * @memberOf platform - * @type string|null - */ - platform.ua = ua; - - /** - * The browser/environment version. - * - * @memberOf platform - * @type string|null - */ - platform.version = name && version; - - /** - * The name of the operating system. - * - * @memberOf platform - * @type Object - */ - platform.os = os || { - - /** - * The CPU architecture the OS is built for. - * - * @memberOf platform.os - * @type number|null - */ - 'architecture': null, - - /** - * The family of the OS. - * - * Common values include: - * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", - * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", - * "Android", "iOS" and "Windows Phone" - * - * @memberOf platform.os - * @type string|null - */ - 'family': null, - - /** - * The version of the OS. - * - * @memberOf platform.os - * @type string|null - */ - 'version': null, - - /** - * Returns the OS string. - * - * @memberOf platform.os - * @returns {string} The OS string. - */ - 'toString': function() { return 'null'; } - }; - - platform.parse = parse; - platform.toString = toStringPlatform; - - if (platform.version) { - description.unshift(version); - } - if (platform.name) { - description.unshift(name); - } - if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { - description.push(product ? '(' + os + ')' : 'on ' + os); - } - if (description.length) { - platform.description = description.join(' '); - } - return platform; - } - - /*--------------------------------------------------------------------------*/ - - // Export platform. - var platform = parse(); - - // Some AMD build optimizers, like r.js, check for condition patterns like the following: - if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose platform on the global object to prevent errors when platform is - // loaded by a script tag in the presence of an AMD loader. - // See http://requirejs.org/docs/errors.html#mismatch for more details. - root.platform = platform; - - // Define as an anonymous module so platform can be aliased through path mapping. - define(function() { - return platform; - }); - } - // Check for `exports` after `define` in case a build optimizer adds an `exports` object. - else if (freeExports && freeModule) { - // Export for CommonJS support. - forOwn(platform, function(value, key) { - freeExports[key] = value; - }); - } - else { - // Export to the global object. - root.platform = platform; - } -}.call(this)); - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],10:[function(require,module,exports){ -var grammar = module.exports = { - v: [{ - name: 'version', - reg: /^(\d*)$/ - }], - o: [{ //o=- 20518 0 IN IP4 203.0.113.1 - // NB: sessionId will be a String in most cases because it is huge - name: 'origin', - reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, - names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], - format: "%s %s %d %s IP%d %s" - }], - // default parsing of these only (though some of these feel outdated) - s: [{ name: 'name' }], - i: [{ name: 'description' }], - u: [{ name: 'uri' }], - e: [{ name: 'email' }], - p: [{ name: 'phone' }], - z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly.. - r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly - //k: [{}], // outdated thing ignored - t: [{ //t=0 0 - name: 'timing', - reg: /^(\d*) (\d*)/, - names: ['start', 'stop'], - format: "%d %d" - }], - c: [{ //c=IN IP4 10.47.197.26 - name: 'connection', - reg: /^IN IP(\d) (\S*)/, - names: ['version', 'ip'], - format: "IN IP%d %s" - }], - b: [{ //b=AS:4000 - push: 'bandwidth', - reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, - names: ['type', 'limit'], - format: "%s:%s" - }], - m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31 - // NB: special - pushes to session - // TODO: rtp/fmtp should be filtered by the payloads found here? - reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/, - names: ['type', 'port', 'protocol', 'payloads'], - format: "%s %d %s %s" - }], - a: [ - { //a=rtpmap:110 opus/48000/2 - push: 'rtp', - reg: /^rtpmap:(\d*) ([\w\-]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, - names: ['payload', 'codec', 'rate', 'encoding'], - format: function (o) { - return (o.encoding) ? - "rtpmap:%d %s/%s/%s": - o.rate ? - "rtpmap:%d %s/%s": - "rtpmap:%d %s"; - } - }, - { - //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 - //a=fmtp:111 minptime=10; useinbandfec=1 - push: 'fmtp', - reg: /^fmtp:(\d*) ([\S| ]*)/, - names: ['payload', 'config'], - format: "fmtp:%d %s" - }, - { //a=control:streamid=0 - name: 'control', - reg: /^control:(.*)/, - format: "control:%s" - }, - { //a=rtcp:65179 IN IP4 193.84.77.194 - name: 'rtcp', - reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, - names: ['port', 'netType', 'ipVer', 'address'], - format: function (o) { - return (o.address != null) ? - "rtcp:%d %s IP%d %s": - "rtcp:%d"; - } - }, - { //a=rtcp-fb:98 trr-int 100 - push: 'rtcpFbTrrInt', - reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, - names: ['payload', 'value'], - format: "rtcp-fb:%d trr-int %d" - }, - { //a=rtcp-fb:98 nack rpsi - push: 'rtcpFb', - reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, - names: ['payload', 'type', 'subtype'], - format: function (o) { - return (o.subtype != null) ? - "rtcp-fb:%s %s %s": - "rtcp-fb:%s %s"; - } - }, - { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset - //a=extmap:1/recvonly URI-gps-string - push: 'ext', - reg: /^extmap:([\w_\/]*) (\S*)(?: (\S*))?/, - names: ['value', 'uri', 'config'], // value may include "/direction" suffix - format: function (o) { - return (o.config != null) ? - "extmap:%s %s %s": - "extmap:%s %s"; - } - }, - { - //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 - push: 'crypto', - reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, - names: ['id', 'suite', 'config', 'sessionConfig'], - format: function (o) { - return (o.sessionConfig != null) ? - "crypto:%d %s %s %s": - "crypto:%d %s %s"; - } - }, - { //a=setup:actpass - name: 'setup', - reg: /^setup:(\w*)/, - format: "setup:%s" - }, - { //a=mid:1 - name: 'mid', - reg: /^mid:([^\s]*)/, - format: "mid:%s" - }, - { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a - name: 'msid', - reg: /^msid:(.*)/, - format: "msid:%s" - }, - { //a=ptime:20 - name: 'ptime', - reg: /^ptime:(\d*)/, - format: "ptime:%d" - }, - { //a=maxptime:60 - name: 'maxptime', - reg: /^maxptime:(\d*)/, - format: "maxptime:%d" - }, - { //a=sendrecv - name: 'direction', - reg: /^(sendrecv|recvonly|sendonly|inactive)/ - }, - { //a=ice-lite - name: 'icelite', - reg: /^(ice-lite)/ - }, - { //a=ice-ufrag:F7gI - name: 'iceUfrag', - reg: /^ice-ufrag:(\S*)/, - format: "ice-ufrag:%s" - }, - { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g - name: 'icePwd', - reg: /^ice-pwd:(\S*)/, - format: "ice-pwd:%s" - }, - { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 - name: 'fingerprint', - reg: /^fingerprint:(\S*) (\S*)/, - names: ['type', 'hash'], - format: "fingerprint:%s %s" - }, - { - //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host - //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 - //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 - //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 - //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 - push:'candidates', - reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?/, - names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation'], - format: function (o) { - var str = "candidate:%s %d %s %d %s %d typ %s"; - - str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v"; - - // NB: candidate has three optional chunks, so %void middles one if it's missing - str += (o.tcptype != null) ? " tcptype %s" : "%v"; - - if (o.generation != null) { - str += " generation %d"; - } - return str; - } - }, - { //a=end-of-candidates (keep after the candidates line for readability) - name: 'endOfCandidates', - reg: /^(end-of-candidates)/ - }, - { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... - name: 'remoteCandidates', - reg: /^remote-candidates:(.*)/, - format: "remote-candidates:%s" - }, - { //a=ice-options:google-ice - name: 'iceOptions', - reg: /^ice-options:(\S*)/, - format: "ice-options:%s" - }, - { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 - push: "ssrcs", - reg: /^ssrc:(\d*) ([\w_]*):(.*)/, - names: ['id', 'attribute', 'value'], - format: "ssrc:%d %s:%s" - }, - { //a=ssrc-group:FEC 1 2 - push: "ssrcGroups", - reg: /^ssrc-group:(\w*) (.*)/, - names: ['semantics', 'ssrcs'], - format: "ssrc-group:%s %s" - }, - { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV - name: "msidSemantic", - reg: /^msid-semantic:\s?(\w*) (\S*)/, - names: ['semantic', 'token'], - format: "msid-semantic: %s %s" // space after ":" is not accidental - }, - { //a=group:BUNDLE audio video - push: 'groups', - reg: /^group:(\w*) (.*)/, - names: ['type', 'mids'], - format: "group:%s %s" - }, - { //a=rtcp-mux - name: 'rtcpMux', - reg: /^(rtcp-mux)/ - }, - { //a=rtcp-rsize - name: 'rtcpRsize', - reg: /^(rtcp-rsize)/ - }, - { // any a= that we don't understand is kepts verbatim on media.invalid - push: 'invalid', - names: ["value"] - } - ] -}; - -// set sensible defaults to avoid polluting the grammar with boring details -Object.keys(grammar).forEach(function (key) { - var objs = grammar[key]; - objs.forEach(function (obj) { - if (!obj.reg) { - obj.reg = /(.*)/; - } - if (!obj.format) { - obj.format = "%s"; - } - }); -}); - -},{}],11:[function(require,module,exports){ -var parser = require('./parser'); -var writer = require('./writer'); - -exports.write = writer; -exports.parse = parser.parse; -exports.parseFmtpConfig = parser.parseFmtpConfig; -exports.parsePayloads = parser.parsePayloads; -exports.parseRemoteCandidates = parser.parseRemoteCandidates; - -},{"./parser":12,"./writer":13}],12:[function(require,module,exports){ -var toIntIfInt = function (v) { - return String(Number(v)) === v ? Number(v) : v; -}; - -var attachProperties = function (match, location, names, rawName) { - if (rawName && !names) { - location[rawName] = toIntIfInt(match[1]); - } - else { - for (var i = 0; i < names.length; i += 1) { - if (match[i+1] != null) { - location[names[i]] = toIntIfInt(match[i+1]); - } - } - } -}; - -var parseReg = function (obj, location, content) { - var needsBlank = obj.name && obj.names; - if (obj.push && !location[obj.push]) { - location[obj.push] = []; - } - else if (needsBlank && !location[obj.name]) { - location[obj.name] = {}; - } - var keyLocation = obj.push ? - {} : // blank object that will be pushed - needsBlank ? location[obj.name] : location; // otherwise, named location or root - - attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name); - - if (obj.push) { - location[obj.push].push(keyLocation); - } -}; - -var grammar = require('./grammar'); -var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/); - -exports.parse = function (sdp) { - var session = {} - , media = [] - , location = session; // points at where properties go under (one of the above) - - // parse lines we understand - sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) { - var type = l[0]; - var content = l.slice(2); - if (type === 'm') { - media.push({rtp: [], fmtp: []}); - location = media[media.length-1]; // point at latest media line - } - - for (var j = 0; j < (grammar[type] || []).length; j += 1) { - var obj = grammar[type][j]; - if (obj.reg.test(content)) { - return parseReg(obj, location, content); - } - } - }); - - session.media = media; // link it up - return session; -}; - -var fmtpReducer = function (acc, expr) { - var s = expr.split('='); - if (s.length === 2) { - acc[s[0]] = toIntIfInt(s[1]); - } - return acc; -}; - -exports.parseFmtpConfig = function (str) { - return str.split(/\;\s?/).reduce(fmtpReducer, {}); -}; - -exports.parsePayloads = function (str) { - return str.split(' ').map(Number); -}; - -exports.parseRemoteCandidates = function (str) { - var candidates = []; - var parts = str.split(' ').map(toIntIfInt); - for (var i = 0; i < parts.length; i += 3) { - candidates.push({ - component: parts[i], - ip: parts[i + 1], - port: parts[i + 2] - }); - } - return candidates; -}; - -},{"./grammar":10}],13:[function(require,module,exports){ -var grammar = require('./grammar'); - -// customized util.format - discards excess arguments and can void middle ones -var formatRegExp = /%[sdv%]/g; -var format = function (formatStr) { - var i = 1; - var args = arguments; - var len = args.length; - return formatStr.replace(formatRegExp, function (x) { - if (i >= len) { - return x; // missing argument - } - var arg = args[i]; - i += 1; - switch (x) { - case '%%': - return '%'; - case '%s': - return String(arg); - case '%d': - return Number(arg); - case '%v': - return ''; - } - }); - // NB: we discard excess arguments - they are typically undefined from makeLine -}; - -var makeLine = function (type, obj, location) { - var str = obj.format instanceof Function ? - (obj.format(obj.push ? location : location[obj.name])) : - obj.format; - - var args = [type + '=' + str]; - if (obj.names) { - for (var i = 0; i < obj.names.length; i += 1) { - var n = obj.names[i]; - if (obj.name) { - args.push(location[obj.name][n]); - } - else { // for mLine and push attributes - args.push(location[obj.names[i]]); - } - } - } - else { - args.push(location[obj.name]); - } - return format.apply(null, args); -}; - -// RFC specified order -// TODO: extend this with all the rest -var defaultOuterOrder = [ - 'v', 'o', 's', 'i', - 'u', 'e', 'p', 'c', - 'b', 't', 'r', 'z', 'a' -]; -var defaultInnerOrder = ['i', 'c', 'b', 'a']; - - -module.exports = function (session, opts) { - opts = opts || {}; - // ensure certain properties exist - if (session.version == null) { - session.version = 0; // "v=0" must be there (only defined version atm) - } - if (session.name == null) { - session.name = " "; // "s= " must be there if no meaningful name set - } - session.media.forEach(function (mLine) { - if (mLine.payloads == null) { - mLine.payloads = ""; - } - }); - - var outerOrder = opts.outerOrder || defaultOuterOrder; - var innerOrder = opts.innerOrder || defaultInnerOrder; - var sdp = []; - - // loop through outerOrder for matching properties on session - outerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in session && session[obj.name] != null) { - sdp.push(makeLine(type, obj, session)); - } - else if (obj.push in session && session[obj.push] != null) { - session[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - - // then for each media line, follow the innerOrder - session.media.forEach(function (mLine) { - sdp.push(makeLine('m', grammar.m[0], mLine)); - - innerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in mLine && mLine[obj.name] != null) { - sdp.push(makeLine(type, obj, mLine)); - } - else if (obj.push in mLine && mLine[obj.push] != null) { - mLine[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - }); - - return sdp.join('\r\n') + '\r\n'; -}; - -},{"./grammar":10}],14:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -module.exports = function arrayEquals(array) { - // if the other array is a falsy value, return - if (!array) - return false; - - // compare lengths - can save a lot of time - if (this.length != array.length) - return false; - - for (var i = 0, l = this.length; i < l; i++) { - // Check if we have nested arrays - if (this[i] instanceof Array && array[i] instanceof Array) { - // recurse into the nested arrays - if (!arrayEquals.apply(this[i], [array[i]])) - return false; - } else if (this[i] != array[i]) { - // Warning - two different object instances will never be equal: - // {x:20} != {x:20} - return false; - } - } - return true; -}; - - -},{}],15:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -exports.Interop = require('./interop'); - -},{"./interop":16}],16:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* global RTCSessionDescription */ -/* global RTCIceCandidate */ -/* jshint -W097 */ -"use strict"; - -var transform = require('./transform'); -var arrayEquals = require('./array-equals'); - -function Interop() { - - /** - * This map holds the most recent Unified Plan offer/answer SDP that was - * converted to Plan B, with the SDP type ('offer' or 'answer') as keys and - * the SDP string as values. - * - * @type {{}} - */ - this.cache = { - mlB2UMap : {}, - mlU2BMap : {} - }; -} - -module.exports = Interop; - -/** - * Changes the candidate args to match with the related Unified Plan - */ -Interop.prototype.candidateToUnifiedPlan = function(candidate) { - var cand = new RTCIceCandidate(candidate); - - cand.sdpMLineIndex = this.cache.mlB2UMap[cand.sdpMLineIndex]; - /* TODO: change sdpMid to (audio|video)-SSRC */ - - return cand; -}; - -/** - * Changes the candidate args to match with the related Plan B - */ -Interop.prototype.candidateToPlanB = function(candidate) { - var cand = new RTCIceCandidate(candidate); - - if (cand.sdpMid.indexOf('audio') === 0) { - cand.sdpMid = 'audio'; - } else if (cand.sdpMid.indexOf('video') === 0) { - cand.sdpMid = 'video'; - } else { - throw new Error('candidate with ' + cand.sdpMid + ' not allowed'); - } - - cand.sdpMLineIndex = this.cache.mlU2BMap[cand.sdpMLineIndex]; - - return cand; -}; - -/** - * Returns the index of the first m-line with the given media type and with a - * direction which allows sending, in the last Unified Plan description with - * type "answer" converted to Plan B. Returns {null} if there is no saved - * answer, or if none of its m-lines with the given type allow sending. - * @param type the media type ("audio" or "video"). - * @returns {*} - */ -Interop.prototype.getFirstSendingIndexFromAnswer = function(type) { - if (!this.cache.answer) { - return null; - } - - var session = transform.parse(this.cache.answer); - if (session && session.media && Array.isArray(session.media)){ - for (var i = 0; i < session.media.length; i++) { - if (session.media[i].type == type && - (!session.media[i].direction /* default to sendrecv */ || - session.media[i].direction === 'sendrecv' || - session.media[i].direction === 'sendonly')){ - return i; - } - } - } - - return null; -}; - -/** - * This method transforms a Unified Plan SDP to an equivalent Plan B SDP. A - * PeerConnection wrapper transforms the SDP to Plan B before passing it to the - * application. - * - * @param desc - * @returns {*} - */ -Interop.prototype.toPlanB = function(desc) { - var self = this; - //#region Preliminary input validation. - - if (typeof desc !== 'object' || desc === null || - typeof desc.sdp !== 'string') { - console.warn('An empty description was passed as an argument.'); - return desc; - } - - // Objectify the SDP for easier manipulation. - var session = transform.parse(desc.sdp); - - // If the SDP contains no media, there's nothing to transform. - if (typeof session.media === 'undefined' || - !Array.isArray(session.media) || session.media.length === 0) { - console.warn('The description has no media.'); - return desc; - } - - // Try some heuristics to "make sure" this is a Unified Plan SDP. Plan B - // SDP has a video, an audio and a data "channel" at most. - if (session.media.length <= 3 && session.media.every(function(m) { - return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; - })) { - console.warn('This description does not look like Unified Plan.'); - return desc; - } - - //#endregion - - // HACK https://bugzilla.mozilla.org/show_bug.cgi?id=1113443 - var sdp = desc.sdp; - var rewrite = false; - for (var i = 0; i < session.media.length; i++) { - var uLine = session.media[i]; - uLine.rtp.forEach(function(rtp) { - if (rtp.codec === 'NULL') - { - rewrite = true; - var offer = transform.parse(self.cache.offer); - rtp.codec = offer.media[i].rtp[0].codec; - } - }); - } - if (rewrite) { - sdp = transform.write(session); - } - - // Unified Plan SDP is our "precious". Cache it for later use in the Plan B - // -> Unified Plan transformation. - this.cache[desc.type] = sdp; - - //#region Convert from Unified Plan to Plan B. - - // We rebuild the session.media array. - var media = session.media; - session.media = []; - - // Associative array that maps channel types to channel objects for fast - // access to channel objects by their type, e.g. type2bl['audio']->channel - // obj. - var type2bl = {}; - - // Used to build the group:BUNDLE value after the channels construction - // loop. - var types = []; - - media.forEach(function(uLine) { - // rtcp-mux is required in the Plan B SDP. - if ((typeof uLine.rtcpMux !== 'string' || - uLine.rtcpMux !== 'rtcp-mux') && - uLine.direction !== 'inactive') { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'without the rtcp-mux attribute were found.'); - } - - // If we don't have a channel for this uLine.type OR the selected is - // inactive, then select this uLine as the channel basis. - if (typeof type2bl[uLine.type] === 'undefined' || - type2bl[uLine.type].direction === 'inactive') { - type2bl[uLine.type] = uLine; - } - - if (uLine.protocol != type2bl[uLine.type].protocol) { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'have different protocols and this library does not have ' + - 'support for that'); - } - - if (uLine.payloads != type2bl[uLine.type].payloads) { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'have different payloads and this library does not have ' + - 'support for that'); - } - - }); - - // Implode the Unified Plan m-lines/tracks into Plan B channels. - media.forEach(function(uLine) { - if (uLine.type === 'application') { - session.media.push(uLine); - types.push(uLine.mid); - return; - } - - // Add sources to the channel and handle a=msid. - if (typeof uLine.sources === 'object') { - Object.keys(uLine.sources).forEach(function(ssrc) { - if (typeof type2bl[uLine.type].sources !== 'object') - type2bl[uLine.type].sources = {}; - - // Assign the sources to the channel. - type2bl[uLine.type].sources[ssrc] = - uLine.sources[ssrc]; - - if (typeof uLine.msid !== 'undefined') { - // In Plan B the msid is an SSRC attribute. Also, we don't - // care about the obsolete label and mslabel attributes. - // - // Note that it is not guaranteed that the uLine will - // have an msid. recvonly channels in particular don't have - // one. - type2bl[uLine.type].sources[ssrc].msid = - uLine.msid; - } - // NOTE ssrcs in ssrc groups will share msids, as - // draft-uberti-rtcweb-plan-00 mandates. - }); - } - - // Add ssrc groups to the channel. - if (typeof uLine.ssrcGroups !== 'undefined' && - Array.isArray(uLine.ssrcGroups)) { - - // Create the ssrcGroups array, if it's not defined. - if (typeof type2bl[uLine.type].ssrcGroups === 'undefined' || - !Array.isArray(type2bl[uLine.type].ssrcGroups)) { - type2bl[uLine.type].ssrcGroups = []; - } - - type2bl[uLine.type].ssrcGroups = - type2bl[uLine.type].ssrcGroups.concat( - uLine.ssrcGroups); - } - - if (type2bl[uLine.type] === uLine) { - // Plan B mids are in ['audio', 'video', 'data'] - uLine.mid = uLine.type; - - // Plan B doesn't support/need the bundle-only attribute. - delete uLine.bundleOnly; - - // In Plan B the msid is an SSRC attribute. - delete uLine.msid; - - if (uLine.type == media[0].type) { - types.unshift(uLine.type); - // Add the channel to the new media array. - session.media.unshift(uLine); - } else { - types.push(uLine.type); - // Add the channel to the new media array. - session.media.push(uLine); - } - } - }); - - if (typeof session.groups !== 'undefined') { - // We regenerate the BUNDLE group with the new mids. - session.groups.some(function(group) { - if (group.type === 'BUNDLE') { - group.mids = types.join(' '); - return true; - } - }); - } - - // msid semantic - session.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - var resStr = transform.write(session); - - return new RTCSessionDescription({ - type: desc.type, - sdp: resStr - }); - - //#endregion -}; - -/* follow rules defined in RFC4145 */ -function addSetupAttr(uLine) { - if (typeof uLine.setup === 'undefined') { - return; - } - - if (uLine.setup === "active") { - uLine.setup = "passive"; - } else if (uLine.setup === "passive") { - uLine.setup = "active"; - } -} - -/** - * This method transforms a Plan B SDP to an equivalent Unified Plan SDP. A - * PeerConnection wrapper transforms the SDP to Unified Plan before passing it - * to FF. - * - * @param desc - * @returns {*} - */ -Interop.prototype.toUnifiedPlan = function(desc) { - var self = this; - //#region Preliminary input validation. - - if (typeof desc !== 'object' || desc === null || - typeof desc.sdp !== 'string') { - console.warn('An empty description was passed as an argument.'); - return desc; - } - - var session = transform.parse(desc.sdp); - - // If the SDP contains no media, there's nothing to transform. - if (typeof session.media === 'undefined' || - !Array.isArray(session.media) || session.media.length === 0) { - console.warn('The description has no media.'); - return desc; - } - - // Try some heuristics to "make sure" this is a Plan B SDP. Plan B SDP has - // a video, an audio and a data "channel" at most. - if (session.media.length > 3 || !session.media.every(function(m) { - return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; - })) { - console.warn('This description does not look like Plan B.'); - return desc; - } - - // Make sure this Plan B SDP can be converted to a Unified Plan SDP. - var mids = []; - session.media.forEach(function(m) { - mids.push(m.mid); - }); - - var hasBundle = false; - if (typeof session.groups !== 'undefined' && - Array.isArray(session.groups)) { - hasBundle = session.groups.every(function(g) { - return g.type !== 'BUNDLE' || - arrayEquals.apply(g.mids.sort(), [mids.sort()]); - }); - } - - if (!hasBundle) { - var mustBeBundle = false; - - session.media.forEach(function(m) { - if (m.direction !== 'inactive') { - mustBeBundle = true; - } - }); - - if (mustBeBundle) { - throw new Error("Cannot convert to Unified Plan because m-lines that" + - " are not bundled were found."); - } - } - - //#endregion - - - //#region Convert from Plan B to Unified Plan. - - // Unfortunately, a Plan B offer/answer doesn't have enough information to - // rebuild an equivalent Unified Plan offer/answer. - // - // For example, if this is a local answer (in Unified Plan style) that we - // convert to Plan B prior to handing it over to the application (the - // PeerConnection wrapper called us, for instance, after a successful - // createAnswer), we want to remember the m-line at which we've seen the - // (local) SSRC. That's because when the application wants to do call the - // SLD method, forcing us to do the inverse transformation (from Plan B to - // Unified Plan), we need to know to which m-line to assign the (local) - // SSRC. We also need to know all the other m-lines that the original - // answer had and include them in the transformed answer as well. - // - // Another example is if this is a remote offer that we convert to Plan B - // prior to giving it to the application, we want to remember the mid at - // which we've seen the (remote) SSRC. - // - // In the iteration that follows, we use the cached Unified Plan (if it - // exists) to assign mids to ssrcs. - - var type; - if (desc.type === 'answer') { - type = 'offer'; - } else if (desc.type === 'offer') { - type = 'answer'; - } else { - throw new Error("Type '" + desc.type + "' not supported."); - } - - var cached; - if (typeof this.cache[type] !== 'undefined') { - cached = transform.parse(this.cache[type]); - } - - var recvonlySsrcs = { - audio: {}, - video: {} - }; - - // A helper map that sends mids to m-line objects. We use it later to - // rebuild the Unified Plan style session.media array. - var mid2ul = {}; - var bIdx = 0; - var uIdx = 0; - - var sources2ul = {}; - - var candidates; - var iceUfrag; - var icePwd; - var fingerprint; - var payloads = {}; - var rtcpFb = {}; - var rtp = {}; - - session.media.forEach(function(bLine) { - if ((typeof bLine.rtcpMux !== 'string' || - bLine.rtcpMux !== 'rtcp-mux') && - bLine.direction !== 'inactive') { - throw new Error("Cannot convert to Unified Plan because m-lines " + - "without the rtcp-mux attribute were found."); - } - - if (bLine.type === 'application') { - mid2ul[bLine.mid] = bLine; - return; - } - - // With rtcp-mux and bundle all the channels should have the same ICE - // stuff. - var sources = bLine.sources; - var ssrcGroups = bLine.ssrcGroups; - var port = bLine.port; - - /* Chrome adds different candidates even using bundle, so we concat the candidates list */ - if (typeof bLine.candidates != 'undefined') { - if (typeof candidates != 'undefined') { - candidates = candidates.concat(bLine.candidates); - } else { - candidates = bLine.candidates; - } - } - - if ((typeof iceUfrag != 'undefined') && (typeof bLine.iceUfrag != 'undefined') && (iceUfrag != bLine.iceUfrag)) { - throw new Error("Only BUNDLE supported, iceUfrag must be the same for all m-lines.\n" + - "\tLast iceUfrag: " + iceUfrag + "\n" + - "\tNew iceUfrag: " + bLine.iceUfrag - ); - } - - if (typeof bLine.iceUfrag != 'undefined') { - iceUfrag = bLine.iceUfrag; - } - - if ((typeof icePwd != 'undefined') && (typeof bLine.icePwd != 'undefined') && (icePwd != bLine.icePwd)) { - throw new Error("Only BUNDLE supported, icePwd must be the same for all m-lines.\n" + - "\tLast icePwd: " + icePwd + "\n" + - "\tNew icePwd: " + bLine.icePwd - ); - } - - if (typeof bLine.icePwd != 'undefined') { - icePwd = bLine.icePwd; - } - - if ((typeof fingerprint != 'undefined') && (typeof bLine.fingerprint != 'undefined') && - (fingerprint.type != bLine.fingerprint.type || fingerprint.hash != bLine.fingerprint.hash)) { - throw new Error("Only BUNDLE supported, fingerprint must be the same for all m-lines.\n" + - "\tLast fingerprint: " + JSON.stringify(fingerprint) + "\n" + - "\tNew fingerprint: " + JSON.stringify(bLine.fingerprint) - ); - } - - if (typeof bLine.fingerprint != 'undefined') { - fingerprint = bLine.fingerprint; - } - - payloads[bLine.type] = bLine.payloads; - rtcpFb[bLine.type] = bLine.rtcpFb; - rtp[bLine.type] = bLine.rtp; - - // inverted ssrc group map - var ssrc2group = {}; - if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) { - ssrcGroups.forEach(function (ssrcGroup) { - // XXX This might brake if an SSRC is in more than one group - // for some reason. - if (typeof ssrcGroup.ssrcs !== 'undefined' && - Array.isArray(ssrcGroup.ssrcs)) { - ssrcGroup.ssrcs.forEach(function (ssrc) { - if (typeof ssrc2group[ssrc] === 'undefined') { - ssrc2group[ssrc] = []; - } - - ssrc2group[ssrc].push(ssrcGroup); - }); - } - }); - } - - // ssrc to m-line index. - var ssrc2ml = {}; - - if (typeof sources === 'object') { - - // We'll use the "bLine" object as a prototype for each new "mLine" - // that we create, but first we need to clean it up a bit. - delete bLine.sources; - delete bLine.ssrcGroups; - delete bLine.candidates; - delete bLine.iceUfrag; - delete bLine.icePwd; - delete bLine.fingerprint; - delete bLine.port; - delete bLine.mid; - - // Explode the Plan B channel sources with one m-line per source. - Object.keys(sources).forEach(function(ssrc) { - - // The (unified) m-line for this SSRC. We either create it from - // scratch or, if it's a grouped SSRC, we re-use a related - // mline. In other words, if the source is grouped with another - // source, put the two together in the same m-line. - var uLine; - - // We assume here that we are the answerer in the O/A, so any - // offers which we translate come from the remote side, while - // answers are local. So the check below is to make that we - // handle receive-only SSRCs in a special way only if they come - // from the remote side. - if (desc.type==='offer') { - // We want to detect SSRCs which are used by a remote peer - // in an m-line with direction=recvonly (i.e. they are - // being used for RTCP only). - // This information would have gotten lost if the remote - // peer used Unified Plan and their local description was - // translated to Plan B. So we use the lack of an MSID - // attribute to deduce a "receive only" SSRC. - if (!sources[ssrc].msid) { - recvonlySsrcs[bLine.type][ssrc] = sources[ssrc]; - // Receive-only SSRCs must not create new m-lines. We - // will assign them to an existing m-line later. - return; - } - } - - if (typeof ssrc2group[ssrc] !== 'undefined' && - Array.isArray(ssrc2group[ssrc])) { - ssrc2group[ssrc].some(function (ssrcGroup) { - // ssrcGroup.ssrcs *is* an Array, no need to check - // again here. - return ssrcGroup.ssrcs.some(function (related) { - if (typeof ssrc2ml[related] === 'object') { - uLine = ssrc2ml[related]; - return true; - } - }); - }); - } - - if (typeof uLine === 'object') { - // the m-line already exists. Just add the source. - uLine.sources[ssrc] = sources[ssrc]; - delete sources[ssrc].msid; - } else { - // Use the "bLine" as a prototype for the "uLine". - uLine = Object.create(bLine); - ssrc2ml[ssrc] = uLine; - - if (typeof sources[ssrc].msid !== 'undefined') { - // Assign the msid of the source to the m-line. Note - // that it is not guaranteed that the source will have - // msid. In particular "recvonly" sources don't have an - // msid. Note that "recvonly" is a term only defined - // for m-lines. - uLine.msid = sources[ssrc].msid; - delete sources[ssrc].msid; - } - - // We assign one SSRC per media line. - uLine.sources = {}; - uLine.sources[ssrc] = sources[ssrc]; - uLine.ssrcGroups = ssrc2group[ssrc]; - - // Use the cached Unified Plan SDP (if it exists) to assign - // SSRCs to mids. - if (typeof cached !== 'undefined' && - typeof cached.media !== 'undefined' && - Array.isArray(cached.media)) { - - cached.media.forEach(function (m) { - if (typeof m.sources === 'object') { - Object.keys(m.sources).forEach(function (s) { - if (s === ssrc) { - uLine.mid = m.mid; - } - }); - } - }); - } - - if (typeof uLine.mid === 'undefined') { - - // If this is an SSRC that we see for the first time - // assign it a new mid. This is typically the case when - // this method is called to transform a remote - // description for the first time or when there is a - // new SSRC in the remote description because a new - // peer has joined the conference. Local SSRCs should - // have already been added to the map in the toPlanB - // method. - // - // Because FF generates answers in Unified Plan style, - // we MUST already have a cached answer with all the - // local SSRCs mapped to some m-line/mid. - - uLine.mid = [bLine.type, '-', ssrc].join(''); - } - - // Include the candidates in the 1st media line. - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - uLine.port = port; - - mid2ul[uLine.mid] = uLine; - sources2ul[uIdx] = uLine.sources; - - self.cache.mlU2BMap[uIdx] = bIdx; - if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { - self.cache.mlB2UMap[bIdx] = uIdx; - } - uIdx++; - } - }); - } else { - var uLine = bLine; - - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - uLine.port = port; - - mid2ul[uLine.mid] = uLine; - - self.cache.mlU2BMap[uIdx] = bIdx; - if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { - self.cache.mlB2UMap[bIdx] = uIdx; - } - } - - bIdx++; - }); - - // Rebuild the media array in the right order and add the missing mLines - // (missing from the Plan B SDP). - session.media = []; - mids = []; // reuse - - if (desc.type === 'answer') { - - // The media lines in the answer must match the media lines in the - // offer. The order is important too. Here we assume that Firefox is - // the answerer, so we merely have to use the reconstructed (unified) - // answer to update the cached (unified) answer accordingly. - // - // In the general case, one would have to use the cached (unified) - // offer to find the m-lines that are missing from the reconstructed - // answer, potentially grabbing them from the cached (unified) answer. - // One has to be careful with this approach because inactive m-lines do - // not always have an mid, making it tricky (impossible?) to find where - // exactly and which m-lines are missing from the reconstructed answer. - - for (var i = 0; i < cached.media.length; i++) { - var uLine = cached.media[i]; - - delete uLine.msid; - delete uLine.sources; - delete uLine.ssrcGroups; - - if (typeof sources2ul[i] === 'undefined') { - if (!uLine.direction - || uLine.direction === 'sendrecv') - uLine.direction = 'recvonly'; - else if (uLine.direction === 'sendonly') - uLine.direction = 'inactive'; - } else { - if (!uLine.direction - || uLine.direction === 'sendrecv') - uLine.direction = 'sendrecv'; - else if (uLine.direction === 'recvonly') - uLine.direction = 'sendonly'; - } - - uLine.sources = sources2ul[i]; - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - - uLine.rtp = rtp[uLine.type]; - uLine.payloads = payloads[uLine.type]; - uLine.rtcpFb = rtcpFb[uLine.type]; - - session.media.push(uLine); - - if (typeof uLine.mid === 'string') { - // inactive lines don't/may not have an mid. - mids.push(uLine.mid); - } - } - } else { - - // SDP offer/answer (and the JSEP spec) forbids removing an m-section - // under any circumstances. If we are no longer interested in sending a - // track, we just remove the msid and ssrc attributes and set it to - // either a=recvonly (as the reofferer, we must use recvonly if the - // other side was previously sending on the m-section, but we can also - // leave the possibility open if it wasn't previously in use), or - // a=inactive. - - if (typeof cached !== 'undefined' && - typeof cached.media !== 'undefined' && - Array.isArray(cached.media)) { - cached.media.forEach(function(uLine) { - mids.push(uLine.mid); - if (typeof mid2ul[uLine.mid] !== 'undefined') { - session.media.push(mid2ul[uLine.mid]); - } else { - delete uLine.msid; - delete uLine.sources; - delete uLine.ssrcGroups; - - if (!uLine.direction - || uLine.direction === 'sendrecv') { - uLine.direction = 'sendonly'; - } - if (!uLine.direction - || uLine.direction === 'recvonly') { - uLine.direction = 'inactive'; - } - - addSetupAttr (uLine); - session.media.push(uLine); - } - }); - } - - // Add all the remaining (new) m-lines of the transformed SDP. - Object.keys(mid2ul).forEach(function(mid) { - if (mids.indexOf(mid) === -1) { - mids.push(mid); - if (mid2ul[mid].direction === 'recvonly') { - // This is a remote recvonly channel. Add its SSRC to the - // appropriate sendrecv or sendonly channel. - // TODO(gp) what if we don't have sendrecv/sendonly - // channel? - - var done = false; - - session.media.some(function (uLine) { - if ((uLine.direction === 'sendrecv' || - uLine.direction === 'sendonly') && - uLine.type === mid2ul[mid].type) { - // mid2ul[mid] shouldn't have any ssrc-groups - Object.keys(mid2ul[mid].sources).forEach( - function (ssrc) { - uLine.sources[ssrc] = - mid2ul[mid].sources[ssrc]; - }); - - done = true; - return true; - } - }); - - if (!done) { - session.media.push(mid2ul[mid]); - } - } else { - session.media.push(mid2ul[mid]); - } - } - }); - } - - // After we have constructed the Plan Unified m-lines we can figure out - // where (in which m-line) to place the 'recvonly SSRCs'. - // Note: we assume here that we are the answerer in the O/A, so any offers - // which we translate come from the remote side, while answers are local - // (and so our last local description is cached as an 'answer'). - ["audio", "video"].forEach(function (type) { - if (!session || !session.media || !Array.isArray(session.media)) - return; - - var idx = null; - if (Object.keys(recvonlySsrcs[type]).length > 0) { - idx = self.getFirstSendingIndexFromAnswer(type); - if (idx === null){ - // If this is the first offer we receive, we don't have a - // cached answer. Assume that we will be sending media using - // the first m-line for each media type. - - for (var i = 0; i < session.media.length; i++) { - if (session.media[i].type === type) { - idx = i; - break; - } - } - } - } - - if (idx && session.media.length > idx) { - var mLine = session.media[idx]; - Object.keys(recvonlySsrcs[type]).forEach(function(ssrc) { - if (mLine.sources && mLine.sources[ssrc]) { - console.warn("Replacing an existing SSRC."); - } - if (!mLine.sources) { - mLine.sources = {}; - } - - mLine.sources[ssrc] = recvonlySsrcs[type][ssrc]; - }); - } - }); - - if (typeof session.groups !== 'undefined') { - // We regenerate the BUNDLE group (since we regenerated the mids) - session.groups.some(function(group) { - if (group.type === 'BUNDLE') { - group.mids = mids.join(' '); - return true; - } - }); - } - - // msid semantic - session.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - var resStr = transform.write(session); - - // Cache the transformed SDP (Unified Plan) for later re-use in this - // function. - this.cache[desc.type] = resStr; - - return new RTCSessionDescription({ - type: desc.type, - sdp: resStr - }); - - //#endregion -}; - -},{"./array-equals":14,"./transform":17}],17:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var transform = require('sdp-transform'); - -exports.write = function(session, opts) { - - if (typeof session !== 'undefined' && - typeof session.media !== 'undefined' && - Array.isArray(session.media)) { - - session.media.forEach(function (mLine) { - // expand sources to ssrcs - if (typeof mLine.sources !== 'undefined' && - Object.keys(mLine.sources).length !== 0) { - mLine.ssrcs = []; - Object.keys(mLine.sources).forEach(function (ssrc) { - var source = mLine.sources[ssrc]; - Object.keys(source).forEach(function (attribute) { - mLine.ssrcs.push({ - id: ssrc, - attribute: attribute, - value: source[attribute] - }); - }); - }); - delete mLine.sources; - } - - // join ssrcs in ssrc groups - if (typeof mLine.ssrcGroups !== 'undefined' && - Array.isArray(mLine.ssrcGroups)) { - mLine.ssrcGroups.forEach(function (ssrcGroup) { - if (typeof ssrcGroup.ssrcs !== 'undefined' && - Array.isArray(ssrcGroup.ssrcs)) { - ssrcGroup.ssrcs = ssrcGroup.ssrcs.join(' '); - } - }); - } - }); - } - - // join group mids - if (typeof session !== 'undefined' && - typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { - - session.groups.forEach(function (g) { - if (typeof g.mids !== 'undefined' && Array.isArray(g.mids)) { - g.mids = g.mids.join(' '); - } - }); - } - - return transform.write(session, opts); -}; - -exports.parse = function(sdp) { - var session = transform.parse(sdp); - - if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && - Array.isArray(session.media)) { - - session.media.forEach(function (mLine) { - // group sources attributes by ssrc - if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) { - mLine.sources = {}; - mLine.ssrcs.forEach(function (ssrc) { - if (!mLine.sources[ssrc.id]) - mLine.sources[ssrc.id] = {}; - mLine.sources[ssrc.id][ssrc.attribute] = ssrc.value; - }); - - delete mLine.ssrcs; - } - - // split ssrcs in ssrc groups - if (typeof mLine.ssrcGroups !== 'undefined' && - Array.isArray(mLine.ssrcGroups)) { - mLine.ssrcGroups.forEach(function (ssrcGroup) { - if (typeof ssrcGroup.ssrcs === 'string') { - ssrcGroup.ssrcs = ssrcGroup.ssrcs.split(' '); - } - }); - } - }); - } - // split group mids - if (typeof session !== 'undefined' && - typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { - - session.groups.forEach(function (g) { - if (typeof g.mids === 'string') { - g.mids = g.mids.split(' '); - } - }); - } - - return session; -}; - - -},{"sdp-transform":11}],18:[function(require,module,exports){ -/*! - * UAParser.js v0.7.18 - * Lightweight JavaScript-based User-Agent string parser - * https://github.com/faisalman/ua-parser-js - * - * Copyright © 2012-2016 Faisal Salman - * Dual licensed under GPLv2 or MIT - */ - -(function (window, undefined) { - - 'use strict'; - - ////////////// - // Constants - ///////////// - - - var LIBVERSION = '0.7.18', - EMPTY = '', - UNKNOWN = '?', - FUNC_TYPE = 'function', - UNDEF_TYPE = 'undefined', - OBJ_TYPE = 'object', - STR_TYPE = 'string', - MAJOR = 'major', // deprecated - MODEL = 'model', - NAME = 'name', - TYPE = 'type', - VENDOR = 'vendor', - VERSION = 'version', - ARCHITECTURE= 'architecture', - CONSOLE = 'console', - MOBILE = 'mobile', - TABLET = 'tablet', - SMARTTV = 'smarttv', - WEARABLE = 'wearable', - EMBEDDED = 'embedded'; - - - /////////// - // Helper - ////////// - - - var util = { - extend : function (regexes, extensions) { - var margedRegexes = {}; - for (var i in regexes) { - if (extensions[i] && extensions[i].length % 2 === 0) { - margedRegexes[i] = extensions[i].concat(regexes[i]); - } else { - margedRegexes[i] = regexes[i]; - } - } - return margedRegexes; - }, - has : function (str1, str2) { - if (typeof str1 === "string") { - return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; - } else { - return false; - } - }, - lowerize : function (str) { - return str.toLowerCase(); - }, - major : function (version) { - return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g,'').split(".")[0] : undefined; - }, - trim : function (str) { - return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); - } - }; - - - /////////////// - // Map helper - ////////////// - - - var mapper = { - - rgx : function (ua, arrays) { - - //var result = {}, - var i = 0, j, k, p, q, matches, match;//, args = arguments; - - /*// construct object barebones - for (p = 0; p < args[1].length; p++) { - q = args[1][p]; - result[typeof q === OBJ_TYPE ? q[0] : q] = undefined; - }*/ - - // loop through all regexes maps - while (i < arrays.length && !matches) { - - var regex = arrays[i], // even sequence (0,2,4,..) - props = arrays[i + 1]; // odd sequence (1,3,5,..) - j = k = 0; - - // try matching uastring with regexes - while (j < regex.length && !matches) { - - matches = regex[j++].exec(ua); - - if (!!matches) { - for (p = 0; p < props.length; p++) { - match = matches[++k]; - q = props[p]; - // check if given property is actually array - if (typeof q === OBJ_TYPE && q.length > 0) { - if (q.length == 2) { - if (typeof q[1] == FUNC_TYPE) { - // assign modified match - this[q[0]] = q[1].call(this, match); - } else { - // assign given value, ignore regex match - this[q[0]] = q[1]; - } - } else if (q.length == 3) { - // check whether function or regex - if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { - // call function (usually string mapper) - this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; - } else { - // sanitize match using given regex - this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; - } - } else if (q.length == 4) { - this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; - } - } else { - this[q] = match ? match : undefined; - } - } - } - } - i += 2; - } - // console.log(this); - //return this; - }, - - str : function (str, map) { - - for (var i in map) { - // check if array - if (typeof map[i] === OBJ_TYPE && map[i].length > 0) { - for (var j = 0; j < map[i].length; j++) { - if (util.has(map[i][j], str)) { - return (i === UNKNOWN) ? undefined : i; - } - } - } else if (util.has(map[i], str)) { - return (i === UNKNOWN) ? undefined : i; - } - } - return str; - } - }; - - - /////////////// - // String map - ////////////// - - - var maps = { - - browser : { - oldsafari : { - version : { - '1.0' : '/8', - '1.2' : '/1', - '1.3' : '/3', - '2.0' : '/412', - '2.0.2' : '/416', - '2.0.3' : '/417', - '2.0.4' : '/419', - '?' : '/' - } - } - }, - - device : { - amazon : { - model : { - 'Fire Phone' : ['SD', 'KF'] - } - }, - sprint : { - model : { - 'Evo Shift 4G' : '7373KT' - }, - vendor : { - 'HTC' : 'APA', - 'Sprint' : 'Sprint' - } - } - }, - - os : { - windows : { - version : { - 'ME' : '4.90', - 'NT 3.11' : 'NT3.51', - 'NT 4.0' : 'NT4.0', - '2000' : 'NT 5.0', - 'XP' : ['NT 5.1', 'NT 5.2'], - 'Vista' : 'NT 6.0', - '7' : 'NT 6.1', - '8' : 'NT 6.2', - '8.1' : 'NT 6.3', - '10' : ['NT 6.4', 'NT 10.0'], - 'RT' : 'ARM' - } - } - } - }; - - - ////////////// - // Regex map - ///////////// - - - var regexes = { - - browser : [[ - - // Presto based - /(opera\smini)\/([\w\.-]+)/i, // Opera Mini - /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet - /(opera).+version\/([\w\.]+)/i, // Opera > 9.80 - /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 - ], [NAME, VERSION], [ - - /(opios)[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0 - ], [[NAME, 'Opera Mini'], VERSION], [ - - /\s(opr)\/([\w\.]+)/i // Opera Webkit - ], [[NAME, 'Opera'], VERSION], [ - - // Mixed - /(kindle)\/([\w\.]+)/i, // Kindle - /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]*)/i, - // Lunascape/Maxthon/Netfront/Jasmine/Blazer - - // Trident based - /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i, - // Avant/IEMobile/SlimBrowser/Baidu - /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer - - // Webkit/KHTML based - /(rekonq)\/([\w\.]*)/i, // Rekonq - /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark)\/([\w\.-]+)/i - // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser - ], [NAME, VERSION], [ - - /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11 - ], [[NAME, 'IE'], VERSION], [ - - /(edge|edgios|edgea)\/((\d+)?[\w\.]+)/i // Microsoft Edge - ], [[NAME, 'Edge'], VERSION], [ - - /(yabrowser)\/([\w\.]+)/i // Yandex - ], [[NAME, 'Yandex'], VERSION], [ - - /(puffin)\/([\w\.]+)/i // Puffin - ], [[NAME, 'Puffin'], VERSION], [ - - /((?:[\s\/])uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i - // UCBrowser - ], [[NAME, 'UCBrowser'], VERSION], [ - - /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon - ], [[NAME, /_/g, ' '], VERSION], [ - - /(micromessenger)\/([\w\.]+)/i // WeChat - ], [[NAME, 'WeChat'], VERSION], [ - - /(qqbrowserlite)\/([\w\.]+)/i // QQBrowserLite - ], [NAME, VERSION], [ - - /(QQ)\/([\d\.]+)/i // QQ, aka ShouQ - ], [NAME, VERSION], [ - - /m?(qqbrowser)[\/\s]?([\w\.]+)/i // QQBrowser - ], [NAME, VERSION], [ - - /(BIDUBrowser)[\/\s]?([\w\.]+)/i // Baidu Browser - ], [NAME, VERSION], [ - - /(2345Explorer)[\/\s]?([\w\.]+)/i // 2345 Browser - ], [NAME, VERSION], [ - - /(MetaSr)[\/\s]?([\w\.]+)/i // SouGouBrowser - ], [NAME], [ - - /(LBBROWSER)/i // LieBao Browser - ], [NAME], [ - - /xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser - ], [VERSION, [NAME, 'MIUI Browser']], [ - - /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android - ], [VERSION, [NAME, 'Facebook']], [ - - /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless - ], [VERSION, [NAME, 'Chrome Headless']], [ - - /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView - ], [[NAME, /(.+)/, '$1 WebView'], VERSION], [ - - /((?:oculus|samsung)browser)\/([\w\.]+)/i - ], [[NAME, /(.+(?:g|us))(.+)/, '$1 $2'], VERSION], [ // Oculus / Samsung Browser - - /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)*/i // Android Browser - ], [VERSION, [NAME, 'Android Browser']], [ - - /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i - // Chrome/OmniWeb/Arora/Tizen/Nokia - ], [NAME, VERSION], [ - - /(dolfin)\/([\w\.]+)/i // Dolphin - ], [[NAME, 'Dolphin'], VERSION], [ - - /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS - ], [[NAME, 'Chrome'], VERSION], [ - - /(coast)\/([\w\.]+)/i // Opera Coast - ], [[NAME, 'Opera Coast'], VERSION], [ - - /fxios\/([\w\.-]+)/i // Firefox for iOS - ], [VERSION, [NAME, 'Firefox']], [ - - /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari - ], [VERSION, [NAME, 'Mobile Safari']], [ - - /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile - ], [VERSION, NAME], [ - - /webkit.+?(gsa)\/([\w\.]+).+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Google Search Appliance on iOS - ], [[NAME, 'GSA'], VERSION], [ - - /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 - ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [ - - /(konqueror)\/([\w\.]+)/i, // Konqueror - /(webkit|khtml)\/([\w\.]+)/i - ], [NAME, VERSION], [ - - // Gecko based - /(navigator|netscape)\/([\w\.-]+)/i // Netscape - ], [[NAME, 'Netscape'], VERSION], [ - /(swiftfox)/i, // Swiftfox - /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i, - // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror - /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([\w\.-]+)$/i, - - // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix - /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla - - // Other - /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i, - // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir - /(links)\s\(([\w\.]+)/i, // Links - /(gobrowser)\/?([\w\.]*)/i, // GoBrowser - /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser - /(mosaic)[\/\s]([\w\.]+)/i // Mosaic - ], [NAME, VERSION] - - /* ///////////////////// - // Media players BEGIN - //////////////////////// - - , [ - - /(apple(?:coremedia|))\/((\d+)[\w\._]+)/i, // Generic Apple CoreMedia - /(coremedia) v((\d+)[\w\._]+)/i - ], [NAME, VERSION], [ - - /(aqualung|lyssna|bsplayer)\/((\d+)?[\w\.-]+)/i // Aqualung/Lyssna/BSPlayer - ], [NAME, VERSION], [ - - /(ares|ossproxy)\s((\d+)[\w\.-]+)/i // Ares/OSSProxy - ], [NAME, VERSION], [ - - /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/((\d+)[\w\.-]+)/i, - // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC - // NSPlayer/PSP-InternetRadioPlayer/Videos - /(clementine|music player daemon)\s((\d+)[\w\.-]+)/i, // Clementine/MPD - /(lg player|nexplayer)\s((\d+)[\d\.]+)/i, - /player\/(nexplayer|lg player)\s((\d+)[\w\.-]+)/i // NexPlayer/LG Player - ], [NAME, VERSION], [ - /(nexplayer)\s((\d+)[\w\.-]+)/i // Nexplayer - ], [NAME, VERSION], [ - - /(flrp)\/((\d+)[\w\.-]+)/i // Flip Player - ], [[NAME, 'Flip Player'], VERSION], [ - - /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i - // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit - ], [NAME], [ - - /(gstreamer) souphttpsrc (?:\([^\)]+\)){0,1} libsoup\/((\d+)[\w\.-]+)/i - // Gstreamer - ], [NAME, VERSION], [ - - /(htc streaming player)\s[\w_]+\s\/\s((\d+)[\d\.]+)/i, // HTC Streaming Player - /(java|python-urllib|python-requests|wget|libcurl)\/((\d+)[\w\.-_]+)/i, - // Java/urllib/requests/wget/cURL - /(lavf)((\d+)[\d\.]+)/i // Lavf (FFMPEG) - ], [NAME, VERSION], [ - - /(htc_one_s)\/((\d+)[\d\.]+)/i // HTC One S - ], [[NAME, /_/g, ' '], VERSION], [ - - /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+){0,1})/i - // MPlayer SVN - ], [NAME, VERSION], [ - - /(mplayer)(?:\s|\/|[unkow-]+)((\d+)[\w\.-]+)/i // MPlayer - ], [NAME, VERSION], [ - - /(mplayer)/i, // MPlayer (no other info) - /(yourmuze)/i, // YourMuze - /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime - ], [NAME], [ - - /(nero (?:home|scout))\/((\d+)[\w\.-]+)/i // Nero Home/Nero Scout - ], [NAME, VERSION], [ - - /(nokia\d+)\/((\d+)[\w\.-]+)/i // Nokia - ], [NAME, VERSION], [ - - /\s(songbird)\/((\d+)[\w\.-]+)/i // Songbird/Philips-Songbird - ], [NAME, VERSION], [ - - /(winamp)3 version ((\d+)[\w\.-]+)/i, // Winamp - /(winamp)\s((\d+)[\w\.-]+)/i, - /(winamp)mpeg\/((\d+)[\w\.-]+)/i - ], [NAME, VERSION], [ - - /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) - // inlight radio - ], [NAME], [ - - /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/((\d+)[\w\.-]+)/i - // QuickTime/RealMedia/RadioApp/RadioClientApplication/ - // SoundTap/Totem/Stagefright/Streamium - ], [NAME, VERSION], [ - - /(smp)((\d+)[\d\.]+)/i // SMP - ], [NAME, VERSION], [ - - /(vlc) media player - version ((\d+)[\w\.]+)/i, // VLC Videolan - /(vlc)\/((\d+)[\w\.-]+)/i, - /(xbmc|gvfs|xine|xmms|irapp)\/((\d+)[\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp - /(foobar2000)\/((\d+)[\d\.]+)/i, // Foobar2000 - /(itunes)\/((\d+)[\d\.]+)/i // iTunes - ], [NAME, VERSION], [ - - /(wmplayer)\/((\d+)[\w\.-]+)/i, // Windows Media Player - /(windows-media-player)\/((\d+)[\w\.-]+)/i - ], [[NAME, /-/g, ' '], VERSION], [ - - /windows\/((\d+)[\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i - // Windows Media Server - ], [VERSION, [NAME, 'Windows']], [ - - /(com\.riseupradioalarm)\/((\d+)[\d\.]*)/i // RiseUP Radio Alarm - ], [NAME, VERSION], [ - - /(rad.io)\s((\d+)[\d\.]+)/i, // Rad.io - /(radio.(?:de|at|fr))\s((\d+)[\d\.]+)/i - ], [[NAME, 'rad.io'], VERSION] - - ////////////////////// - // Media players END - ////////////////////*/ - - ], - - cpu : [[ - - /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 - ], [[ARCHITECTURE, 'amd64']], [ - - /(ia32(?=;))/i // IA32 (quicktime) - ], [[ARCHITECTURE, util.lowerize]], [ - - /((?:i[346]|x)86)[;\)]/i // IA32 - ], [[ARCHITECTURE, 'ia32']], [ - - // PocketPC mistakenly identified as PowerPC - /windows\s(ce|mobile);\sppc;/i - ], [[ARCHITECTURE, 'arm']], [ - - /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC - ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [ - - /(sun4\w)[;\)]/i // SPARC - ], [[ARCHITECTURE, 'sparc']], [ - - /((?:avr32|ia64(?=;))|68k(?=\))|arm(?:64|(?=v\d+;))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)/i - // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC - ], [[ARCHITECTURE, util.lowerize]] - ], - - device : [[ - - /\((ipad|playbook);[\w\s\);-]+(rim|apple)/i // iPad/PlayBook - ], [MODEL, VENDOR, [TYPE, TABLET]], [ - - /applecoremedia\/[\w\.]+ \((ipad)/ // iPad - ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ - - /(apple\s{0,1}tv)/i // Apple TV - ], [[MODEL, 'Apple TV'], [VENDOR, 'Apple']], [ - - /(archos)\s(gamepad2?)/i, // Archos - /(hp).+(touchpad)/i, // HP TouchPad - /(hp).+(tablet)/i, // HP Tablet - /(kindle)\/([\w\.]+)/i, // Kindle - /\s(nook)[\w\s]+build\/(\w+)/i, // Nook - /(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /(kf[A-z]+)\sbuild\/.+silk\//i // Kindle Fire HD - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ - /(sd|kf)[0349hijorstuw]+\sbuild\/.+silk\//i // Fire Phone - ], [[MODEL, mapper.str, maps.device.amazon.model], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ - - /\((ip[honed|\s\w*]+);.+(apple)/i // iPod/iPhone - ], [MODEL, VENDOR, [TYPE, MOBILE]], [ - /\((ip[honed|\s\w*]+);/i // iPod/iPhone - ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ - - /(blackberry)[\s-]?(\w+)/i, // BlackBerry - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]*)/i, - // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron - /(hp)\s([\w\s]+\w)/i, // HP iPAQ - /(asus)-?(\w+)/i // Asus - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /\(bb10;\s(\w+)/i // BlackBerry 10 - ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ - // Asus Tablets - /android.+(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7|padfone)/i - ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [ - - /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony - /(sony)?(?:sgp.+)\sbuild\//i - ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [ - /android.+\s([c-g]\d{4}|so[-l]\w+)\sbuild\//i - ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - - /\s(ouya)\s/i, // Ouya - /(nintendo)\s([wids3u]+)/i // Nintendo - ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ - - /android.+;\s(shield)\sbuild/i // Nvidia - ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ - - /(playstation\s[34portablevi]+)/i // Playstation - ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ - - /(sprint\s(\w+))/i // Sprint Phones - ], [[VENDOR, mapper.str, maps.device.sprint.vendor], [MODEL, mapper.str, maps.device.sprint.model], [TYPE, MOBILE]], [ - - /(lenovo)\s?(S(?:5000|6000)+(?:[-][\w+]))/i // Lenovo tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC - /(zte)-(\w*)/i, // ZTE - /(alcatel|geeksphone|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]*)/i - // Alcatel/GeeksPhone/Lenovo/Nexian/Panasonic/Sony - ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ - - /(nexus\s9)/i // HTC Nexus 9 - ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ - - /d\/huawei([\w\s-]+)[;\)]/i, - /(nexus\s6p)/i // Huawei - ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ - - /(microsoft);\s(lumia[\s\w]+)/i // Microsoft Lumia - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /[\s\(;](xbox(?:\sone)?)[\s\);]/i // Microsoft Xbox - ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [ - /(kin\.[onetw]{3})/i // Microsoft Kin - ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ - - // Motorola - /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?:?(\s4g)?)[\w\s]+build\//i, - /mot[\s-]?(\w*)/i, - /(XT\d{3,4}) build\//i, - /(nexus\s6)/i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ - /android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [ - - /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices - ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ - - /hbbtv.+maple;(\d+)/i - ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [ - - /\(dtv[\);].+(aquos)/i // Sharp - ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [ - - /android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10))/i, - /((SM-T\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung - /smart-tv.+(samsung)/i - ], [VENDOR, [TYPE, SMARTTV], MODEL], [ - /((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+))/i, - /(sam[sung]*)[\s-]*(\w+-?[\w-]*)/i, - /sec-((sgh\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [ - - /sie-(\w*)/i // Siemens - ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ - - /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia - /(nokia)[\s_-]?([\w-]*)/i - ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [ - - /android\s3\.[\s\w;-]{10}(a\d{3})/i // Acer - ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ - - /android.+([vl]k\-?\d{3})\s+build/i // LG Tablet - ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [ - /android\s3\.[\s\w;-]{10}(lg?)-([06cv9]{3,4})/i // LG Tablet - ], [[VENDOR, 'LG'], MODEL, [TYPE, TABLET]], [ - /(lg) netcast\.tv/i // LG SmartTV - ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ - /(nexus\s[45])/i, // LG - /lg[e;\s\/-]+(\w*)/i, - /android.+lg(\-?[\d\w]+)\s+build/i - ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [ - - /android.+(ideatab[a-z0-9\-\s]+)/i // Lenovo - ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ - - /linux;.+((jolla));/i // Jolla - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /((pebble))app\/[\d\.]+\s/i // Pebble - ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ - - /android.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /crkey/i // Google Chromecast - ], [[MODEL, 'Chromecast'], [VENDOR, 'Google']], [ - - /android.+;\s(glass)\s\d/i // Google Glass - ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [ - - /android.+;\s(pixel c)\s/i // Google Pixel C - ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ - - /android.+;\s(pixel xl|pixel)\s/i // Google Pixel - ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ - - /android.+;\s(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models - /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi - /android.+(mi[\s\-_]*(?:one|one[\s_]plus|note lte)?[\s_]*(?:\d?\w?)[\s_]*(?:plus)?)\s+build/i, // Xiaomi Mi - /android.+(redmi[\s\-_]*(?:note)?(?:[\s_]*[\w\s]+))\s+build/i // Redmi Phones - ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ - /android.+(mi[\s\-_]*(?:pad)(?:[\s_]*[\w\s]+))\s+build/i // Mi Pad tablets - ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ - /android.+;\s(m[1-5]\snote)\sbuild/i // Meizu Tablet - ], [MODEL, [VENDOR, 'Meizu'], [TYPE, TABLET]], [ - - /android.+a000(1)\s+build/i, // OnePlus - /android.+oneplus\s(a\d{4})\s+build/i - ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(RCT[\d\w]+)\s+build/i // RCA Tablets - ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ - - /android.+[;\/\s]+(Venue[\d\s]{2,7})\s+build/i // Dell Venue Tablets - ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Q[T|M][\d\w]+)\s+build/i // Verizon Tablet - ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ - - /android.+[;\/]\s+(Barnes[&\s]+Noble\s+|BN[RT])(V?.*)\s+build/i // Barnes & Noble Tablet - ], [[VENDOR, 'Barnes & Noble'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s+(TM\d{3}.*\b)\s+build/i // Barnes & Noble Tablet - ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ - - /android.+;\s(k88)\sbuild/i // ZTE K Series Tablet - ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(gen\d{3})\s+build.*49h/i // Swiss GEN Mobile - ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(zur\d{3})\s+build/i // Swiss ZUR Tablet - ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((Zeki)?TB.*\b)\s+build/i // Zeki Tablets - ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ - - /(android).+[;\/]\s+([YR]\d{2})\s+build/i, - /android.+[;\/]\s+(Dragon[\-\s]+Touch\s+|DT)(\w{5})\sbuild/i // Dragon Touch Tablet - ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*(NS-?\w{0,9})\sbuild/i // Insignia Tablets - ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((NX|Next)-?\w{0,9})\s+build/i // NextBook Tablets - ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Xtreme\_)?(V(1[045]|2[015]|30|40|60|7[05]|90))\s+build/i - ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones - - /android.+[;\/]\s*(LVTEL\-)?(V1[12])\s+build/i // LvTel Phones - ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(V(100MD|700NA|7011|917G).*\b)\s+build/i // Envizen Tablets - ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Le[\s\-]+Pan)[\s\-]+(\w{1,9})\s+build/i // Le Pan Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Trio[\s\-]*.*)\s+build/i // MachSpeed Tablets - ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Trinity)[\-\s]*(T\d{3})\s+build/i // Trinity Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*TU_(1491)\s+build/i // Rotor Tablets - ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ - - /android.+(KS(.+))\s+build/i // Amazon Kindle Tablets - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ - - /android.+(Gigaset)[\s\-]+(Q\w{1,9})\s+build/i // Gigaset Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet - /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile - ], [[TYPE, util.lowerize], VENDOR, MODEL], [ - - /(android[\w\.\s\-]{0,9});.+build/i // Generic Android Device - ], [MODEL, [VENDOR, 'Generic']] - - - /*////////////////////////// - // TODO: move to string map - //////////////////////////// - - /(C6603)/i // Sony Xperia Z C6603 - ], [[MODEL, 'Xperia Z C6603'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - /(C6903)/i // Sony Xperia Z 1 - ], [[MODEL, 'Xperia Z 1'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - - /(SM-G900[F|H])/i // Samsung Galaxy S5 - ], [[MODEL, 'Galaxy S5'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G7102)/i // Samsung Galaxy Grand 2 - ], [[MODEL, 'Galaxy Grand 2'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G530H)/i // Samsung Galaxy Grand Prime - ], [[MODEL, 'Galaxy Grand Prime'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G313HZ)/i // Samsung Galaxy V - ], [[MODEL, 'Galaxy V'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-T805)/i // Samsung Galaxy Tab S 10.5 - ], [[MODEL, 'Galaxy Tab S 10.5'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ - /(SM-G800F)/i // Samsung Galaxy S5 Mini - ], [[MODEL, 'Galaxy S5 Mini'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-T311)/i // Samsung Galaxy Tab 3 8.0 - ], [[MODEL, 'Galaxy Tab 3 8.0'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ - - /(T3C)/i // Advan Vandroid T3C - ], [MODEL, [VENDOR, 'Advan'], [TYPE, TABLET]], [ - /(ADVAN T1J\+)/i // Advan Vandroid T1J+ - ], [[MODEL, 'Vandroid T1J+'], [VENDOR, 'Advan'], [TYPE, TABLET]], [ - /(ADVAN S4A)/i // Advan Vandroid S4A - ], [[MODEL, 'Vandroid S4A'], [VENDOR, 'Advan'], [TYPE, MOBILE]], [ - - /(V972M)/i // ZTE V972M - ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [ - - /(i-mobile)\s(IQ\s[\d\.]+)/i // i-mobile IQ - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /(IQ6.3)/i // i-mobile IQ IQ 6.3 - ], [[MODEL, 'IQ 6.3'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ - /(i-mobile)\s(i-style\s[\d\.]+)/i // i-mobile i-STYLE - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /(i-STYLE2.1)/i // i-mobile i-STYLE 2.1 - ], [[MODEL, 'i-STYLE 2.1'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ - - /(mobiistar touch LAI 512)/i // mobiistar touch LAI 512 - ], [[MODEL, 'Touch LAI 512'], [VENDOR, 'mobiistar'], [TYPE, MOBILE]], [ - - ///////////// - // END TODO - ///////////*/ - - ], - - engine : [[ - - /windows.+\sedge\/([\w\.]+)/i // EdgeHTML - ], [VERSION, [NAME, 'EdgeHTML']], [ - - /(presto)\/([\w\.]+)/i, // Presto - /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m - /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links - /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab - ], [NAME, VERSION], [ - - /rv\:([\w\.]{1,9}).+(gecko)/i // Gecko - ], [VERSION, NAME] - ], - - os : [[ - - // Windows based - /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes) - ], [NAME, VERSION], [ - /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT - /(windows\sphone(?:\sos)*)[\s\/]?([\d\.\s\w]*)/i, // Windows Phone - /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i - ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ - /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i - ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ - - // Mobile/Embedded OS - /\((bb)(10);/i // BlackBerry 10 - ], [[NAME, 'BlackBerry'], VERSION], [ - /(blackberry)\w*\/?([\w\.]*)/i, // Blackberry - /(tizen)[\/\s]([\w\.]+)/i, // Tizen - /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]*)/i, - // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki - /linux;.+(sailfish);/i // Sailfish OS - ], [NAME, VERSION], [ - /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]*)/i // Symbian - ], [[NAME, 'Symbian'], VERSION], [ - /\((series40);/i // Series 40 - ], [NAME], [ - /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS - ], [[NAME, 'Firefox OS'], VERSION], [ - - // Console - /(nintendo|playstation)\s([wids34portablevu]+)/i, // Nintendo/Playstation - - // GNU/Linux based - /(mint)[\/\s\(]?(\w*)/i, // Mint - /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux - /(joli|[kxln]?ubuntu|debian|suse|opensuse|gentoo|(?=\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?(?!chrom)([\w\.-]*)/i, - // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware - // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus - /(hurd|linux)\s?([\w\.]*)/i, // Hurd/Linux - /(gnu)\s?([\w\.]*)/i // GNU - ], [NAME, VERSION], [ - - /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS - ], [[NAME, 'Chromium OS'], VERSION],[ - - // Solaris - /(sunos)\s?([\w\.\d]*)/i // Solaris - ], [[NAME, 'Solaris'], VERSION], [ - - // BSD based - /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]*)/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly - ], [NAME, VERSION],[ - - /(haiku)\s(\w+)/i // Haiku - ], [NAME, VERSION],[ - - /cfnetwork\/.+darwin/i, - /ip[honead]{2,4}(?:.*os\s([\w]+)\slike\smac|;\sopera)/i // iOS - ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ - - /(mac\sos\sx)\s?([\w\s\.]*)/i, - /(macintosh|mac(?=_powerpc)\s)/i // Mac OS - ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ - - // Other - /((?:open)?solaris)[\/\s-]?([\w\.]*)/i, // Solaris - /(aix)\s((\d)(?=\.|\)|\s)[\w\.])*/i, // AIX - /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i, - // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS - /(unix)\s?([\w\.]*)/i // UNIX - ], [NAME, VERSION] - ] - }; - - - ///////////////// - // Constructor - //////////////// - /* - var Browser = function (name, version) { - this[NAME] = name; - this[VERSION] = version; - }; - var CPU = function (arch) { - this[ARCHITECTURE] = arch; - }; - var Device = function (vendor, model, type) { - this[VENDOR] = vendor; - this[MODEL] = model; - this[TYPE] = type; - }; - var Engine = Browser; - var OS = Browser; - */ - var UAParser = function (uastring, extensions) { - - if (typeof uastring === 'object') { - extensions = uastring; - uastring = undefined; - } - - if (!(this instanceof UAParser)) { - return new UAParser(uastring, extensions).getResult(); - } - - var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); - var rgxmap = extensions ? util.extend(regexes, extensions) : regexes; - //var browser = new Browser(); - //var cpu = new CPU(); - //var device = new Device(); - //var engine = new Engine(); - //var os = new OS(); - - this.getBrowser = function () { - var browser = { name: undefined, version: undefined }; - mapper.rgx.call(browser, ua, rgxmap.browser); - browser.major = util.major(browser.version); // deprecated - return browser; - }; - this.getCPU = function () { - var cpu = { architecture: undefined }; - mapper.rgx.call(cpu, ua, rgxmap.cpu); - return cpu; - }; - this.getDevice = function () { - var device = { vendor: undefined, model: undefined, type: undefined }; - mapper.rgx.call(device, ua, rgxmap.device); - return device; - }; - this.getEngine = function () { - var engine = { name: undefined, version: undefined }; - mapper.rgx.call(engine, ua, rgxmap.engine); - return engine; - }; - this.getOS = function () { - var os = { name: undefined, version: undefined }; - mapper.rgx.call(os, ua, rgxmap.os); - return os; - }; - this.getResult = function () { - return { - ua : this.getUA(), - browser : this.getBrowser(), - engine : this.getEngine(), - os : this.getOS(), - device : this.getDevice(), - cpu : this.getCPU() - }; - }; - this.getUA = function () { - return ua; - }; - this.setUA = function (uastring) { - ua = uastring; - //browser = new Browser(); - //cpu = new CPU(); - //device = new Device(); - //engine = new Engine(); - //os = new OS(); - return this; - }; - return this; - }; - - UAParser.VERSION = LIBVERSION; - UAParser.BROWSER = { - NAME : NAME, - MAJOR : MAJOR, // deprecated - VERSION : VERSION - }; - UAParser.CPU = { - ARCHITECTURE : ARCHITECTURE - }; - UAParser.DEVICE = { - MODEL : MODEL, - VENDOR : VENDOR, - TYPE : TYPE, - CONSOLE : CONSOLE, - MOBILE : MOBILE, - SMARTTV : SMARTTV, - TABLET : TABLET, - WEARABLE: WEARABLE, - EMBEDDED: EMBEDDED - }; - UAParser.ENGINE = { - NAME : NAME, - VERSION : VERSION - }; - UAParser.OS = { - NAME : NAME, - VERSION : VERSION - }; - //UAParser.Utils = util; - - /////////// - // Export - ////////// - - - // check js environment - if (typeof(exports) !== UNDEF_TYPE) { - // nodejs env - if (typeof module !== UNDEF_TYPE && module.exports) { - exports = module.exports = UAParser; - } - // TODO: test!!!!!!!! - /* - if (require && require.main === module && process) { - // cli - var jsonize = function (arr) { - var res = []; - for (var i in arr) { - res.push(new UAParser(arr[i]).getResult()); - } - process.stdout.write(JSON.stringify(res, null, 2) + '\n'); - }; - if (process.stdin.isTTY) { - // via args - jsonize(process.argv.slice(2)); - } else { - // via pipe - var str = ''; - process.stdin.on('readable', function() { - var read = process.stdin.read(); - if (read !== null) { - str += read; - } - }); - process.stdin.on('end', function () { - jsonize(str.replace(/\n$/, '').split('\n')); - }); - } - } - */ - exports.UAParser = UAParser; - } else { - // requirejs env (optional) - if (typeof(define) === FUNC_TYPE && define.amd) { - define(function () { - return UAParser; - }); - } else if (window) { - // browser env - window.UAParser = UAParser; - } - } - - // jQuery/Zepto specific (optional) - // Note: - // In AMD env the global scope should be kept clean, but jQuery is an exception. - // jQuery always exports to global scope, unless jQuery.noConflict(true) is used, - // and we should catch that. - var $ = window && (window.jQuery || window.Zepto); - if (typeof $ !== UNDEF_TYPE) { - var parser = new UAParser(); - $.ua = parser.getResult(); - $.ua.get = function () { - return parser.getUA(); - }; - $.ua.set = function (uastring) { - parser.setUA(uastring); - var result = parser.getResult(); - for (var prop in result) { - $.ua[prop] = result[prop]; - } - }; - } - -})(typeof window === 'object' ? window : this); - -},{}],19:[function(require,module,exports){ -var v1 = require('./v1'); -var v4 = require('./v4'); - -var uuid = v4; -uuid.v1 = v1; -uuid.v4 = v4; - -module.exports = uuid; - -},{"./v1":22,"./v4":23}],20:[function(require,module,exports){ -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = []; -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1); -} - -function bytesToUuid(buf, offset) { - var i = offset || 0; - var bth = byteToHex; - return bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]]; -} - -module.exports = bytesToUuid; - -},{}],21:[function(require,module,exports){ -// Unique ID creation requires a high quality random # generator. In the -// browser this is a little complicated due to unknown quality of Math.random() -// and inconsistent support for the `crypto` API. We do the best we can via -// feature-detection - -// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. -var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) || - (typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto)); -if (getRandomValues) { - // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto - var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef - - module.exports = function whatwgRNG() { - getRandomValues(rnds8); - return rnds8; - }; -} else { - // Math.random()-based (RNG) - // - // If all else fails, use Math.random(). It's fast, but is of unspecified - // quality. - var rnds = new Array(16); - - module.exports = function mathRNG() { - for (var i = 0, r; i < 16; i++) { - if ((i & 0x03) === 0) r = Math.random() * 0x100000000; - rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; - } - - return rnds; - }; -} - -},{}],22:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); - -// **`v1()` - Generate time-based UUID** -// -// Inspired by https://github.com/LiosK/UUID.js -// and http://docs.python.org/library/uuid.html - -var _nodeId; -var _clockseq; - -// Previous uuid creation time -var _lastMSecs = 0; -var _lastNSecs = 0; - -// See https://github.com/broofa/node-uuid for API details -function v1(options, buf, offset) { - var i = buf && offset || 0; - var b = buf || []; - - options = options || {}; - var node = options.node || _nodeId; - var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; - - // node and clockseq need to be initialized to random values if they're not - // specified. We do this lazily to minimize issues related to insufficient - // system entropy. See #189 - if (node == null || clockseq == null) { - var seedBytes = rng(); - if (node == null) { - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - node = _nodeId = [ - seedBytes[0] | 0x01, - seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] - ]; - } - if (clockseq == null) { - // Per 4.2.2, randomize (14 bit) clockseq - clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; - } - } - - // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); - - // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; - - // Time since last uuid creation (in msecs) - var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; - - // Per 4.2.1.2, Bump clockseq on clock regression - if (dt < 0 && options.clockseq === undefined) { - clockseq = clockseq + 1 & 0x3fff; - } - - // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { - nsecs = 0; - } - - // Per 4.2.1.2 Throw error if too many uuids are requested - if (nsecs >= 10000) { - throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; - - // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - msecs += 12219292800000; - - // `time_low` - var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; - - // `time_mid` - var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; - - // `time_high_and_version` - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - b[i++] = tmh >>> 16 & 0xff; - - // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - b[i++] = clockseq >>> 8 | 0x80; - - // `clock_seq_low` - b[i++] = clockseq & 0xff; - - // `node` - for (var n = 0; n < 6; ++n) { - b[i + n] = node[n]; - } - - return buf ? buf : bytesToUuid(b); -} - -module.exports = v1; - -},{"./lib/bytesToUuid":20,"./lib/rng":21}],23:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); - -function v4(options, buf, offset) { - var i = buf && offset || 0; - - if (typeof(options) == 'string') { - buf = options === 'binary' ? new Array(16) : null; - options = null; - } - options = options || {}; - - var rnds = options.random || (options.rng || rng)(); - - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = (rnds[6] & 0x0f) | 0x40; - rnds[8] = (rnds[8] & 0x3f) | 0x80; - - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ++ii) { - buf[i + ii] = rnds[ii]; - } - } - - return buf || bytesToUuid(rnds); -} - -module.exports = v4; - -},{"./lib/bytesToUuid":20,"./lib/rng":21}],24:[function(require,module,exports){ -/* -WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based -on @visionmedia's Emitter from UI Kit. - -Why? I wanted it standalone. - -I also wanted support for wildcard emitters like this: - -emitter.on('*', function (eventName, other, event, payloads) { - -}); - -emitter.on('somenamespace*', function (eventName, payloads) { - -}); - -Please note that callbacks triggered by wildcard registered events also get -the event name as the first argument. -*/ - -module.exports = WildEmitter; - -function WildEmitter() { } - -WildEmitter.mixin = function (constructor) { - var prototype = constructor.prototype || constructor; - - prototype.isWildEmitter= true; - - // Listen on the given `event` with `fn`. Store a group name if present. - prototype.on = function (event, groupName, fn) { - this.callbacks = this.callbacks || {}; - var hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - func._groupName = group; - (this.callbacks[event] = this.callbacks[event] || []).push(func); - return this; - }; - - // Adds an `event` listener that will be invoked a single - // time then automatically removed. - prototype.once = function (event, groupName, fn) { - var self = this, - hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - function on() { - self.off(event, on); - func.apply(this, arguments); - } - this.on(event, group, on); - return this; - }; - - // Unbinds an entire group - prototype.releaseGroup = function (groupName) { - this.callbacks = this.callbacks || {}; - var item, i, len, handlers; - for (item in this.callbacks) { - handlers = this.callbacks[item]; - for (i = 0, len = handlers.length; i < len; i++) { - if (handlers[i]._groupName === groupName) { - //console.log('removing'); - // remove it and shorten the array we're looping through - handlers.splice(i, 1); - i--; - len--; - } - } - } - return this; - }; - - // Remove the given callback for `event` or all - // registered callbacks. - prototype.off = function (event, fn) { - this.callbacks = this.callbacks || {}; - var callbacks = this.callbacks[event], - i; - - if (!callbacks) return this; - - // remove all handlers - if (arguments.length === 1) { - delete this.callbacks[event]; - return this; - } - - // remove specific handler - i = callbacks.indexOf(fn); - callbacks.splice(i, 1); - if (callbacks.length === 0) { - delete this.callbacks[event]; - } - return this; - }; - - /// Emit `event` with the given args. - // also calls any `*` handlers - prototype.emit = function (event) { - this.callbacks = this.callbacks || {}; - var args = [].slice.call(arguments, 1), - callbacks = this.callbacks[event], - specialCallbacks = this.getWildcardCallbacks(event), - i, - len, - item, - listeners; - - if (callbacks) { - listeners = callbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, args); - } - } - - if (specialCallbacks) { - len = specialCallbacks.length; - listeners = specialCallbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, [event].concat(args)); - } - } - - return this; - }; - - // Helper for for finding special wildcard event handlers that match the event - prototype.getWildcardCallbacks = function (eventName) { - this.callbacks = this.callbacks || {}; - var item, - split, - result = []; - - for (item in this.callbacks) { - split = item.split('*'); - if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { - result = result.concat(this.callbacks[item]); - } - } - return result; - }; - -}; - -WildEmitter.mixin(WildEmitter); - -},{}],25:[function(require,module,exports){ -/*! - * EventEmitter v5.2.4 - git.io/ee - * Unlicense - http://unlicense.org/ - * Oliver Caldwell - http://oli.me.uk/ - * @preserve - */ - -;(function (exports) { - 'use strict'; - - /** - * Class for managing events. - * Can be extended to provide event functionality in other classes. - * - * @class EventEmitter Manages event registering and emitting. - */ - function EventEmitter() {} - - // Shortcuts to improve speed and size - var proto = EventEmitter.prototype; - var originalGlobalValue = exports.EventEmitter; - - /** - * Finds the index of the listener for the event in its storage array. - * - * @param {Function[]} listeners Array of listeners to search through. - * @param {Function} listener Method to look for. - * @return {Number} Index of the specified listener, -1 if not found - * @api private - */ - function indexOfListener(listeners, listener) { - var i = listeners.length; - while (i--) { - if (listeners[i].listener === listener) { - return i; - } - } - - return -1; - } - - /** - * Alias a method while keeping the context correct, to allow for overwriting of target method. - * - * @param {String} name The name of the target method. - * @return {Function} The aliased method - * @api private - */ - function alias(name) { - return function aliasClosure() { - return this[name].apply(this, arguments); - }; - } - - /** - * Returns the listener array for the specified event. - * Will initialise the event object and listener arrays if required. - * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. - * Each property in the object response is an array of listener functions. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Function[]|Object} All listener functions for the event. - */ - proto.getListeners = function getListeners(evt) { - var events = this._getEvents(); - var response; - var key; - - // Return a concatenated array of all matching events if - // the selector is a regular expression. - if (evt instanceof RegExp) { - response = {}; - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - response[key] = events[key]; - } - } - } - else { - response = events[evt] || (events[evt] = []); - } - - return response; - }; - - /** - * Takes a list of listener objects and flattens it into a list of listener functions. - * - * @param {Object[]} listeners Raw listener objects. - * @return {Function[]} Just the listener functions. - */ - proto.flattenListeners = function flattenListeners(listeners) { - var flatListeners = []; - var i; - - for (i = 0; i < listeners.length; i += 1) { - flatListeners.push(listeners[i].listener); - } - - return flatListeners; - }; - - /** - * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Object} All listener functions for an event in an object. - */ - proto.getListenersAsObject = function getListenersAsObject(evt) { - var listeners = this.getListeners(evt); - var response; - - if (listeners instanceof Array) { - response = {}; - response[evt] = listeners; - } - - return response || listeners; - }; - - function isValidListener (listener) { - if (typeof listener === 'function' || listener instanceof RegExp) { - return true - } else if (listener && typeof listener === 'object') { - return isValidListener(listener.listener) - } else { - return false - } - } - - /** - * Adds a listener function to the specified event. - * The listener will not be added if it is a duplicate. - * If the listener returns true then it will be removed after it is called. - * If you pass a regular expression as the event name then the listener will be added to all events that match it. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListener = function addListener(evt, listener) { - if (!isValidListener(listener)) { - throw new TypeError('listener must be a function'); - } - - var listeners = this.getListenersAsObject(evt); - var listenerIsWrapped = typeof listener === 'object'; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { - listeners[key].push(listenerIsWrapped ? listener : { - listener: listener, - once: false - }); - } - } - - return this; - }; - - /** - * Alias of addListener - */ - proto.on = alias('addListener'); - - /** - * Semi-alias of addListener. It will add a listener that will be - * automatically removed after its first execution. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addOnceListener = function addOnceListener(evt, listener) { - return this.addListener(evt, { - listener: listener, - once: true - }); - }; - - /** - * Alias of addOnceListener. - */ - proto.once = alias('addOnceListener'); - - /** - * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. - * You need to tell it what event names should be matched by a regex. - * - * @param {String} evt Name of the event to create. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvent = function defineEvent(evt) { - this.getListeners(evt); - return this; - }; - - /** - * Uses defineEvent to define multiple events. - * - * @param {String[]} evts An array of event names to define. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvents = function defineEvents(evts) { - for (var i = 0; i < evts.length; i += 1) { - this.defineEvent(evts[i]); - } - return this; - }; - - /** - * Removes a listener function from the specified event. - * When passed a regular expression as the event name, it will remove the listener from all events that match it. - * - * @param {String|RegExp} evt Name of the event to remove the listener from. - * @param {Function} listener Method to remove from the event. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListener = function removeListener(evt, listener) { - var listeners = this.getListenersAsObject(evt); - var index; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key)) { - index = indexOfListener(listeners[key], listener); - - if (index !== -1) { - listeners[key].splice(index, 1); - } - } - } - - return this; - }; - - /** - * Alias of removeListener - */ - proto.off = alias('removeListener'); - - /** - * Adds listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. - * You can also pass it a regular expression to add the array of listeners to all events that match it. - * Yeah, this function does quite a bit. That's probably a bad thing. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListeners = function addListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(false, evt, listeners); - }; - - /** - * Removes listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be removed. - * You can also pass it a regular expression to remove the listeners from all events that match it. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListeners = function removeListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(true, evt, listeners); - }; - - /** - * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. - * The first argument will determine if the listeners are removed (true) or added (false). - * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be added/removed. - * You can also pass it a regular expression to manipulate the listeners of all events that match it. - * - * @param {Boolean} remove True if you want to remove listeners, false if you want to add. - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add/remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { - var i; - var value; - var single = remove ? this.removeListener : this.addListener; - var multiple = remove ? this.removeListeners : this.addListeners; - - // If evt is an object then pass each of its properties to this method - if (typeof evt === 'object' && !(evt instanceof RegExp)) { - for (i in evt) { - if (evt.hasOwnProperty(i) && (value = evt[i])) { - // Pass the single listener straight through to the singular method - if (typeof value === 'function') { - single.call(this, i, value); - } - else { - // Otherwise pass back to the multiple function - multiple.call(this, i, value); - } - } - } - } - else { - // So evt must be a string - // And listeners must be an array of listeners - // Loop over it and pass each one to the multiple method - i = listeners.length; - while (i--) { - single.call(this, evt, listeners[i]); - } - } - - return this; - }; - - /** - * Removes all listeners from a specified event. - * If you do not specify an event then all listeners will be removed. - * That means every event will be emptied. - * You can also pass a regex to remove all events that match it. - * - * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeEvent = function removeEvent(evt) { - var type = typeof evt; - var events = this._getEvents(); - var key; - - // Remove different things depending on the state of evt - if (type === 'string') { - // Remove all listeners for the specified event - delete events[evt]; - } - else if (evt instanceof RegExp) { - // Remove all events matching the regex. - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - delete events[key]; - } - } - } - else { - // Remove all listeners in all events - delete this._events; - } - - return this; - }; - - /** - * Alias of removeEvent. - * - * Added to mirror the node API. - */ - proto.removeAllListeners = alias('removeEvent'); - - /** - * Emits an event of your choice. - * When emitted, every listener attached to that event will be executed. - * If you pass the optional argument array then those arguments will be passed to every listener upon execution. - * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. - * So they will not arrive within the array on the other side, they will be separate. - * You can also pass a regular expression to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {Array} [args] Optional array of arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emitEvent = function emitEvent(evt, args) { - var listenersMap = this.getListenersAsObject(evt); - var listeners; - var listener; - var i; - var key; - var response; - - for (key in listenersMap) { - if (listenersMap.hasOwnProperty(key)) { - listeners = listenersMap[key].slice(0); - - for (i = 0; i < listeners.length; i++) { - // If the listener returns true then it shall be removed from the event - // The function is executed either with a basic call or an apply if there is an args array - listener = listeners[i]; - - if (listener.once === true) { - this.removeListener(evt, listener.listener); - } - - response = listener.listener.apply(this, args || []); - - if (response === this._getOnceReturnValue()) { - this.removeListener(evt, listener.listener); - } - } - } - } - - return this; - }; - - /** - * Alias of emitEvent - */ - proto.trigger = alias('emitEvent'); - - /** - * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. - * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {...*} Optional additional arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emit = function emit(evt) { - var args = Array.prototype.slice.call(arguments, 1); - return this.emitEvent(evt, args); - }; - - /** - * Sets the current value to check against when executing listeners. If a - * listeners return value matches the one set here then it will be removed - * after execution. This value defaults to true. - * - * @param {*} value The new value to check for when executing listeners. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.setOnceReturnValue = function setOnceReturnValue(value) { - this._onceReturnValue = value; - return this; - }; - - /** - * Fetches the current value to check against when executing listeners. If - * the listeners return value matches this one then it should be removed - * automatically. It will return true by default. - * - * @return {*|Boolean} The current value to check for or the default, true. - * @api private - */ - proto._getOnceReturnValue = function _getOnceReturnValue() { - if (this.hasOwnProperty('_onceReturnValue')) { - return this._onceReturnValue; - } - else { - return true; - } - }; - - /** - * Fetches the events object and creates one if required. - * - * @return {Object} The events storage object. - * @api private - */ - proto._getEvents = function _getEvents() { - return this._events || (this._events = {}); - }; - - /** - * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. - * - * @return {Function} Non conflicting EventEmitter class. - */ - EventEmitter.noConflict = function noConflict() { - exports.EventEmitter = originalGlobalValue; - return EventEmitter; - }; - - // Expose the class either via AMD, CommonJS or the global object - if (typeof define === 'function' && define.amd) { - define(function () { - return EventEmitter; - }); - } - else if (typeof module === 'object' && module.exports){ - module.exports = EventEmitter; - } - else { - exports.EventEmitter = EventEmitter; - } -}(this || {})); - -},{}],26:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var OpenVidu_1 = require("./OpenVidu/OpenVidu"); -if (window) { - window['OpenVidu'] = OpenVidu_1.OpenVidu; -} - -},{"./OpenVidu/OpenVidu":29}],27:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Stream_1 = require("./Stream"); -var Connection = (function () { - function Connection(session, opts) { - this.session = session; - this.disposed = false; - var msg = "'Connection' created "; - if (!!opts) { - msg += "(remote) with 'connectionId' [" + opts.id + ']'; - } - else { - msg += '(local)'; - } - console.info(msg); - this.options = opts; - if (!!opts) { - this.connectionId = opts.id; - if (opts.metadata) { - this.data = opts.metadata; - } - if (opts.streams) { - this.initRemoteStreams(opts.streams); - } - } - this.creationTime = new Date().getTime(); - } - Connection.prototype.sendIceCandidate = function (candidate) { - console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate)); - this.session.openvidu.sendRequest('onIceCandidate', { - endpointName: this.connectionId, - candidate: candidate.candidate, - sdpMid: candidate.sdpMid, - sdpMLineIndex: candidate.sdpMLineIndex - }, function (error, response) { - if (error) { - console.error('Error sending ICE candidate: ' - + JSON.stringify(error)); - } - }); - }; - Connection.prototype.initRemoteStreams = function (options) { - var _this = this; - options.forEach(function (opts) { - var streamOptions = { - id: opts.id, - connection: _this, - frameRate: opts.frameRate, - recvAudio: opts.audioActive, - recvVideo: opts.videoActive, - typeOfVideo: opts.typeOfVideo - }; - var stream = new Stream_1.Stream(_this.session, streamOptions); - _this.addStream(stream); - }); - console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); - }; - Connection.prototype.addStream = function (stream) { - stream.connection = this; - this.stream = stream; - }; - Connection.prototype.removeStream = function (streamId) { - delete this.stream; - }; - Connection.prototype.dispose = function () { - if (!!this.stream) { - delete this.stream; - } - this.disposed = true; - }; - return Connection; -}()); -exports.Connection = Connection; - -},{"./Stream":32}],28:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState"); -var LocalRecorder = (function () { - function LocalRecorder(stream) { - this.stream = stream; - this.chunks = []; - this.count = 0; - this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; - this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; - this.state = LocalRecorderState_1.LocalRecorderState.READY; - } - LocalRecorder.prototype.record = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (typeof MediaRecorder === 'undefined') { - console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); - throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); - } - if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) { - throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); - } - console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'"); - if (typeof MediaRecorder.isTypeSupported === 'function') { - var options = void 0; - if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { - options = { mimeType: 'video/webm;codecs=vp9' }; - } - else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { - options = { mimeType: 'video/webm;codecs=h264' }; - } - else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { - options = { mimeType: 'video/webm;codecs=vp8' }; - } - console.log('Using mimeType ' + options.mimeType); - _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options); - } - else { - console.warn('isTypeSupported is not supported, using default codecs for browser'); - _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream()); - } - _this.mediaRecorder.start(10); - } - catch (err) { - reject(err); - } - _this.mediaRecorder.ondataavailable = function (e) { - _this.chunks.push(e.data); - }; - _this.mediaRecorder.onerror = function (e) { - console.error('MediaRecorder error: ', e); - }; - _this.mediaRecorder.onstart = function () { - console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - }; - _this.mediaRecorder.onpause = function () { - console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onresume = function () { - console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onwarning = function (e) { - console.log('MediaRecorder warning: ' + e); - }; - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - resolve(); - }); - }; - LocalRecorder.prototype.stop = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before')); - } - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - resolve(); - }; - _this.mediaRecorder.stop(); - } - catch (e) { - reject(e); - } - }); - }; - LocalRecorder.prototype.pause = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) { - reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before')); - } - _this.mediaRecorder.pause(); - _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED; - } - catch (error) { - reject(error); - } - }); - }; - LocalRecorder.prototype.resume = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) { - throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before')); - } - _this.mediaRecorder.resume(); - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - } - catch (error) { - reject(error); - } - }); - }; - LocalRecorder.prototype.preview = function (parentElement) { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - this.videoPreview = document.createElement('video'); - this.videoPreview.id = this.id; - this.videoPreview.autoplay = true; - if (typeof parentElement === 'string') { - this.htmlParentElementId = parentElement; - var parentElementDom = document.getElementById(parentElement); - if (parentElementDom) { - this.videoPreview = parentElementDom.appendChild(this.videoPreview); - } - } - else { - this.htmlParentElementId = parentElement.id; - this.videoPreview = parentElement.appendChild(this.videoPreview); - } - this.videoPreview.src = this.videoPreviewSrc; - return this.videoPreview; - }; - LocalRecorder.prototype.clean = function () { - var _this = this; - var f = function () { - delete _this.blob; - _this.chunks = []; - _this.count = 0; - delete _this.mediaRecorder; - _this.state = LocalRecorderState_1.LocalRecorderState.READY; - }; - if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) { - this.stop().then(function () { return f(); }).catch(function () { return f(); }); - } - else { - f(); - } - }; - LocalRecorder.prototype.download = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var a = document.createElement('a'); - a.style.display = 'none'; - document.body.appendChild(a); - var url = window.URL.createObjectURL(this.blob); - a.href = url; - a.download = this.id + '.webm'; - a.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(a); - } - }; - LocalRecorder.prototype.getBlob = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); - } - else { - return this.blob; - } - }; - LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_1 = new XMLHttpRequest(); - http_1.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_1.setRequestHeader(key, headers[key]); - } - } - http_1.onreadystatechange = function () { - if (http_1.readyState === 4) { - if (http_1.status.toString().charAt(0) === '2') { - resolve(http_1.responseText); - } - else { - reject(http_1.status); - } - } - }; - http_1.send(_this.blob); - } - }); - }; - LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_2 = new XMLHttpRequest(); - http_2.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_2.setRequestHeader(key, headers[key]); - } - } - var sendable = new FormData(); - sendable.append('file', _this.blob, _this.id + '.webm'); - http_2.onreadystatechange = function () { - if (http_2.readyState === 4) { - if (http_2.status.toString().charAt(0) === '2') { - resolve(http_2.responseText); - } - else { - reject(http_2.status); - } - } - }; - http_2.send(sendable); - } - }); - }; - LocalRecorder.prototype.onStopDefault = function () { - console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')'); - this.blob = new Blob(this.chunks, { type: 'video/webm' }); - this.chunks = []; - this.videoPreviewSrc = window.URL.createObjectURL(this.blob); - this.state = LocalRecorderState_1.LocalRecorderState.FINISHED; - }; - return LocalRecorder; -}()); -exports.LocalRecorder = LocalRecorder; - -},{"../OpenViduInternal/Enums/LocalRecorderState":35}],29:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorder_1 = require("./LocalRecorder"); -var Publisher_1 = require("./Publisher"); -var Session_1 = require("./Session"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); -var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); -var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); -var platform = require("platform"); -var OpenVidu = (function () { - function OpenVidu() { - this.secret = ''; - this.recorder = false; - this.advancedConfiguration = {}; - console.info("'OpenVidu' initialized"); - } - OpenVidu.prototype.initSession = function () { - this.session = new Session_1.Session(this); - return this.session; - }; - OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) { - var properties; - if (!!param2 && (typeof param2 !== 'function')) { - properties = param2; - properties = { - audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, - frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), - insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, - publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, - publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, - resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), - videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: true, - publishAudio: true, - publishVideo: true, - resolution: '640x480' - }; - } - var publisher = new Publisher_1.Publisher(targetElement, properties, this); - var completionHandler; - if (!!param2 && (typeof param2 === 'function')) { - completionHandler = param2; - } - else if (!!param3) { - completionHandler = param3; - } - publisher.initialize() - .then(function () { - if (completionHandler !== undefined) { - completionHandler(undefined); - } - publisher.emitEvent('accessAllowed', []); - }).catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - publisher.emitEvent('accessDenied', []); - }); - return publisher; - }; - OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - var publisher; - var callback = function (error) { - if (!!error) { - reject(error); - } - else { - resolve(publisher); - } - }; - if (!!properties) { - publisher = _this.initPublisher(targetElement, properties, callback); - } - else { - publisher = _this.initPublisher(targetElement, callback); - } - }); - }; - OpenVidu.prototype.initLocalRecorder = function (stream) { - return new LocalRecorder_1.LocalRecorder(stream); - }; - OpenVidu.prototype.checkSystemRequirements = function () { - var browser = platform.name; - var version = platform.version; - if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') && - (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') && - (browser !== 'Opera') && (browser !== 'Opera Mobile') && - (browser !== 'Safari')) { - return 0; - } - else { - return 1; - } - }; - OpenVidu.prototype.getDevices = function () { - return new Promise(function (resolve, reject) { - navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { - var devices = []; - deviceInfos.forEach(function (deviceInfo) { - if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { - devices.push({ - kind: deviceInfo.kind, - deviceId: deviceInfo.deviceId, - label: deviceInfo.label - }); - } - }); - resolve(devices); - }).catch(function (error) { - console.error('Error getting devices', error); - reject(error); - }); - }); - }; - OpenVidu.prototype.getUserMedia = function (options) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.generateMediaConstraints(options) - .then(function (constraints) { - navigator.mediaDevices.getUserMedia(constraints) - .then(function (mediaStream) { - resolve(mediaStream); - }) - .catch(function (error) { - var errorName; - var errorMessage = error.toString(); - if (!(options.videoSource === 'screen')) { - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; - } - reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - }) - .catch(function (error) { - reject(error); - }); - }); - }; - OpenVidu.prototype.enableProdMode = function () { - console.log = function () { }; - console.debug = function () { }; - console.info = function () { }; - console.warn = function () { }; - }; - OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { - this.advancedConfiguration = configuration; - }; - OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { - var _this = this; - return new Promise(function (resolve, reject) { - var audio, video; - if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) { - audio = false; - } - else if (publisherProperties.audioSource === undefined) { - audio = true; - } - else { - audio = publisherProperties.audioSource; - } - if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) { - video = false; - } - else { - video = { - height: { - ideal: 480 - }, - width: { - ideal: 640 - } - }; - } - var mediaConstraints = { - audio: audio, - video: video - }; - if (typeof mediaConstraints.audio === 'string') { - mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } }; - } - if (mediaConstraints.video) { - if (!!publisherProperties.resolution) { - var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); - var width = Number(widthAndHeight[0]); - var height = Number(widthAndHeight[1]); - mediaConstraints.video.width.ideal = width; - mediaConstraints.video.height.ideal = height; - } - if (!!publisherProperties.frameRate) { - mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate }; - } - if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') { - if (publisherProperties.videoSource === 'screen') { - if (platform.name !== 'Chrome' && platform.name !== 'Firefox') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); - console.error(error); - reject(error); - } - else { - if (!!_this.advancedConfiguration.screenShareChromeExtension) { - var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); - screenSharing.getChromeExtensionStatus(extensionId, function (status) { - if (status === 'installed-enabled') { - screenSharing.getScreenConstraints(function (error, screenConstraints) { - if (!!error && error === 'permission-denied') { - var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - console.error(error_1); - reject(error_1); - } - else { - mediaConstraints.video = screenConstraints; - resolve(mediaConstraints); - } - }); - } - if (status === 'installed-disabled') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - console.error(error); - reject(error); - } - if (status === 'not-installed') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); - console.error(error); - reject(error); - } - }); - } - else { - screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { - if (!!error) { - if (error === 'not-installed') { - var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); - console.error(error_2); - reject(error_2); - } - else if (error === 'installed-disabled') { - var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - console.error(error_3); - reject(error_3); - } - else if (error === 'permission-denied') { - var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - console.error(error_4); - reject(error_4); - } - } - else { - mediaConstraints.video = screenConstraints.video; - resolve(mediaConstraints); - } - }); - } - publisherProperties.videoSource = 'screen'; - } - } - else { - mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource }; - resolve(mediaConstraints); - } - } - else { - resolve(mediaConstraints); - } - } - else { - resolve(mediaConstraints); - } - }); - }; - OpenVidu.prototype.startWs = function (onConnectSucces) { - var config = { - heartbeat: 5000, - sendCloseMessage: false, - ws: { - uri: this.wsUri, - useSockJS: false, - onconnected: onConnectSucces, - ondisconnect: this.disconnectCallback.bind(this), - onreconnecting: this.reconnectingCallback.bind(this), - onreconnected: this.reconnectedCallback.bind(this) - }, - rpc: { - requestTimeout: 15000, - participantJoined: this.session.onParticipantJoined.bind(this.session), - participantPublished: this.session.onParticipantPublished.bind(this.session), - participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), - participantLeft: this.session.onParticipantLeft.bind(this.session), - participantEvicted: this.session.onParticipantEvicted.bind(this.session), - recordingStarted: this.session.onRecordingStarted.bind(this.session), - recordingStopped: this.session.onRecordingStopped.bind(this.session), - sendMessage: this.session.onNewMessage.bind(this.session), - iceCandidate: this.session.recvIceCandidate.bind(this.session), - mediaError: this.session.onMediaError.bind(this.session) - } - }; - this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); - }; - OpenVidu.prototype.closeWs = function () { - this.jsonRpcClient.close(); - }; - OpenVidu.prototype.sendRequest = function (method, params, callback) { - if (params && params instanceof Function) { - callback = params; - params = {}; - } - console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); - this.jsonRpcClient.send(method, params, callback); - }; - OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) { - var is = (!!mediaSource && - mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' && - mediaSource.id !== undefined && typeof mediaSource.id === 'string' && - mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' && - mediaSource.label !== undefined && typeof mediaSource.label === 'string' && - mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' && - mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string'); - return is; - }; - OpenVidu.prototype.getWsUri = function () { - return this.wsUri; - }; - OpenVidu.prototype.getSecret = function () { - return this.secret; - }; - OpenVidu.prototype.getRecorder = function () { - return this.recorder; - }; - OpenVidu.prototype.disconnectCallback = function () { - console.warn('Websocket connection lost'); - if (this.isRoomAvailable()) { - this.session.onLostConnection(); - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.reconnectingCallback = function () { - console.warn('Websocket connection lost (reconnecting)'); - if (this.isRoomAvailable()) { - this.session.onLostConnection(); - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.reconnectedCallback = function () { - console.warn('Websocket reconnected'); - }; - OpenVidu.prototype.isRoomAvailable = function () { - if (this.session !== undefined && this.session instanceof Session_1.Session) { - return true; - } - else { - console.warn('Session instance not found'); - return false; - } - }; - return OpenVidu; -}()); -exports.OpenVidu = OpenVidu; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":52,"../OpenViduInternal/ScreenSharing/Screen-Capturing":59,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":58,"./LocalRecorder":28,"./Publisher":30,"./Session":31,"platform":9}],30:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Session_1 = require("./Session"); -var Stream_1 = require("./Stream"); -var StreamManager_1 = require("./StreamManager"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var Publisher = (function (_super) { - __extends(Publisher, _super); - function Publisher(targEl, properties, openvidu) { - var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this; - _this.openvidu = openvidu; - _this.accessAllowed = false; - _this.isSubscribedToRemote = false; - _this.accessDenied = false; - _this.properties = properties; - _this.stream.ee.on('local-stream-destroyed-by-disconnect', function (reason) { - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - }); - return _this; - } - Publisher.prototype.publishAudio = function (value) { - this.stream.getWebRtcPeer().audioEnabled = value; - console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream'); - }; - Publisher.prototype.publishVideo = function (value) { - this.stream.getWebRtcPeer().videoEnabled = value; - console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream'); - }; - Publisher.prototype.subscribeToRemote = function (value) { - value = (value !== undefined) ? value : true; - this.isSubscribedToRemote = value; - this.stream.subscribeToMyRemote(value); - }; - Publisher.prototype.on = function (type, handler) { - var _this = this; - _super.prototype.on.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.on('stream-created-by-publisher', function () { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'remoteVideoPlaying') { - if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.ee.emitEvent('accessAllowed'); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.ee.emitEvent('accessDenied'); - } - } - return this; - }; - Publisher.prototype.once = function (type, handler) { - var _this = this; - _super.prototype.once.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.once('stream-created-by-publisher', function () { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'remoteVideoPlaying') { - if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.ee.emitEvent('accessAllowed'); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.ee.emitEvent('accessDenied'); - } - } - return this; - }; - Publisher.prototype.initialize = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var errorCallback = function (openViduError) { - _this.accessDenied = true; - _this.accessAllowed = false; - reject(openViduError); - }; - var successCallback = function (mediaStream) { - _this.accessAllowed = true; - _this.accessDenied = false; - if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) { - mediaStream.removeTrack(mediaStream.getAudioTracks()[0]); - mediaStream.addTrack(_this.properties.audioSource); - } - if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) { - mediaStream.removeTrack(mediaStream.getVideoTracks()[0]); - mediaStream.addTrack(_this.properties.videoSource); - } - if (!!mediaStream.getAudioTracks()[0]) { - mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; - } - if (!!mediaStream.getVideoTracks()[0]) { - mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; - } - _this.stream.setMediaStream(mediaStream); - if (!_this.stream.displayMyRemote()) { - _this.stream.updateMediaStreamInVideos(); - } - _this.stream.isLocalStreamReadyToPublish = true; - _this.stream.ee.emitEvent('stream-ready-to-publish', []); - if (!!_this.firstVideoElement) { - _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode); - } - delete _this.firstVideoElement; - resolve(); - }; - _this.openvidu.generateMediaConstraints(_this.properties) - .then(function (constraints) { - var outboundStreamOptions = { - mediaConstraints: constraints, - publisherProperties: _this.properties - }; - _this.stream.setOutboundStreamOptions(outboundStreamOptions); - var constraintsAux = {}; - var timeForDialogEvent = 1250; - if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) { - var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio); - constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1; - constraintsAux.video = constraints.video; - var startTime_1 = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (mediaStream) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) { - constraintsAux.audio = definedAudioConstraint_1; - constraintsAux.video = false; - startTime_1 = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (audioOnlyStream) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); - successCallback(mediaStream); - }) - .catch(function (error) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'notallowederror': - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'overconstrainederror': - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - } - }); - } - else { - successCallback(mediaStream); - } - }) - .catch(function (error) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - case 'notallowederror': - errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'overconstrainederror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - } - }); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'")); - } - }) - .catch(function (error) { - errorCallback(error); - }); - }); - }; - Publisher.prototype.updateSession = function (session) { - this.session = session; - this.stream.session = session; - }; - Publisher.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - Publisher.prototype.reestablishStreamPlayingEvent = function () { - if (this.ee.getListeners('streamPlaying').length > 0) { - this.addPlayEventToFirstVideo(); - } - }; - Publisher.prototype.setPermissionDialogTimer = function (waitTime) { - var _this = this; - this.permissionDialogTimeout = setTimeout(function () { - _this.ee.emitEvent('accessDialogOpened', []); - }, waitTime); - }; - Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) { - clearTimeout(this.permissionDialogTimeout); - if ((Date.now() - startTime) > waitTime) { - this.ee.emitEvent('accessDialogClosed', []); - } - }; - return Publisher; -}(StreamManager_1.StreamManager)); -exports.Publisher = Publisher; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Events/StreamEvent":44,"../OpenViduInternal/Events/VideoElementEvent":46,"./Session":31,"./Stream":32,"./StreamManager":33}],31:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Connection_1 = require("./Connection"); -var Subscriber_1 = require("./Subscriber"); -var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent"); -var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent"); -var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); -var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var platform = require("platform"); -var EventEmitter = require("wolfy87-eventemitter"); -var Session = (function () { - function Session(openvidu) { - this.streamManagers = []; - this.remoteStreamsCreated = {}; - this.remoteConnections = {}; - this.speakingEventsEnabled = false; - this.ee = new EventEmitter(); - this.openvidu = openvidu; - } - Session.prototype.connect = function (token, metadata) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.processToken(token); - if (_this.openvidu.checkSystemRequirements()) { - _this.options = { - sessionId: _this.sessionId, - participantId: token, - metadata: !!metadata ? _this.stringClientMetadata(metadata) : '' - }; - _this.connectAux(token).then(function () { - resolve(); - }).catch(function (error) { - reject(error); - }); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu')); - } - }); - }; - Session.prototype.disconnect = function () { - this.leave(false, 'disconnect'); - }; - Session.prototype.subscribe = function (stream, targetElement, param3, param4) { - var properties = {}; - if (!!param3 && typeof param3 !== 'function') { - properties = { - insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, - subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: true, - subscribeToVideo: true - }; - } - var completionHandler; - if (!!param3 && (typeof param3 === 'function')) { - completionHandler = param3; - } - else if (!!param4) { - completionHandler = param4; - } - console.info('Subscribing to ' + stream.connection.connectionId); - stream.subscribe() - .then(function () { - console.info('Subscribed correctly to ' + stream.connection.connectionId); - if (completionHandler !== undefined) { - completionHandler(undefined); - } - }) - .catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - }); - var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties); - if (!!subscriber.targetElement) { - stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode); - } - return subscriber; - }; - Session.prototype.subscribeAsync = function (stream, targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - var subscriber; - var callback = function (error) { - if (!!error) { - reject(error); - } - else { - resolve(subscriber); - } - }; - if (!!properties) { - subscriber = _this.subscribe(stream, targetElement, properties, callback); - } - else { - subscriber = _this.subscribe(stream, targetElement, callback); - } - }); - }; - Session.prototype.unsubscribe = function (subscriber) { - var connectionId = subscriber.stream.connection.connectionId; - console.info('Unsubscribing from ' + connectionId); - this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { - if (error) { - console.error('Error unsubscribing from ' + connectionId, error); - } - else { - console.info('Unsubscribed correctly from ' + connectionId); - } - subscriber.stream.disposeWebRtcPeer(); - subscriber.stream.disposeMediaStream(); - }); - subscriber.stream.streamManager.removeAllVideos(); - }; - Session.prototype.publish = function (publisher) { - var _this = this; - return new Promise(function (resolve, reject) { - publisher.session = _this; - publisher.stream.session = _this; - if (!publisher.stream.isLocalStreamPublished) { - _this.connection.addStream(publisher.stream); - publisher.stream.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - } - else { - publisher.initialize() - .then(function () { - _this.connection.addStream(publisher.stream); - publisher.reestablishStreamPlayingEvent(); - publisher.stream.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }).catch(function (error) { - reject(error); - }); - } - }); - }; - Session.prototype.unpublish = function (publisher) { - var stream = publisher.stream; - if (!stream.connection) { - console.error('The associated Connection object of this Publisher is null', stream); - return; - } - else if (stream.connection !== this.connection) { - console.error('The associated Connection object of this Publisher is not your local Connection.' + - "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); - return; - } - else { - console.info('Unpublishing local media (' + stream.connection.connectionId + ')'); - this.openvidu.sendRequest('unpublishVideo', function (error, response) { - if (error) { - console.error(error); - } - else { - console.info('Media unpublished correctly'); - } - }); - stream.disposeWebRtcPeer(); - delete stream.connection.stream; - var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish'); - publisher.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - } - }; - Session.prototype.signal = function (signal) { - var _this = this; - return new Promise(function (resolve, reject) { - var signalMessage = {}; - if (signal.to && signal.to.length > 0) { - var connectionIds_1 = []; - signal.to.forEach(function (connection) { - connectionIds_1.push(connection.connectionId); - }); - signalMessage['to'] = connectionIds_1; - } - else { - signalMessage['to'] = []; - } - signalMessage['data'] = signal.data ? signal.data : ''; - signalMessage['type'] = signal.type ? signal.type : ''; - _this.openvidu.sendRequest('sendMessage', { - message: JSON.stringify(signalMessage) - }, function (error, response) { - if (!!error) { - reject(error); - } - else { - resolve(); - } - }); - }); - }; - Session.prototype.on = function (type, handler) { - this.ee.on(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered by 'Session'", event); - } - else { - console.info("Event '" + type + "' triggered by 'Session'"); - } - handler(event); - }); - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = true; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !str.speechEvent && str.hasAudio) { - str.enableSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.once = function (type, handler) { - this.ee.once(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered by 'Session'", event); - } - else { - console.info("Event '" + type + "' triggered by 'Session'"); - } - handler(event); - }); - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = true; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !str.speechEvent && str.hasAudio) { - str.enableOnceSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.off = function (type, handler) { - if (!handler) { - this.ee.removeAllListeners(type); - } - else { - this.ee.off(type, handler); - } - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = false; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !!str.speechEvent) { - str.disableSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.onParticipantJoined = function (response) { - var _this = this; - this.getConnection(response.id, '') - .then(function (connection) { - console.warn('Connection ' + response.id + ' already exists in connections list'); - }) - .catch(function (openViduError) { - var connection = new Connection_1.Connection(_this, response); - _this.remoteConnections[response.id] = connection; - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - }; - Session.prototype.onParticipantLeft = function (msg) { - var _this = this; - this.getRemoteConnection(msg.name, 'Remote connection ' + msg.name + " unknown when 'onParticipantLeft'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (connection) { - if (!!connection.stream) { - var stream = connection.stream; - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - delete _this.remoteStreamsCreated[stream.streamId]; - } - delete _this.remoteConnections[connection.connectionId]; - _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onParticipantPublished = function (response) { - var _this = this; - var afterConnectionFound = function (connection) { - _this.remoteConnections[connection.connectionId] = connection; - if (!_this.remoteStreamsCreated[connection.stream.streamId]) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]); - } - _this.remoteStreamsCreated[connection.stream.streamId] = true; - }; - var connection; - this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (con) { - connection = con; - response.metadata = con.data; - connection.options = response; - connection.initRemoteStreams(response.streams); - afterConnectionFound(connection); - }) - .catch(function (openViduError) { - connection = new Connection_1.Connection(_this, response); - afterConnectionFound(connection); - }); - }; - Session.prototype.onParticipantUnpublished = function (msg) { - var _this = this; - this.getRemoteConnection(msg.name, "Remote connection '" + msg.name + "' unknown when 'onParticipantUnpublished'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (connection) { - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - var streamId = connection.stream.streamId; - delete _this.remoteStreamsCreated[streamId]; - connection.removeStream(streamId); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onParticipantEvicted = function (msg) { - }; - Session.prototype.onNewMessage = function (msg) { - var _this = this; - console.info('New signal: ' + JSON.stringify(msg)); - this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: " - + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId) - .then(function (connection) { - _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); - _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.recvIceCandidate = function (msg) { - var candidate = { - candidate: msg.candidate, - sdpMid: msg.sdpMid, - sdpMLineIndex: msg.sdpMLineIndex - }; - this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) - .then(function (connection) { - var stream = connection.stream; - stream.getWebRtcPeer().addIceCandidate(candidate, function (error) { - if (error) { - console.error('Error adding candidate for ' + stream.streamId - + ' stream of endpoint ' + msg.endpointName + ': ' + error); - } - }); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onSessionClosed = function (msg) { - console.info('Session closed: ' + JSON.stringify(msg)); - var s = msg.room; - if (s !== undefined) { - this.ee.emitEvent('session-closed', [{ - session: s - }]); - } - else { - console.warn('Session undefined on session closed', msg); - } - }; - Session.prototype.onLostConnection = function () { - if (!this.connection) { - console.warn('Not connected to session: if you are not debugging, this is probably a certificate error'); - var url = 'https://' + this.openvidu.getWsUri().split('wss://')[1].split('/openvidu')[0]; - if (window.confirm('If you are not debugging, this is probably a certificate error at \"' + url + '\"\n\nClick OK to navigate and accept it')) { - location.assign(url + '/accept-certificate'); - } - return; - } - console.warn('Lost connection in Session ' + this.sessionId); - if (!!this.sessionId && !this.connection.disposed) { - this.leave(true, 'networkDisconnect'); - } - }; - Session.prototype.onMediaError = function (params) { - console.error('Media error: ' + JSON.stringify(params)); - var err = params.error; - if (err) { - this.ee.emitEvent('error-media', [{ - error: err - }]); - } - else { - console.warn('Received undefined media error. Params:', params); - } - }; - Session.prototype.onRecordingStarted = function (response) { - this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]); - }; - Session.prototype.onRecordingStopped = function (response) { - this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]); - }; - Session.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - Session.prototype.leave = function (forced, reason) { - var _this = this; - forced = !!forced; - console.info('Leaving Session (forced=' + forced + ')'); - if (!!this.connection) { - if (!this.connection.disposed && !forced) { - this.openvidu.sendRequest('leaveRoom', function (error, response) { - if (error) { - console.error(error); - } - _this.openvidu.closeWs(); - }); - } - else { - this.openvidu.closeWs(); - } - if (!!this.connection.stream) { - this.connection.stream.disposeWebRtcPeer(); - if (this.connection.stream.isLocalStreamPublished) { - this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); - } - } - if (!this.connection.disposed) { - var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason); - this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); - sessionDisconnectEvent.callDefaultBehaviour(); - } - } - else { - console.warn('You were not connected to the session ' + this.sessionId); - } - }; - Session.prototype.connectAux = function (token) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.openvidu.startWs(function (error) { - if (!!error) { - reject(error); - } - else { - var joinParams = { - token: (!!token) ? token : '', - session: _this.sessionId, - metadata: !!_this.options.metadata ? _this.options.metadata : '', - secret: _this.openvidu.getSecret(), - recorder: _this.openvidu.getRecorder(), - }; - _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { - if (!!error) { - reject(error); - } - else { - _this.connection = new Connection_1.Connection(_this); - _this.connection.connectionId = response.id; - _this.connection.data = response.metadata; - var events_1 = { - connections: new Array(), - streams: new Array() - }; - var existingParticipants = response.value; - existingParticipants.forEach(function (participant) { - var connection = new Connection_1.Connection(_this, participant); - _this.remoteConnections[connection.connectionId] = connection; - events_1.connections.push(connection); - if (!!connection.stream) { - _this.remoteStreamsCreated[connection.stream.streamId] = true; - events_1.streams.push(connection.stream); - } - }); - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]); - events_1.connections.forEach(function (connection) { - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - events_1.streams.forEach(function (stream) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]); - }); - resolve(); - } - }); - } - }); - }); - }; - Session.prototype.stringClientMetadata = function (metadata) { - if (typeof metadata !== 'string') { - return JSON.stringify(metadata); - } - else { - return metadata; - } - }; - Session.prototype.getConnection = function (connectionId, errorMessage) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections[connectionId]; - if (!!connection) { - resolve(connection); - } - else { - if (_this.connection.connectionId === connectionId) { - resolve(_this.connection); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - } - }); - }; - Session.prototype.getRemoteConnection = function (connectionId, errorMessage) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections[connectionId]; - if (!!connection) { - resolve(connection); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - }); - }; - Session.prototype.processToken = function (token) { - var url = new URL(token); - this.sessionId = url.searchParams.get('sessionId'); - var secret = url.searchParams.get('secret'); - var recorder = url.searchParams.get('recorder'); - if (!!secret) { - this.openvidu.secret = secret; - } - if (!!recorder) { - this.openvidu.recorder = true; - } - this.openvidu.wsUri = 'wss://' + url.host + '/openvidu'; - }; - return Session; -}()); -exports.Session = Session; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/Events/ConnectionEvent":38,"../OpenViduInternal/Events/RecordingEvent":41,"../OpenViduInternal/Events/SessionDisconnectedEvent":42,"../OpenViduInternal/Events/SignalEvent":43,"../OpenViduInternal/Events/StreamEvent":44,"./Connection":27,"./Subscriber":34,"platform":9,"wolfy87-eventemitter":25}],32:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats"); -var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent"); -var EventEmitter = require("wolfy87-eventemitter"); -var kurentoUtils = require("../OpenViduInternal/KurentoUtils/kurento-utils-js"); -var Stream = (function () { - function Stream(session, options) { - var _this = this; - this.ee = new EventEmitter(); - this.isSubscribeToRemote = false; - this.isLocalStreamReadyToPublish = false; - this.isLocalStreamPublished = false; - this.session = session; - if (options.hasOwnProperty('id')) { - this.inboundStreamOpts = options; - this.streamId = this.inboundStreamOpts.id; - this.hasAudio = this.inboundStreamOpts.recvAudio; - this.hasVideo = this.inboundStreamOpts.recvVideo; - this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo; - this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; - } - else { - this.outboundStreamOpts = options; - if (this.isSendVideo()) { - if (this.isSendScreen()) { - this.streamId = 'SCREEN'; - this.typeOfVideo = 'SCREEN'; - } - else { - this.streamId = 'CAMERA'; - this.typeOfVideo = 'CAMERA'; - } - this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; - } - else { - this.streamId = 'MICRO'; - delete this.typeOfVideo; - } - this.hasAudio = this.isSendAudio(); - this.hasVideo = this.isSendVideo(); - } - this.ee.on('mediastream-updated', function () { - _this.streamManager.updateMediaStream(_this.mediaStream); - console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']'); - }); - } - Stream.prototype.getMediaStream = function () { - return this.mediaStream; - }; - Stream.prototype.setMediaStream = function (mediaStream) { - this.mediaStream = mediaStream; - }; - Stream.prototype.updateMediaStreamInVideos = function () { - this.ee.emitEvent('mediastream-updated'); - }; - Stream.prototype.getWebRtcPeer = function () { - return this.webRtcPeer; - }; - Stream.prototype.getRTCPeerConnection = function () { - return this.webRtcPeer.peerConnection; - }; - Stream.prototype.subscribeToMyRemote = function (value) { - this.isSubscribeToRemote = value; - }; - Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { - this.outboundStreamOpts = outboundStreamOpts; - }; - Stream.prototype.subscribe = function () { - var _this = this; - return new Promise(function (resolve, reject) { - _this.initWebRtcPeerReceive() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }); - }; - Stream.prototype.publish = function () { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.isLocalStreamReadyToPublish) { - _this.initWebRtcPeerSend() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - } - else { - _this.ee.once('stream-ready-to-publish', function () { - _this.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }); - } - }); - }; - Stream.prototype.disposeWebRtcPeer = function () { - if (this.webRtcPeer) { - this.webRtcPeer.dispose(); - } - if (this.speechEvent) { - this.speechEvent.stop(); - } - this.stopWebRtcStats(); - console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed'); - }; - Stream.prototype.disposeMediaStream = function () { - if (this.mediaStream) { - this.mediaStream.getAudioTracks().forEach(function (track) { - track.stop(); - }); - this.mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - delete this.mediaStream; - } - console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed'); - }; - Stream.prototype.displayMyRemote = function () { - return this.isSubscribeToRemote; - }; - Stream.prototype.isSendAudio = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.audioSource !== null && - this.outboundStreamOpts.publisherProperties.audioSource !== false); - }; - Stream.prototype.isSendVideo = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.videoSource !== null && - this.outboundStreamOpts.publisherProperties.videoSource !== false); - }; - Stream.prototype.isSendScreen = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.videoSource === 'screen'); - }; - Stream.prototype.setSpeechEventIfNotExists = function () { - if (!this.speechEvent) { - var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}; - harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50; - harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50; - this.speechEvent = kurentoUtils.WebRtcPeer.hark(this.mediaStream, harkOptions); - } - }; - Stream.prototype.enableSpeakingEvents = function () { - var _this = this; - this.setSpeechEventIfNotExists(); - this.speechEvent.on('speaking', function () { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - }); - this.speechEvent.on('stopped_speaking', function () { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - }); - }; - Stream.prototype.enableOnceSpeakingEvents = function () { - var _this = this; - this.setSpeechEventIfNotExists(); - this.speechEvent.on('speaking', function () { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - _this.disableSpeakingEvents(); - }); - this.speechEvent.on('stopped_speaking', function () { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - _this.disableSpeakingEvents(); - }); - }; - Stream.prototype.disableSpeakingEvents = function () { - this.speechEvent.stop(); - this.speechEvent = undefined; - }; - Stream.prototype.initWebRtcPeerSend = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var userMediaConstraints = { - audio: _this.isSendAudio(), - video: _this.isSendVideo() - }; - var options = { - videoStream: _this.mediaStream, - mediaConstraints: userMediaConstraints, - onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), - iceServers: _this.session.openvidu.advancedConfiguration.iceServers - }; - var successCallback = function (error, sdpOfferParam, wp) { - if (error) { - reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error))); - } - console.debug('Sending SDP offer to publish as ' - + _this.streamId, sdpOfferParam); - _this.session.openvidu.sendRequest('publishVideo', { - sdpOffer: sdpOfferParam, - doLoopback: _this.displayMyRemote() || false, - audioActive: _this.isSendAudio(), - videoActive: _this.isSendVideo(), - typeOfVideo: ((_this.isSendVideo()) ? (_this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''), - frameRate: !!_this.frameRate ? _this.frameRate : -1 - }, function (error, response) { - if (error) { - reject('Error on publishVideo: ' + JSON.stringify(error)); - } - else { - _this.processSdpAnswer(response.sdpAnswer) - .then(function () { - _this.isLocalStreamPublished = true; - if (_this.displayMyRemote()) { - _this.updateMediaStreamInVideos(); - } - _this.ee.emitEvent('stream-created-by-publisher'); - resolve(); - }) - .catch(function (error) { - reject(error); - }); - console.info("'Publisher' successfully published to session"); - } - }); - }; - if (_this.displayMyRemote()) { - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function (err) { - if (err) { - reject(err); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - } - else { - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options, function (error) { - if (error) { - reject(error); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - } - }); - }; - Stream.prototype.initWebRtcPeerReceive = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var offerConstraints = { - audio: _this.inboundStreamOpts.recvAudio, - video: _this.inboundStreamOpts.recvVideo - }; - console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); - var options = { - onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), - mediaConstraints: offerConstraints - }; - var successCallback = function (error, sdpOfferParam, wp) { - if (error) { - reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error))); - } - console.debug('Sending SDP offer to subscribe to ' - + _this.streamId, sdpOfferParam); - _this.session.openvidu.sendRequest('receiveVideoFrom', { - sender: _this.streamId, - sdpOffer: sdpOfferParam - }, function (error, response) { - if (error) { - reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error))); - } - else { - _this.processSdpAnswer(response.sdpAnswer).then(function () { - resolve(); - }).catch(function (error) { - reject(error); - }); - } - }); - }; - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function (error) { - if (error) { - reject(error); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - }); - }; - Stream.prototype.processSdpAnswer = function (sdpAnswer) { - var _this = this; - return new Promise(function (resolve, reject) { - var answer = new RTCSessionDescription({ - type: 'answer', - sdp: sdpAnswer, - }); - console.debug(_this.streamId + ': set peer connection with recvd SDP answer', sdpAnswer); - var streamId = _this.streamId; - var peerConnection = _this.webRtcPeer.peerConnection; - peerConnection.setRemoteDescription(answer, function () { - if (!_this.isLocal() || _this.displayMyRemote()) { - _this.mediaStream = peerConnection.getRemoteStreams()[0]; - console.debug('Peer remote stream', _this.mediaStream); - if (!!_this.mediaStream) { - _this.ee.emitEvent('mediastream-updated'); - if (!!_this.mediaStream.getAudioTracks()[0] && _this.session.speakingEventsEnabled) { - _this.enableSpeakingEvents(); - } - } - } - _this.initWebRtcStats(); - resolve(); - }, function (error) { - reject(new Error(_this.streamId + ': Error setting SDP to the peer connection: ' + JSON.stringify(error))); - }); - }); - }; - Stream.prototype.initWebRtcStats = function () { - this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); - this.webRtcStats.initWebRtcStats(); - }; - Stream.prototype.stopWebRtcStats = function () { - if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { - this.webRtcStats.stopWebRtcStats(); - } - }; - Stream.prototype.isLocal = function () { - return (!this.inboundStreamOpts && !!this.outboundStreamOpts); - }; - return Stream; -}()); -exports.Stream = Stream; - -},{"../OpenViduInternal/Events/PublisherSpeakingEvent":40,"../OpenViduInternal/KurentoUtils/kurento-utils-js":57,"../OpenViduInternal/WebRtcStats/WebRtcStats":60,"wolfy87-eventemitter":25}],33:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); -var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var EventEmitter = require("wolfy87-eventemitter"); -var StreamManager = (function () { - function StreamManager(stream, targetElement) { - var _this = this; - this.videos = []; - this.lazyLaunchVideoElementCreatedEvent = false; - this.ee = new EventEmitter(); - this.stream = stream; - this.stream.streamManager = this; - this.remote = !this.stream.isLocal(); - if (!!targetElement) { - var targEl = void 0; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targetElement); - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - if (!!targEl) { - this.firstVideoElement = { - targetElement: targEl, - video: document.createElement('video'), - id: '' - }; - this.targetElement = targEl; - this.element = targEl; - } - } - this.canPlayListener = function () { - if (_this.stream.isLocal()) { - if (!_this.stream.displayMyRemote()) { - console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); - } - else { - console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]); - } - } - else { - console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); - } - _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]); - }; - } - StreamManager.prototype.on = function (type, handler) { - this.ee.on(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered", event); - } - else { - console.info("Event '" + type + "' triggered"); - } - handler(event); - }); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = false; - } - } - if (type === 'streamPlaying' || type === 'videoPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); - this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); - } - } - return this; - }; - StreamManager.prototype.once = function (type, handler) { - this.ee.once(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered once", event); - } - else { - console.info("Event '" + type + "' triggered once"); - } - handler(event); - }); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - } - } - if (type === 'streamPlaying' || type === 'videoPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); - this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); - } - } - return this; - }; - StreamManager.prototype.off = function (type, handler) { - if (!handler) { - this.ee.removeAllListeners(type); - } - else { - this.ee.off(type, handler); - } - return this; - }; - StreamManager.prototype.addVideoElement = function (video) { - this.initializeVideoProperties(video); - for (var _i = 0, _a = this.videos; _i < _a.length; _i++) { - var v = _a[_i]; - if (v.video === video) { - return 0; - } - } - var returnNumber = 1; - this.initializeVideoProperties(video); - for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) { - var streamManager = _c[_b]; - if (streamManager.disassociateVideo(video)) { - returnNumber = -1; - break; - } - } - this.stream.session.streamManagers.forEach(function (streamManager) { - streamManager.disassociateVideo(video); - }); - this.pushNewStreamManagerVideo({ - video: video, - id: video.id - }); - console.info('New video element associated to ', this); - return returnNumber; - }; - StreamManager.prototype.createVideoElement = function (targetElement, insertMode) { - var targEl; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targEl); - if (!targEl) { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - else { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - var video = document.createElement('video'); - this.initializeVideoProperties(video); - var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; - switch (insMode) { - case VideoInsertMode_1.VideoInsertMode.AFTER: - targEl.parentNode.insertBefore(video, targEl.nextSibling); - break; - case VideoInsertMode_1.VideoInsertMode.APPEND: - targEl.appendChild(video); - break; - case VideoInsertMode_1.VideoInsertMode.BEFORE: - targEl.parentNode.insertBefore(video, targEl); - break; - case VideoInsertMode_1.VideoInsertMode.PREPEND: - targEl.insertBefore(video, targEl.childNodes[0]); - break; - case VideoInsertMode_1.VideoInsertMode.REPLACE: - targEl.parentNode.replaceChild(video, targEl); - break; - default: - insMode = VideoInsertMode_1.VideoInsertMode.APPEND; - targEl.appendChild(video); - break; - } - var v = { - targetElement: targEl, - video: video, - insertMode: insMode, - id: video.id - }; - this.pushNewStreamManagerVideo(v); - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement; - return video; - }; - StreamManager.prototype.initializeVideoProperties = function (video) { - video.srcObject = this.stream.getMediaStream(); - video.autoplay = true; - video.controls = false; - if (!video.id) { - video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId; - if (!this.id && !!this.targetElement) { - this.id = video.id; - } - } - if (!this.remote && !this.stream.displayMyRemote()) { - video.muted = true; - if (this.stream.outboundStreamOpts.publisherProperties.mirror) { - this.mirrorVideo(video); - } - } - }; - StreamManager.prototype.removeAllVideos = function () { - var _this = this; - for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) { - if (this.stream.session.streamManagers[i] === this) { - this.stream.session.streamManagers.splice(i, 1); - } - } - this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) { - streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener); - if (!!streamManagerVideo.targetElement) { - streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video); - _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]); - _this.videos.splice(videos.length - 1 - index, 1); - } - else { - streamManagerVideo.video.srcObject = null; - } - }); - }; - StreamManager.prototype.disassociateVideo = function (video) { - var disassociated = false; - for (var i = 0; i < this.videos.length; i++) { - if (this.videos[i].video === video) { - this.videos.splice(i, 1); - disassociated = true; - console.info('Video element disassociated from ', this); - break; - } - } - return disassociated; - }; - StreamManager.prototype.addPlayEventToFirstVideo = function () { - if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) { - this.videos[0].video.addEventListener('canplay', this.canPlayListener); - } - }; - StreamManager.prototype.updateMediaStream = function (mediaStream) { - this.videos.forEach(function (streamManagerVideo) { - streamManagerVideo.video.srcObject = mediaStream; - }); - }; - StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) { - this.videos.push(streamManagerVideo); - this.addPlayEventToFirstVideo(); - if (this.stream.session.streamManagers.indexOf(this) === -1) { - this.stream.session.streamManagers.push(this); - } - }; - StreamManager.prototype.mirrorVideo = function (video) { - video.style.transform = 'rotateY(180deg)'; - video.style.webkitTransform = 'rotateY(180deg)'; - }; - return StreamManager; -}()); -exports.StreamManager = StreamManager; - -},{"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/Events/StreamManagerEvent":45,"../OpenViduInternal/Events/VideoElementEvent":46,"wolfy87-eventemitter":25}],34:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var StreamManager_1 = require("./StreamManager"); -var Subscriber = (function (_super) { - __extends(Subscriber, _super); - function Subscriber(stream, targEl, properties) { - var _this = _super.call(this, stream, targEl) || this; - _this.element = _this.targetElement; - _this.stream = stream; - _this.properties = properties; - return _this; - } - Subscriber.prototype.subscribeToAudio = function (value) { - this.stream.getMediaStream().getAudioTracks().forEach(function (track) { - track.enabled = value; - }); - console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream'); - return this; - }; - Subscriber.prototype.subscribeToVideo = function (value) { - this.stream.getMediaStream().getVideoTracks().forEach(function (track) { - track.enabled = value; - }); - console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream'); - return this; - }; - return Subscriber; -}(StreamManager_1.StreamManager)); -exports.Subscriber = Subscriber; - -},{"./StreamManager":33}],35:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorderState; -(function (LocalRecorderState) { - LocalRecorderState["READY"] = "READY"; - LocalRecorderState["RECORDING"] = "RECORDING"; - LocalRecorderState["PAUSED"] = "PAUSED"; - LocalRecorderState["FINISHED"] = "FINISHED"; -})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {})); - -},{}],36:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var OpenViduErrorName; -(function (OpenViduErrorName) { - OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; - OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED"; - OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; - OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; - OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; - OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED"; - OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; - OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; - OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; - OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; - OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; - OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED"; - OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; -})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); -var OpenViduError = (function () { - function OpenViduError(name, message) { - this.name = name; - this.message = message; - } - return OpenViduError; -}()); -exports.OpenViduError = OpenViduError; - -},{}],37:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var VideoInsertMode; -(function (VideoInsertMode) { - VideoInsertMode["AFTER"] = "AFTER"; - VideoInsertMode["APPEND"] = "APPEND"; - VideoInsertMode["BEFORE"] = "BEFORE"; - VideoInsertMode["PREPEND"] = "PREPEND"; - VideoInsertMode["REPLACE"] = "REPLACE"; -})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); - -},{}],38:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var ConnectionEvent = (function (_super) { - __extends(ConnectionEvent, _super); - function ConnectionEvent(cancelable, target, type, connection, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.connection = connection; - _this.reason = reason; - return _this; - } - ConnectionEvent.prototype.callDefaultBehaviour = function () { }; - return ConnectionEvent; -}(Event_1.Event)); -exports.ConnectionEvent = ConnectionEvent; - -},{"./Event":39}],39:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Event = (function () { - function Event(cancelable, target, type) { - this.hasBeenPrevented = false; - this.cancelable = cancelable; - this.target = target; - this.type = type; - } - Event.prototype.isDefaultPrevented = function () { - return this.hasBeenPrevented; - }; - Event.prototype.preventDefault = function () { - this.callDefaultBehaviour = function () { }; - this.hasBeenPrevented = true; - }; - return Event; -}()); -exports.Event = Event; - -},{}],40:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var PublisherSpeakingEvent = (function (_super) { - __extends(PublisherSpeakingEvent, _super); - function PublisherSpeakingEvent(target, type, connection, streamId) { - var _this = _super.call(this, false, target, type) || this; - _this.type = type; - _this.connection = connection; - _this.streamId = streamId; - return _this; - } - PublisherSpeakingEvent.prototype.callDefaultBehaviour = function () { }; - return PublisherSpeakingEvent; -}(Event_1.Event)); -exports.PublisherSpeakingEvent = PublisherSpeakingEvent; - -},{"./Event":39}],41:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var RecordingEvent = (function (_super) { - __extends(RecordingEvent, _super); - function RecordingEvent(target, type, id, name) { - var _this = _super.call(this, false, target, type) || this; - _this.id = id; - if (name !== id) { - _this.name = name; - } - return _this; - } - RecordingEvent.prototype.callDefaultBehaviour = function () { }; - return RecordingEvent; -}(Event_1.Event)); -exports.RecordingEvent = RecordingEvent; - -},{"./Event":39}],42:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var SessionDisconnectedEvent = (function (_super) { - __extends(SessionDisconnectedEvent, _super); - function SessionDisconnectedEvent(target, reason) { - var _this = _super.call(this, true, target, 'sessionDisconnected') || this; - _this.reason = reason; - return _this; - } - SessionDisconnectedEvent.prototype.callDefaultBehaviour = function () { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); - var session = this.target; - for (var connectionId in session.remoteConnections) { - if (!!session.remoteConnections[connectionId].stream) { - session.remoteConnections[connectionId].stream.disposeWebRtcPeer(); - session.remoteConnections[connectionId].stream.disposeMediaStream(); - if (session.remoteConnections[connectionId].stream.streamManager) { - session.remoteConnections[connectionId].stream.streamManager.removeAllVideos(); - } - delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId]; - session.remoteConnections[connectionId].dispose(); - } - delete session.remoteConnections[connectionId]; - } - }; - return SessionDisconnectedEvent; -}(Event_1.Event)); -exports.SessionDisconnectedEvent = SessionDisconnectedEvent; - -},{"./Event":39}],43:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var SignalEvent = (function (_super) { - __extends(SignalEvent, _super); - function SignalEvent(target, type, data, from) { - var _this = _super.call(this, false, target, type) || this; - _this.type = type; - _this.data = data; - _this.from = from; - return _this; - } - SignalEvent.prototype.callDefaultBehaviour = function () { }; - return SignalEvent; -}(Event_1.Event)); -exports.SignalEvent = SignalEvent; - -},{"./Event":39}],44:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var Publisher_1 = require("../../OpenVidu/Publisher"); -var Session_1 = require("../../OpenVidu/Session"); -var StreamEvent = (function (_super) { - __extends(StreamEvent, _super); - function StreamEvent(cancelable, target, type, stream, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.stream = stream; - _this.reason = reason; - return _this; - } - StreamEvent.prototype.callDefaultBehaviour = function () { - if (this.type === 'streamDestroyed') { - if (this.target instanceof Session_1.Session) { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); - this.stream.disposeWebRtcPeer(); - } - else if (this.target instanceof Publisher_1.Publisher) { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Publisher'"); - this.stream.isLocalStreamReadyToPublish = false; - } - this.stream.disposeMediaStream(); - if (this.stream.streamManager) - this.stream.streamManager.removeAllVideos(); - delete this.stream.session.remoteStreamsCreated[this.stream.streamId]; - var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId]; - if (!!remoteConnection && !!remoteConnection.options) { - var streamOptionsServer = remoteConnection.options.streams; - for (var i = streamOptionsServer.length - 1; i >= 0; --i) { - if (streamOptionsServer[i].id === this.stream.streamId) { - streamOptionsServer.splice(i, 1); - } - } - } - } - }; - return StreamEvent; -}(Event_1.Event)); -exports.StreamEvent = StreamEvent; - -},{"../../OpenVidu/Publisher":30,"../../OpenVidu/Session":31,"./Event":39}],45:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var StreamManagerEvent = (function (_super) { - __extends(StreamManagerEvent, _super); - function StreamManagerEvent(target) { - return _super.call(this, false, target, 'streamPlaying') || this; - } - StreamManagerEvent.prototype.callDefaultBehaviour = function () { }; - return StreamManagerEvent; -}(Event_1.Event)); -exports.StreamManagerEvent = StreamManagerEvent; - -},{"./Event":39}],46:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var VideoElementEvent = (function (_super) { - __extends(VideoElementEvent, _super); - function VideoElementEvent(element, target, type) { - var _this = _super.call(this, false, target, type) || this; - _this.element = element; - return _this; - } - VideoElementEvent.prototype.callDefaultBehaviour = function () { }; - return VideoElementEvent; -}(Event_1.Event)); -exports.VideoElementEvent = VideoElementEvent; - -},{"./Event":39}],47:[function(require,module,exports){ -function Mapper() { - var sources = {}; - this.forEach = function (callback) { - for (var key in sources) { - var source = sources[key]; - for (var key2 in source) - callback(source[key2]); - } - ; - }; - this.get = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return undefined; - return ids[id]; - }; - this.remove = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return; - delete ids[id]; - for (var i in ids) { - return false; - } - delete sources[source]; - }; - this.set = function (value, id, source) { - if (value == undefined) - return this.remove(id, source); - var ids = sources[source]; - if (ids == undefined) - sources[source] = ids = {}; - ids[id] = value; - }; -} -; -Mapper.prototype.pop = function (id, source) { - var value = this.get(id, source); - if (value == undefined) - return undefined; - this.remove(id, source); - return value; -}; -module.exports = Mapper; - -},{}],48:[function(require,module,exports){ -var JsonRpcClient = require('./jsonrpcclient'); -exports.JsonRpcClient = JsonRpcClient; - -},{"./jsonrpcclient":49}],49:[function(require,module,exports){ -var RpcBuilder = require('../'); -var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); -Date.now = Date.now || function () { - return +new Date; -}; -var PING_INTERVAL = 5000; -var RECONNECTING = 'RECONNECTING'; -var CONNECTED = 'CONNECTED'; -var DISCONNECTED = 'DISCONNECTED'; -var Logger = console; -function JsonRpcClient(configuration) { - var self = this; - var wsConfig = configuration.ws; - var notReconnectIfNumLessThan = -1; - var pingNextNum = 0; - var enabledPings = true; - var pingPongStarted = false; - var pingInterval; - var status = DISCONNECTED; - var onreconnecting = wsConfig.onreconnecting; - var onreconnected = wsConfig.onreconnected; - var onconnected = wsConfig.onconnected; - var onerror = wsConfig.onerror; - configuration.rpc.pull = function (params, request) { - request.reply(null, "push"); - }; - wsConfig.onreconnecting = function () { - Logger.debug("--------- ONRECONNECTING -----------"); - if (status === RECONNECTING) { - Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it"); - return; - } - status = RECONNECTING; - if (onreconnecting) { - onreconnecting(); - } - }; - wsConfig.onreconnected = function () { - Logger.debug("--------- ONRECONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - enabledPings = true; - updateNotReconnectIfLessThan(); - usePing(); - if (onreconnected) { - onreconnected(); - } - }; - wsConfig.onconnected = function () { - Logger.debug("--------- ONCONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - enabledPings = true; - usePing(); - if (onconnected) { - onconnected(); - } - }; - wsConfig.onerror = function (error) { - Logger.debug("--------- ONERROR -----------"); - status = DISCONNECTED; - if (onerror) { - onerror(error); - } - }; - var ws = new WebSocketWithReconnection(wsConfig); - Logger.debug('Connecting websocket to URI: ' + wsConfig.uri); - var rpcBuilderOptions = { - request_timeout: configuration.rpc.requestTimeout, - ping_request_timeout: configuration.rpc.heartbeatRequestTimeout - }; - var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) { - Logger.debug('Received request: ' + JSON.stringify(request)); - try { - var func = configuration.rpc[request.method]; - if (func === undefined) { - Logger.error("Method " + request.method + " not registered in client"); - } - else { - func(request.params, request); - } - } - catch (err) { - Logger.error('Exception processing request: ' + JSON.stringify(request)); - Logger.error(err); - } - }); - this.send = function (method, params, callback) { - if (method !== 'ping') { - Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); - } - var requestTime = Date.now(); - rpc.encode(method, params, function (error, result) { - if (error) { - try { - Logger.error("ERROR:" + error.message + " in Request: method:" + - method + " params:" + JSON.stringify(params) + " request:" + - error.request); - if (error.data) { - Logger.error("ERROR DATA:" + JSON.stringify(error.data)); - } - } - catch (e) { } - error.requestTime = requestTime; - } - if (callback) { - if (result != undefined && result.value !== 'pong') { - Logger.debug('Response: ' + JSON.stringify(result)); - } - callback(error, result); - } - }); - }; - function updateNotReconnectIfLessThan() { - Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' + - notReconnectIfNumLessThan + ')'); - notReconnectIfNumLessThan = pingNextNum; - } - function sendPing() { - if (enabledPings) { - var params = null; - if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) { - params = { - interval: configuration.heartbeat || PING_INTERVAL - }; - } - pingNextNum++; - self.send('ping', params, (function (pingNum) { - return function (error, result) { - if (error) { - Logger.debug("Error in ping request #" + pingNum + " (" + - error.message + ")"); - if (pingNum > notReconnectIfNumLessThan) { - enabledPings = false; - updateNotReconnectIfLessThan(); - Logger.debug("Server did not respond to ping message #" + - pingNum + ". Reconnecting... "); - ws.reconnectWs(); - } - } - }; - })(pingNextNum)); - } - else { - Logger.debug("Trying to send ping, but ping is not enabled"); - } - } - function usePing() { - if (!pingPongStarted) { - Logger.debug("Starting ping (if configured)"); - pingPongStarted = true; - if (configuration.heartbeat != undefined) { - pingInterval = setInterval(sendPing, configuration.heartbeat); - sendPing(); - } - } - } - this.close = function () { - Logger.debug("Closing jsonRpcClient explicitly by client"); - if (pingInterval != undefined) { - Logger.debug("Clearing ping interval"); - clearInterval(pingInterval); - } - pingPongStarted = false; - enabledPings = false; - if (configuration.sendCloseMessage) { - Logger.debug("Sending close message"); - this.send('closeSession', null, function (error, result) { - if (error) { - Logger.error("Error sending close message: " + JSON.stringify(error)); - } - ws.close(); - }); - } - else { - ws.close(); - } - }; - this.forceClose = function (millis) { - ws.forceClose(millis); - }; - this.reconnect = function () { - ws.reconnectWs(); - }; -} -module.exports = JsonRpcClient; - -},{"../":52,"./transports/webSocketWithReconnection":51}],50:[function(require,module,exports){ -var WebSocketWithReconnection = require('./webSocketWithReconnection'); -exports.WebSocketWithReconnection = WebSocketWithReconnection; - -},{"./webSocketWithReconnection":51}],51:[function(require,module,exports){ -(function (global){ -"use strict"; -var BrowserWebSocket = global.WebSocket || global.MozWebSocket; -var Logger = console; -var MAX_RETRIES = 2000; -var RETRY_TIME_MS = 3000; -var CONNECTING = 0; -var OPEN = 1; -var CLOSING = 2; -var CLOSED = 3; -function WebSocketWithReconnection(config) { - var closing = false; - var registerMessageHandler; - var wsUri = config.uri; - var useSockJS = config.useSockJS; - var reconnecting = false; - var forcingDisconnection = false; - var ws; - if (useSockJS) { - ws = new SockJS(wsUri); - } - else { - ws = new WebSocket(wsUri); - } - ws.onopen = function () { - logConnected(ws, wsUri); - if (config.onconnected) { - config.onconnected(); - } - }; - ws.onerror = function (error) { - Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error); - if (config.onerror) { - config.onerror(error); - } - }; - function logConnected(ws, wsUri) { - try { - Logger.debug("WebSocket connected to " + wsUri); - } - catch (e) { - Logger.error(e); - } - } - var reconnectionOnClose = function () { - if (ws.readyState === CLOSED) { - if (closing) { - Logger.debug("Connection closed by user"); - } - else { - Logger.debug("Connection closed unexpectecly. Reconnecting..."); - reconnectToSameUri(MAX_RETRIES, 1); - } - } - else { - Logger.debug("Close callback from previous websocket. Ignoring it"); - } - }; - ws.onclose = reconnectionOnClose; - function reconnectToSameUri(maxRetries, numRetries) { - Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); - if (numRetries === 1) { - if (reconnecting) { - Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); - return; - } - else { - reconnecting = true; - } - if (config.onreconnecting) { - config.onreconnecting(); - } - } - if (forcingDisconnection) { - reconnectToNewUri(maxRetries, numRetries, wsUri); - } - else { - if (config.newWsUriOnReconnection) { - config.newWsUriOnReconnection(function (error, newWsUri) { - if (error) { - Logger.debug(error); - setTimeout(function () { - reconnectToSameUri(maxRetries, numRetries + 1); - }, RETRY_TIME_MS); - } - else { - reconnectToNewUri(maxRetries, numRetries, newWsUri); - } - }); - } - else { - reconnectToNewUri(maxRetries, numRetries, wsUri); - } - } - } - function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { - Logger.debug("Reconnection attempt #" + numRetries); - ws.close(); - wsUri = reconnectWsUri || wsUri; - var newWs; - if (useSockJS) { - newWs = new SockJS(wsUri); - } - else { - newWs = new WebSocket(wsUri); - } - newWs.onopen = function () { - Logger.debug("Reconnected after " + numRetries + " attempts..."); - logConnected(newWs, wsUri); - reconnecting = false; - registerMessageHandler(); - if (config.onreconnected()) { - config.onreconnected(); - } - newWs.onclose = reconnectionOnClose; - }; - var onErrorOrClose = function (error) { - Logger.warn("Reconnection error: ", error); - if (numRetries === maxRetries) { - if (config.ondisconnect) { - config.ondisconnect(); - } - } - else { - setTimeout(function () { - reconnectToSameUri(maxRetries, numRetries + 1); - }, RETRY_TIME_MS); - } - }; - newWs.onerror = onErrorOrClose; - ws = newWs; - } - this.close = function () { - closing = true; - ws.close(); - }; - this.forceClose = function (millis) { - Logger.debug("Testing: Force WebSocket close"); - if (millis) { - Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); - var goodWsUri = wsUri; - wsUri = "wss://21.234.12.34.4:443/"; - forcingDisconnection = true; - setTimeout(function () { - Logger.debug("Testing: Recover good wsUri " + goodWsUri); - wsUri = goodWsUri; - forcingDisconnection = false; - }, millis); - } - ws.close(); - }; - this.reconnectWs = function () { - Logger.debug("reconnectWs"); - reconnectToSameUri(MAX_RETRIES, 1, wsUri); - }; - this.send = function (message) { - ws.send(message); - }; - this.addEventListener = function (type, callback) { - registerMessageHandler = function () { - ws.addEventListener(type, callback); - }; - registerMessageHandler(); - }; -} -module.exports = WebSocketWithReconnection; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],52:[function(require,module,exports){ -var defineProperty_IE8 = false; -if (Object.defineProperty) { - try { - Object.defineProperty({}, "x", {}); - } - catch (e) { - defineProperty_IE8 = true; - } -} -if (!Function.prototype.bind) { - Function.prototype.bind = function (oThis) { - if (typeof this !== 'function') { - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { - return fToBind.apply(this instanceof fNOP && oThis - ? this - : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); - }; - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - return fBound; - }; -} -var EventEmitter = require('events').EventEmitter; -var inherits = require('inherits'); -var packers = require('./packers'); -var Mapper = require('./Mapper'); -var BASE_TIMEOUT = 5000; -function unifyResponseMethods(responseMethods) { - if (!responseMethods) - return {}; - for (var key in responseMethods) { - var value = responseMethods[key]; - if (typeof value == 'string') - responseMethods[key] = - { - response: value - }; - } - ; - return responseMethods; -} -; -function unifyTransport(transport) { - if (!transport) - return; - if (transport instanceof Function) - return { send: transport }; - if (transport.send instanceof Function) - return transport; - if (transport.postMessage instanceof Function) { - transport.send = transport.postMessage; - return transport; - } - if (transport.write instanceof Function) { - transport.send = transport.write; - return transport; - } - if (transport.onmessage !== undefined) - return; - if (transport.pause instanceof Function) - return; - throw new SyntaxError("Transport is not a function nor a valid object"); -} -; -function RpcNotification(method, params) { - if (defineProperty_IE8) { - this.method = method; - this.params = params; - } - else { - Object.defineProperty(this, 'method', { value: method, enumerable: true }); - Object.defineProperty(this, 'params', { value: params, enumerable: true }); - } -} -; -function RpcBuilder(packer, options, transport, onRequest) { - var self = this; - if (!packer) - throw new SyntaxError('Packer is not defined'); - if (!packer.pack || !packer.unpack) - throw new SyntaxError('Packer is invalid'); - var responseMethods = unifyResponseMethods(packer.responseMethods); - if (options instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = options; - transport = undefined; - options = undefined; - } - ; - if (options && options.send instanceof Function) { - if (transport && !(transport instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - onRequest = transport; - transport = options; - options = undefined; - } - ; - if (transport instanceof Function) { - if (onRequest != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = transport; - transport = undefined; - } - ; - if (transport && transport.send instanceof Function) - if (onRequest && !(onRequest instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - options = options || {}; - EventEmitter.call(this); - if (onRequest) - this.on('request', onRequest); - if (defineProperty_IE8) - this.peerID = options.peerID; - else - Object.defineProperty(this, 'peerID', { value: options.peerID }); - var max_retries = options.max_retries || 0; - function transportMessage(event) { - self.decode(event.data || event); - } - ; - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - if (transport) { - if (transport.removeEventListener) - transport.removeEventListener('message', transportMessage); - else if (transport.removeListener) - transport.removeListener('data', transportMessage); - } - ; - if (value) { - if (value.addEventListener) - value.addEventListener('message', transportMessage); - else if (value.addListener) - value.addListener('data', transportMessage); - } - ; - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - this.setTransport(transport); - var request_timeout = options.request_timeout || BASE_TIMEOUT; - var ping_request_timeout = options.ping_request_timeout || request_timeout; - var response_timeout = options.response_timeout || BASE_TIMEOUT; - var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT; - var requestID = 0; - var requests = new Mapper(); - var responses = new Mapper(); - var processedResponses = new Mapper(); - var message2Key = {}; - function storeResponse(message, id, dest) { - var response = { - message: message, - timeout: setTimeout(function () { - responses.remove(id, dest); - }, response_timeout) - }; - responses.set(response, id, dest); - } - ; - function storeProcessedResponse(ack, from) { - var timeout = setTimeout(function () { - processedResponses.remove(ack, from); - }, duplicates_timeout); - processedResponses.set(timeout, ack, from); - } - ; - function RpcRequest(method, params, id, from, transport) { - RpcNotification.call(this, method, params); - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - var response = responses.get(id, from); - if (!(transport || self.getTransport())) { - if (defineProperty_IE8) - this.duplicated = Boolean(response); - else - Object.defineProperty(this, 'duplicated', { - value: Boolean(response) - }); - } - var responseMethod = responseMethods[method]; - this.pack = packer.pack.bind(packer, this, id); - this.reply = function (error, result, transport) { - if (error instanceof Function || error && error.send instanceof Function) { - if (result != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = error; - result = null; - error = undefined; - } - else if (result instanceof Function - || result && result.send instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = result; - result = null; - } - ; - transport = unifyTransport(transport); - if (response) - clearTimeout(response.timeout); - if (from != undefined) { - if (error) - error.dest = from; - if (result) - result.dest = from; - } - ; - var message; - if (error || result != undefined) { - if (self.peerID != undefined) { - if (error) - error.from = self.peerID; - else - result.from = self.peerID; - } - if (responseMethod) { - if (responseMethod.error == undefined && error) - message = - { - error: error - }; - else { - var method = error - ? responseMethod.error - : responseMethod.response; - message = - { - method: method, - params: error || result - }; - } - } - else - message = - { - error: error, - result: result - }; - message = packer.pack(message, id); - } - else if (response) - message = response.message; - else - message = packer.pack({ result: null }, id); - storeResponse(message, id, from); - transport = transport || this.getTransport() || self.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - } - ; - inherits(RpcRequest, RpcNotification); - function cancel(message) { - var key = message2Key[message]; - if (!key) - return; - delete message2Key[message]; - var request = requests.pop(key.id, key.dest); - if (!request) - return; - clearTimeout(request.timeout); - storeProcessedResponse(key.id, key.dest); - } - ; - this.cancel = function (message) { - if (message) - return cancel(message); - for (var message in message2Key) - cancel(message); - }; - this.close = function () { - var transport = this.getTransport(); - if (transport && transport.close) - transport.close(); - this.cancel(); - processedResponses.forEach(clearTimeout); - responses.forEach(function (response) { - clearTimeout(response.timeout); - }); - }; - this.encode = function (method, params, dest, transport, callback) { - if (params instanceof Function) { - if (dest != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = params; - transport = undefined; - dest = undefined; - params = undefined; - } - else if (dest instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = dest; - transport = undefined; - dest = undefined; - } - else if (transport instanceof Function) { - if (callback != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = transport; - transport = undefined; - } - ; - if (self.peerID != undefined) { - params = params || {}; - params.from = self.peerID; - } - ; - if (dest != undefined) { - params = params || {}; - params.dest = dest; - } - ; - var message = { - method: method, - params: params - }; - if (callback) { - var id = requestID++; - var retried = 0; - message = packer.pack(message, id); - function dispatchCallback(error, result) { - self.cancel(message); - callback(error, result); - } - ; - var request = { - message: message, - callback: dispatchCallback, - responseMethods: responseMethods[method] || {} - }; - var encode_transport = unifyTransport(transport); - function sendRequest(transport) { - var rt = (method === 'ping' ? ping_request_timeout : request_timeout); - request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++)); - message2Key[message] = { id: id, dest: dest }; - requests.set(request, id, dest); - transport = transport || encode_transport || self.getTransport(); - if (transport) - return transport.send(message); - return message; - } - ; - function retry(transport) { - transport = unifyTransport(transport); - console.warn(retried + ' retry for request message:', message); - var timeout = processedResponses.pop(id, dest); - clearTimeout(timeout); - return sendRequest(transport); - } - ; - function timeout() { - if (retried < max_retries) - return retry(transport); - var error = new Error('Request has timed out'); - error.request = message; - error.retry = retry; - dispatchCallback(error); - } - ; - return sendRequest(transport); - } - ; - message = packer.pack(message); - transport = transport || this.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - this.decode = function (message, transport) { - if (!message) - throw new TypeError("Message is not defined"); - try { - message = packer.unpack(message); - } - catch (e) { - return console.debug(e, message); - } - ; - var id = message.id; - var ack = message.ack; - var method = message.method; - var params = message.params || {}; - var from = params.from; - var dest = params.dest; - if (self.peerID != undefined && from == self.peerID) - return; - if (id == undefined && ack == undefined) { - var notification = new RpcNotification(method, params); - if (self.emit('request', notification)) - return; - return notification; - } - ; - function processRequest() { - transport = unifyTransport(transport) || self.getTransport(); - if (transport) { - var response = responses.get(id, from); - if (response) - return transport.send(response.message); - } - ; - var idAck = (id != undefined) ? id : ack; - var request = new RpcRequest(method, params, idAck, from, transport); - if (self.emit('request', request)) - return; - return request; - } - ; - function processResponse(request, error, result) { - request.callback(error, result); - } - ; - function duplicatedResponse(timeout) { - console.warn("Response already processed", message); - clearTimeout(timeout); - storeProcessedResponse(ack, from); - } - ; - if (method) { - if (dest == undefined || dest == self.peerID) { - var request = requests.get(ack, from); - if (request) { - var responseMethods = request.responseMethods; - if (method == responseMethods.error) - return processResponse(request, params); - if (method == responseMethods.response) - return processResponse(request, null, params); - return processRequest(); - } - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - } - return processRequest(); - } - ; - var error = message.error; - var result = message.result; - if (error && error.dest && error.dest != self.peerID) - return; - if (result && result.dest && result.dest != self.peerID) - return; - var request = requests.get(ack, from); - if (!request) { - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - return console.warn("No callback was defined for this message", message); - } - ; - processResponse(request, error, result); - }; -} -; -inherits(RpcBuilder, EventEmitter); -RpcBuilder.RpcNotification = RpcNotification; -module.exports = RpcBuilder; -var clients = require('./clients'); -var transports = require('./clients/transports'); -RpcBuilder.clients = clients; -RpcBuilder.clients.transports = transports; -RpcBuilder.packers = packers; - -},{"./Mapper":47,"./clients":48,"./clients/transports":50,"./packers":55,"events":1,"inherits":6}],53:[function(require,module,exports){ -function pack(message, id) { - var result = { - jsonrpc: "2.0" - }; - if (message.method) { - result.method = message.method; - if (message.params) - result.params = message.params; - if (id != undefined) - result.id = id; - } - else if (id != undefined) { - if (message.error) { - if (message.result !== undefined) - throw new TypeError("Both result and error are defined"); - result.error = message.error; - } - else if (message.result !== undefined) - result.result = message.result; - else - throw new TypeError("No result or error is defined"); - result.id = id; - } - ; - return JSON.stringify(result); -} -; -function unpack(message) { - var result = message; - if (typeof message === 'string' || message instanceof String) { - result = JSON.parse(message); - } - var version = result.jsonrpc; - if (version !== '2.0') - throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); - if (result.method == undefined) { - if (result.id == undefined) - throw new TypeError("Invalid message: " + message); - var result_defined = result.result !== undefined; - var error_defined = result.error !== undefined; - if (result_defined && error_defined) - throw new TypeError("Both result and error are defined: " + message); - if (!result_defined && !error_defined) - throw new TypeError("No result or error is defined: " + message); - result.ack = result.id; - delete result.id; - } - return result; -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],54:[function(require,module,exports){ -function pack(message) { - throw new TypeError("Not yet implemented"); -} -; -function unpack(message) { - throw new TypeError("Not yet implemented"); -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],55:[function(require,module,exports){ -var JsonRPC = require('./JsonRPC'); -var XmlRPC = require('./XmlRPC'); -exports.JsonRPC = JsonRPC; -exports.XmlRPC = XmlRPC; - -},{"./JsonRPC":53,"./XmlRPC":54}],56:[function(require,module,exports){ -var freeice = require('freeice'); -var inherits = require('inherits'); -var UAParser = require('ua-parser-js'); -var uuid = require('uuid'); -var hark = require('hark'); -var EventEmitter = require('events').EventEmitter; -var recursive = require('merge').recursive.bind(undefined, true); -var sdpTranslator = require('sdp-translator'); -var logger = window.Logger || console; -var MEDIA_CONSTRAINTS = { - audio: true, - video: { - width: 640, - framerate: 15 - } -}; -var ua = (window && window.navigator) ? window.navigator.userAgent : ''; -var parser = new UAParser(ua); -var browser = parser.getBrowser(); -var usePlanB = false; -if (browser.name === 'Chrome' || browser.name === 'Chromium') { - logger.debug(browser.name + ": using SDP PlanB"); - usePlanB = true; -} -function noop(error) { - if (error) - logger.error(error); -} -function trackStop(track) { - track.stop && track.stop(); -} -function streamStop(stream) { - stream.getTracks().forEach(trackStop); -} -var dumpSDP = function (description) { - if (typeof description === 'undefined' || description === null) { - return ''; - } - return 'type: ' + description.type + '\r\n' + description.sdp; -}; -function bufferizeCandidates(pc, onerror) { - var candidatesQueue = []; - pc.addEventListener('signalingstatechange', function () { - if (this.signalingState === 'stable') { - while (candidatesQueue.length) { - var entry = candidatesQueue.shift(); - pc.addIceCandidate(entry.candidate, entry.callback, entry.callback); - } - } - }); - return function (candidate, callback) { - callback = callback || onerror; - switch (pc.signalingState) { - case 'closed': - callback(new Error('PeerConnection object is closed')); - break; - case 'stable': - if (pc.remoteDescription) { - pc.addIceCandidate(candidate, callback, callback); - } - break; - default: - candidatesQueue.push({ - candidate: candidate, - callback: callback - }); - } - }; -} -function removeFIDFromOffer(sdp) { - var n = sdp.indexOf("a=ssrc-group:FID"); - if (n > 0) { - return sdp.slice(0, n); - } - else { - return sdp; - } -} -function getSimulcastInfo(videoStream) { - var videoTracks = videoStream.getVideoTracks(); - if (!videoTracks.length) { - logger.warn('No video tracks available in the video stream'); - return ''; - } - var lines = [ - 'a=x-google-flag:conference', - 'a=ssrc-group:SIM 1 2 3', - 'a=ssrc:1 cname:localVideo', - 'a=ssrc:1 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:1 mslabel:' + videoStream.id, - 'a=ssrc:1 label:' + videoTracks[0].id, - 'a=ssrc:2 cname:localVideo', - 'a=ssrc:2 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:2 mslabel:' + videoStream.id, - 'a=ssrc:2 label:' + videoTracks[0].id, - 'a=ssrc:3 cname:localVideo', - 'a=ssrc:3 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:3 mslabel:' + videoStream.id, - 'a=ssrc:3 label:' + videoTracks[0].id - ]; - lines.push(''); - return lines.join('\n'); -} -function WebRtcPeer(mode, options, callback) { - if (!(this instanceof WebRtcPeer)) { - return new WebRtcPeer(mode, options, callback); - } - WebRtcPeer.super_.call(this); - if (options instanceof Function) { - callback = options; - options = undefined; - } - options = options || {}; - callback = (callback || noop).bind(this); - var self = this; - var localVideo = options.localVideo; - var remoteVideo = options.remoteVideo; - var videoStream = options.videoStream; - var audioStream = options.audioStream; - var mediaConstraints = options.mediaConstraints; - var connectionConstraints = options.connectionConstraints; - var pc = options.peerConnection; - var sendSource = options.sendSource || 'webcam'; - var guid = uuid.v4(); - var configuration = recursive({ - iceServers: (!!options.iceServers && options.iceServers.length > 0) ? options.iceServers : freeice() - }, options.configuration); - var onicecandidate = options.onicecandidate; - if (onicecandidate) - this.on('icecandidate', onicecandidate); - var oncandidategatheringdone = options.oncandidategatheringdone; - if (oncandidategatheringdone) { - this.on('candidategatheringdone', oncandidategatheringdone); - } - var simulcast = options.simulcast; - var multistream = options.multistream; - var interop = new sdpTranslator.Interop(); - var candidatesQueueOut = []; - var candidategatheringdone = false; - Object.defineProperties(this, { - 'peerConnection': { - get: function () { - return pc; - } - }, - 'id': { - value: options.id || guid, - writable: false - }, - 'remoteVideo': { - get: function () { - return remoteVideo; - } - }, - 'localVideo': { - get: function () { - return localVideo; - } - }, - 'currentFrame': { - get: function () { - if (!remoteVideo) - return; - if (remoteVideo.readyState < remoteVideo.HAVE_CURRENT_DATA) - throw new Error('No video stream data available'); - var canvas = document.createElement('canvas'); - canvas.width = remoteVideo.videoWidth; - canvas.height = remoteVideo.videoHeight; - canvas.getContext('2d').drawImage(remoteVideo, 0, 0); - return canvas; - } - } - }); - if (!pc) { - pc = new RTCPeerConnection(configuration); - } - pc.addEventListener('icecandidate', function (event) { - var candidate = event.candidate; - if (EventEmitter.listenerCount(self, 'icecandidate') || - EventEmitter.listenerCount(self, 'candidategatheringdone')) { - if (candidate) { - var cand; - if (multistream && usePlanB) { - cand = interop.candidateToUnifiedPlan(candidate); - } - else { - cand = candidate; - } - self.emit('icecandidate', cand); - candidategatheringdone = false; - } - else if (!candidategatheringdone) { - self.emit('candidategatheringdone'); - candidategatheringdone = true; - } - } - else if (!candidategatheringdone) { - candidatesQueueOut.push(candidate); - if (!candidate) - candidategatheringdone = true; - } - }); - pc.onaddstream = options.onaddstream; - pc.onnegotiationneeded = options.onnegotiationneeded; - this.on('newListener', function (event, listener) { - if (event === 'icecandidate' || event === 'candidategatheringdone') { - while (candidatesQueueOut.length) { - var candidate = candidatesQueueOut.shift(); - if (!candidate === (event === 'candidategatheringdone')) { - listener(candidate); - } - } - } - }); - var addIceCandidate = bufferizeCandidates(pc); - this.addIceCandidate = function (iceCandidate, callback) { - var candidate; - if (multistream && usePlanB) { - candidate = interop.candidateToPlanB(iceCandidate); - } - else { - candidate = new RTCIceCandidate(iceCandidate); - } - logger.debug('Remote ICE candidate received', iceCandidate); - callback = (callback || noop).bind(this); - addIceCandidate(candidate, callback); - }; - this.generateOffer = function (callback) { - callback = callback.bind(this); - var offerAudio = true; - var offerVideo = true; - if (mediaConstraints) { - offerAudio = (typeof mediaConstraints.audio === 'boolean') ? - mediaConstraints.audio : true; - offerVideo = (typeof mediaConstraints.video === 'boolean') ? - mediaConstraints.video : true; - } - var browserDependantConstraints = { - offerToReceiveAudio: (mode !== 'sendonly' && offerAudio), - offerToReceiveVideo: (mode !== 'sendonly' && offerVideo) - }; - var constraints = browserDependantConstraints; - logger.debug('constraints: ' + JSON.stringify(constraints)); - pc.createOffer(constraints).then(function (offer) { - logger.debug('Created SDP offer'); - offer = mangleSdpToAddSimulcast(offer); - return pc.setLocalDescription(offer); - }).then(function () { - var localDescription = pc.localDescription; - logger.debug('Local description set', localDescription.sdp); - if (multistream && usePlanB) { - localDescription = interop.toUnifiedPlan(localDescription); - logger.debug('offer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); - } - callback(null, localDescription.sdp, self.processAnswer.bind(self)); - }).catch(callback); - }; - this.getLocalSessionDescriptor = function () { - return pc.localDescription; - }; - this.getRemoteSessionDescriptor = function () { - return pc.remoteDescription; - }; - function setRemoteVideo() { - if (remoteVideo) { - remoteVideo.pause(); - var stream = pc.getRemoteStreams()[0]; - remoteVideo.srcObject = stream; - logger.debug('Remote stream:', stream); - remoteVideo.load(); - } - } - this.showLocalVideo = function () { - localVideo.srcObject = videoStream; - localVideo.muted = true; - }; - this.processAnswer = function (sdpAnswer, callback) { - callback = (callback || noop).bind(this); - var answer = new RTCSessionDescription({ - type: 'answer', - sdp: sdpAnswer - }); - if (multistream && usePlanB) { - var planBAnswer = interop.toPlanB(answer); - logger.debug('asnwer::planB', dumpSDP(planBAnswer)); - answer = planBAnswer; - } - logger.debug('SDP answer received, setting remote description'); - if (pc.signalingState === 'closed') { - return callback('PeerConnection is closed'); - } - pc.setRemoteDescription(answer, function () { - setRemoteVideo(); - callback(); - }, callback); - }; - this.processOffer = function (sdpOffer, callback) { - callback = callback.bind(this); - var offer = new RTCSessionDescription({ - type: 'offer', - sdp: sdpOffer - }); - if (multistream && usePlanB) { - var planBOffer = interop.toPlanB(offer); - logger.debug('offer::planB', dumpSDP(planBOffer)); - offer = planBOffer; - } - logger.debug('SDP offer received, setting remote description'); - if (pc.signalingState === 'closed') { - return callback('PeerConnection is closed'); - } - pc.setRemoteDescription(offer).then(function () { - return setRemoteVideo(); - }).then(function () { - return pc.createAnswer(); - }).then(function (answer) { - answer = mangleSdpToAddSimulcast(answer); - logger.debug('Created SDP answer'); - return pc.setLocalDescription(answer); - }).then(function () { - var localDescription = pc.localDescription; - if (multistream && usePlanB) { - localDescription = interop.toUnifiedPlan(localDescription); - logger.debug('answer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); - } - logger.debug('Local description set', localDescription.sdp); - callback(null, localDescription.sdp); - }).catch(callback); - }; - function mangleSdpToAddSimulcast(answer) { - if (simulcast) { - if (browser.name === 'Chrome' || browser.name === 'Chromium') { - logger.debug('Adding multicast info'); - answer = new RTCSessionDescription({ - 'type': answer.type, - 'sdp': removeFIDFromOffer(answer.sdp) + getSimulcastInfo(videoStream) - }); - } - else { - logger.warn('Simulcast is only available in Chrome browser.'); - } - } - return answer; - } - function start() { - if (pc.signalingState === 'closed') { - callback('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); - } - if (videoStream && localVideo) { - self.showLocalVideo(); - } - if (videoStream) { - pc.addStream(videoStream); - } - if (audioStream) { - pc.addStream(audioStream); - } - var browser = parser.getBrowser(); - if (mode === 'sendonly' && - (browser.name === 'Chrome' || browser.name === 'Chromium') && - browser.major === 39) { - mode = 'sendrecv'; - } - callback(); - } - if (mode !== 'recvonly' && !videoStream && !audioStream) { - function getMedia(constraints) { - if (constraints === undefined) { - constraints = MEDIA_CONSTRAINTS; - } - navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - videoStream = stream; - start(); - }).catch(callback); - } - if (sendSource === 'webcam') { - getMedia(mediaConstraints); - } - else { - getScreenConstraints(sendSource, function (error, constraints_) { - if (error) - return callback(error); - constraints = [mediaConstraints]; - constraints.unshift(constraints_); - getMedia(recursive.apply(undefined, constraints)); - }, guid); - } - } - else { - setTimeout(start, 0); - } - this.on('_dispose', function () { - if (localVideo) { - localVideo.pause(); - localVideo.srcObject = null; - localVideo.load(); - localVideo.muted = false; - } - if (remoteVideo) { - remoteVideo.pause(); - remoteVideo.srcObject = null; - remoteVideo.load(); - } - self.removeAllListeners(); - if (window.cancelChooseDesktopMedia !== undefined) { - window.cancelChooseDesktopMedia(guid); - } - }); -} -inherits(WebRtcPeer, EventEmitter); -function createEnableDescriptor(type) { - var method = 'get' + type + 'Tracks'; - return { - enumerable: true, - get: function () { - if (!this.peerConnection) - return; - var streams = this.peerConnection.getLocalStreams(); - if (!streams.length) - return; - for (var i = 0, stream; stream = streams[i]; i++) { - var tracks = stream[method](); - for (var j = 0, track; track = tracks[j]; j++) - if (!track.enabled) - return false; - } - return true; - }, - set: function (value) { - function trackSetEnable(track) { - track.enabled = value; - } - this.peerConnection.getLocalStreams().forEach(function (stream) { - stream[method]().forEach(trackSetEnable); - }); - } - }; -} -Object.defineProperties(WebRtcPeer.prototype, { - 'enabled': { - enumerable: true, - get: function () { - return this.audioEnabled && this.videoEnabled; - }, - set: function (value) { - this.audioEnabled = this.videoEnabled = value; - } - }, - 'audioEnabled': createEnableDescriptor('Audio'), - 'videoEnabled': createEnableDescriptor('Video') -}); -WebRtcPeer.prototype.getLocalStream = function (index) { - if (this.peerConnection) { - return this.peerConnection.getLocalStreams()[index || 0]; - } -}; -WebRtcPeer.prototype.getRemoteStream = function (index) { - if (this.peerConnection) { - return this.peerConnection.getRemoteStreams()[index || 0]; - } -}; -WebRtcPeer.prototype.dispose = function () { - logger.debug('Disposing WebRtcPeer'); - var pc = this.peerConnection; - try { - if (pc) { - if (pc.signalingState === 'closed') - return; - pc.getLocalStreams().forEach(streamStop); - pc.close(); - } - } - catch (err) { - logger.warn('Exception disposing webrtc peer ' + err); - } - this.emit('_dispose'); -}; -function WebRtcPeerRecvonly(options, callback) { - if (!(this instanceof WebRtcPeerRecvonly)) { - return new WebRtcPeerRecvonly(options, callback); - } - WebRtcPeerRecvonly.super_.call(this, 'recvonly', options, callback); -} -inherits(WebRtcPeerRecvonly, WebRtcPeer); -function WebRtcPeerSendonly(options, callback) { - if (!(this instanceof WebRtcPeerSendonly)) { - return new WebRtcPeerSendonly(options, callback); - } - WebRtcPeerSendonly.super_.call(this, 'sendonly', options, callback); -} -inherits(WebRtcPeerSendonly, WebRtcPeer); -function WebRtcPeerSendrecv(options, callback) { - if (!(this instanceof WebRtcPeerSendrecv)) { - return new WebRtcPeerSendrecv(options, callback); - } - WebRtcPeerSendrecv.super_.call(this, 'sendrecv', options, callback); -} -inherits(WebRtcPeerSendrecv, WebRtcPeer); -function harkUtils(stream, options) { - return hark(stream, options); -} -exports.bufferizeCandidates = bufferizeCandidates; -exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; -exports.WebRtcPeerSendonly = WebRtcPeerSendonly; -exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; -exports.hark = harkUtils; - -},{"events":1,"freeice":2,"hark":5,"inherits":6,"merge":7,"sdp-translator":15,"ua-parser-js":18,"uuid":19}],57:[function(require,module,exports){ -var WebRtcPeer = require('./WebRtcPeer'); -exports.WebRtcPeer = WebRtcPeer; - -},{"./WebRtcPeer":56}],58:[function(require,module,exports){ -window.getScreenId = function (callback) { - if (!!navigator.mozGetUserMedia) { - callback(null, 'firefox', { - video: { - mozMediaSource: 'window', - mediaSource: 'window' - } - }); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeMediaSourceId) { - if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { - callback('permission-denied'); - } - else { - callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId)); - } - window.removeEventListener('message', onIFrameCallback); - } - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); - window.removeEventListener('message', onIFrameCallback); - } - } - setTimeout(postGetSourceIdMessage, 100); -}; -function getScreenConstraints(error, sourceId) { - var screen_constraints = { - audio: false, - video: { - mandatory: { - chromeMediaSource: error ? 'screen' : 'desktop', - maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, - maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 - }, - optional: [] - } - }; - if (sourceId) { - screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; - } - return screen_constraints; -} -var iframe; -function postGetSourceIdMessage() { - if (!iframe) { - loadIFrame(postGetSourceIdMessage); - return; - } - if (!iframe.isLoaded) { - setTimeout(postGetSourceIdMessage, 100); - return; - } - iframe.contentWindow.postMessage({ - captureSourceId: true - }, '*'); -} -function loadIFrame(loadCallback) { - if (iframe) { - loadCallback(); - return; - } - iframe = document.createElement('iframe'); - iframe.onload = function () { - iframe.isLoaded = true; - loadCallback(); - }; - iframe.src = 'https://www.webrtc-experiment.com/getSourceId/'; - iframe.style.display = 'none'; - (document.body || document.documentElement).appendChild(iframe); -} -window.getChromeExtensionStatus = function (callback) { - if (!!navigator.mozGetUserMedia) { - callback('installed-enabled'); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus); - } - window.removeEventListener('message', onIFrameCallback); - } - setTimeout(postGetChromeExtensionStatusMessage, 100); -}; -function postGetChromeExtensionStatusMessage() { - if (!iframe) { - loadIFrame(postGetChromeExtensionStatusMessage); - return; - } - if (!iframe.isLoaded) { - setTimeout(postGetChromeExtensionStatusMessage, 100); - return; - } - iframe.contentWindow.postMessage({ - getChromeExtensionStatus: true - }, '*'); -} -exports.getScreenId = getScreenId; - -},{}],59:[function(require,module,exports){ -var chromeMediaSource = 'screen'; -var screenCallback; -var isFirefox = typeof window.InstallTrigger !== 'undefined'; -var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; -var isChrome = !!window.chrome && !isOpera; -window.addEventListener('message', function (event) { - if (event.origin != window.location.origin) { - return; - } - onMessageCallback(event.data); -}); -function onMessageCallback(data) { - if (data == 'PermissionDeniedError') { - chromeMediaSource = 'PermissionDeniedError'; - if (screenCallback) - return screenCallback('PermissionDeniedError'); - else - throw new Error('PermissionDeniedError'); - } - if (data == 'rtcmulticonnection-extension-loaded') { - chromeMediaSource = 'desktop'; - } - if (data.sourceId && screenCallback) { - screenCallback(sourceId = data.sourceId); - } -} -function isChromeExtensionAvailable(callback) { - if (isFirefox) - return callback(false); - if (chromeMediaSource == 'desktop') - return callback('isFirefox'); - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback('unavailable'); - } - else - callback('available'); - }, 2000); -} -function getSourceId(callback) { - if (!callback) - throw '"callback" parameter is mandatory.'; - if (sourceId) - return callback(sourceId); - screenCallback = callback; - window.postMessage('get-sourceId', '*'); -} -function getChromeExtensionStatus(extensionid, callback) { - if (isFirefox) - return callback('not-chrome'); - if (arguments.length != 2) { - callback = extensionid; - extensionid = 'ajhifddimkapgcifgcodmmfdlknahffk'; - } - var image = document.createElement('img'); - image.src = 'chrome-extension://' + extensionid + '/icon.png'; - image.onload = function () { - chromeMediaSource = 'screen'; - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback(extensionid == extensionid ? 'installed-enabled' : 'installed-disabled'); - } - else - callback('installed-enabled'); - }, 2000); - }; - image.onerror = function () { - callback('not-installed'); - }; -} -function getScreenConstraints(callback) { - sourceId = ''; - var firefoxScreenConstraints = { - mozMediaSource: 'window', - mediaSource: 'window' - }; - if (isFirefox) - return callback(null, firefoxScreenConstraints); - var screen_constraints = { - mandatory: { - chromeMediaSource: chromeMediaSource, - maxWidth: screen.width > 1920 ? screen.width : 1920, - maxHeight: screen.height > 1080 ? screen.height : 1080 - }, - optional: [] - }; - if (chromeMediaSource == 'desktop' && !sourceId) { - getSourceId(function () { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); - }); - return; - } - if (chromeMediaSource == 'desktop') { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - } - callback(null, screen_constraints); -} -exports.getScreenConstraints = getScreenConstraints; -exports.isChromeExtensionAvailable = isChromeExtensionAvailable; -exports.getChromeExtensionStatus = getChromeExtensionStatus; -exports.getSourceId = getSourceId; - -},{}],60:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var platform = require("platform"); -var WebRtcStats = (function () { - function WebRtcStats(stream) { - this.stream = stream; - this.webRtcStatsEnabled = false; - this.statsInterval = 1; - this.stats = { - inbound: { - audio: { - bytesReceived: 0, - packetsReceived: 0, - packetsLost: 0 - }, - video: { - bytesReceived: 0, - packetsReceived: 0, - packetsLost: 0, - framesDecoded: 0, - nackCount: 0 - } - }, - outbound: { - audio: { - bytesSent: 0, - packetsSent: 0, - }, - video: { - bytesSent: 0, - packetsSent: 0, - framesEncoded: 0, - nackCount: 0 - } - } - }; - } - WebRtcStats.prototype.isEnabled = function () { - return this.webRtcStatsEnabled; - }; - WebRtcStats.prototype.initWebRtcStats = function () { - var _this = this; - var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); - if (elastestInstrumentation) { - console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - this.webRtcStatsEnabled = true; - var instrumentation_1 = JSON.parse(elastestInstrumentation); - this.statsInterval = instrumentation_1.webrtc.interval; - console.warn('localStorage item: ' + JSON.stringify(instrumentation_1)); - this.webRtcStatsIntervalId = setInterval(function () { - _this.sendStatsToHttpEndpoint(instrumentation_1); - }, this.statsInterval * 1000); - return; - } - console.debug('WebRtc stats not enabled'); - }; - WebRtcStats.prototype.stopWebRtcStats = function () { - if (this.webRtcStatsEnabled) { - clearInterval(this.webRtcStatsIntervalId); - console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - } - }; - WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { - var _this = this; - var sendPost = function (json) { - var http = new XMLHttpRequest(); - var url = instrumentation.webrtc.httpEndpoint; - http.open('POST', url, true); - http.setRequestHeader('Content-type', 'application/json'); - http.onreadystatechange = function () { - if (http.readyState === 4 && http.status === 200) { - console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId); - } - }; - http.send(json); - }; - var f = function (stats) { - if (platform.name.indexOf('Firefox') !== -1) { - stats.forEach(function (stat) { - var json = {}; - if ((stat.type === 'inbound-rtp') && - (stat.nackCount !== null && - stat.isRemote === false && - stat.id.startsWith('inbound') && - stat.remoteId.startsWith('inbound'))) { - var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; - var jit = stat.jitter * 1000; - var metrics = { - bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, - jitter: jit, - packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, - packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval - }; - var units = { - bytesReceived: 'bytes', - jitter: 'ms', - packetsReceived: 'packets', - packetsLost: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; - metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; - units['framesDecoded'] = 'frames'; - units['nackCount'] = 'packets'; - _this.stats.inbound.video.framesDecoded = stat.framesDecoded; - _this.stats.inbound.video.nackCount = stat.nackCount; - } - _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; - _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; - _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - else if ((stat.type === 'outbound-rtp') && - (stat.isRemote === false && - stat.id.toLowerCase().includes('outbound'))) { - var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, - packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval - }; - var units = { - bytesSent: 'bytes', - packetsSent: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; - units['framesEncoded'] = 'frames'; - _this.stats.outbound.video.framesEncoded = stat.framesEncoded; - } - _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; - _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - }); - } - else if (platform.name.indexOf('Chrome') !== -1) { - for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { - var key = _a[_i]; - var stat = stats[key]; - if (stat.type === 'ssrc') { - var json = {}; - if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || - (stat.mediaType === 'video' && 'qpSum' in stat))) { - var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, - jitter: stat.googJitterBufferMs, - packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, - packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval - }; - var units = { - bytesReceived: 'bytes', - jitter: 'ms', - packetsReceived: 'packets', - packetsLost: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; - metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; - units['framesDecoded'] = 'frames'; - units['nackCount'] = 'packets'; - _this.stats.inbound.video.framesDecoded = stat.framesDecoded; - _this.stats.inbound.video.nackCount = stat.googNacksSent; - } - _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; - _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; - _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - else if ('bytesSent' in stat) { - var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, - packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval - }; - var units = { - bytesSent: 'bytes', - packetsSent: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; - units['framesEncoded'] = 'frames'; - _this.stats.outbound.video.framesEncoded = stat.framesEncoded; - } - _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; - _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - } - } - } - }; - this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); }); - }; - WebRtcStats.prototype.standardizeReport = function (response) { - if (platform.name.indexOf('Firefox') !== -1) { - return response; - } - var standardReport = {}; - response.result().forEach(function (report) { - var standardStats = { - id: report.id, - timestamp: report.timestamp, - type: report.type - }; - report.names().forEach(function (name) { - standardStats[name] = report.stat(name); - }); - standardReport[standardStats.id] = standardStats; - }); - return standardReport; - }; - WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) { - var _this = this; - if (platform.name.indexOf('Firefox') !== -1) { - return pc.getStats(null, function (response) { - var report = _this.standardizeReport(response); - successCb(report); - }, failureCb); - } - else if (platform.name.indexOf('Chrome') !== -1) { - return pc.getStats(function (response) { - var report = _this.standardizeReport(response); - successCb(report); - }, null, failureCb); - } - }; - return WebRtcStats; -}()); -exports.WebRtcStats = WebRtcStats; - -},{"platform":9}]},{},[26]) -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL21lcmdlL21lcmdlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi9ncmFtbWFyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL3BhcnNlci5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi93cml0ZXIuanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2FycmF5LWVxdWFscy5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNsYXRvci9saWIvaW5kZXguanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2ludGVyb3AuanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL3RyYW5zZm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91YS1wYXJzZXItanMvc3JjL3VhLXBhcnNlci5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9NYXBwZXIuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvSnNvblJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL1htbFJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcy9XZWJSdGNQZWVyLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8uanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2prQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3RlQSxnREFBK0M7QUFFL0MsSUFBSSxNQUFNLEVBQUU7SUFFUixNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsbUJBQVEsQ0FBQztDQUNqQzs7Ozs7QUNhRCxtQ0FBa0M7QUFXbEM7SUFvQ0ksb0JBQW9CLE9BQWdCLEVBQUUsSUFBd0I7UUFBMUMsWUFBTyxHQUFQLE9BQU8sQ0FBUztRQUxwQyxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBT2IsSUFBSSxHQUFHLEdBQUcsdUJBQXVCLENBQUM7UUFDbEMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFO1lBQ1IsR0FBRyxJQUFJLGdDQUFnQyxHQUFHLElBQUksQ0FBQyxFQUFFLEdBQUcsR0FBRyxDQUFDO1NBQzNEO2FBQU07WUFDSCxHQUFHLElBQUksU0FBUyxDQUFDO1NBQ3BCO1FBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVsQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUVwQixJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUU7WUFFUixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDNUIsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQzthQUM3QjtZQUNELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFDZCxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2FBQ3hDO1NBQ0o7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDN0MsQ0FBQztJQVFELHFDQUFnQixHQUFoQixVQUFpQixTQUFTO1FBRXRCLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxlQUFlLEVBQ2xGLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBRWxELElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsRUFBRTtZQUNoRCxZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVk7WUFDL0IsU0FBUyxFQUFFLFNBQVMsQ0FBQyxTQUFTO1lBQzlCLE1BQU0sRUFBRSxTQUFTLENBQUMsTUFBTTtZQUN4QixhQUFhLEVBQUUsU0FBUyxDQUFDLGFBQWE7U0FDekMsRUFBRSxVQUFDLEtBQUssRUFBRSxRQUFRO1lBQ2YsSUFBSSxLQUFLLEVBQUU7Z0JBQ1AsT0FBTyxDQUFDLEtBQUssQ0FBQywrQkFBK0I7c0JBQ3ZDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQzthQUNoQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUtELHNDQUFpQixHQUFqQixVQUFrQixPQUE4QjtRQUFoRCxpQkFtQkM7UUFmRyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQUEsSUFBSTtZQUNoQixJQUFNLGFBQWEsR0FBeUI7Z0JBQ3hDLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTtnQkFDWCxVQUFVLEVBQUUsS0FBSTtnQkFDaEIsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO2dCQUN6QixTQUFTLEVBQUUsSUFBSSxDQUFDLFdBQVc7Z0JBQzNCLFNBQVMsRUFBRSxJQUFJLENBQUMsV0FBVztnQkFDM0IsV0FBVyxFQUFFLElBQUksQ0FBQyxXQUFXO2FBQ2hDLENBQUM7WUFDRixJQUFNLE1BQU0sR0FBRyxJQUFJLGVBQU0sQ0FBQyxLQUFJLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBRXZELEtBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDM0IsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxHQUFHLElBQUksQ0FBQyxZQUFZLEdBQUcsMERBQTBELEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQzlLLENBQUM7SUFLRCw4QkFBUyxHQUFULFVBQVUsTUFBYztRQUNwQixNQUFNLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUN6QixDQUFDO0lBS0QsaUNBQVksR0FBWixVQUFhLFFBQWdCO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBS0QsNEJBQU8sR0FBUDtRQUNJLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDZixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7U0FDdEI7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztJQUN6QixDQUFDO0lBRUwsaUJBQUM7QUFBRCxDQXZJQSxBQXVJQyxJQUFBO0FBdklZLGdDQUFVOzs7OztBQ1h2QixtRkFBa0Y7QUFhbEY7SUFpQkksdUJBQW9CLE1BQWM7UUFBZCxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBWDFCLFdBQU0sR0FBVSxFQUFFLENBQUM7UUFFbkIsVUFBSyxHQUFHLENBQUMsQ0FBQztRQVVkLElBQUksQ0FBQyxZQUFZLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQztRQUM1RyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLGNBQWMsQ0FBQztRQUMxRSxJQUFJLENBQUMsS0FBSyxHQUFHLHVDQUFrQixDQUFDLEtBQUssQ0FBQztJQUMxQyxDQUFDO0lBT0QsOEJBQU0sR0FBTjtRQUFBLGlCQXFFQztRQXBFRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFFL0IsSUFBSTtnQkFFQSxJQUFJLE9BQU8sYUFBYSxLQUFLLFdBQVcsRUFBRTtvQkFDdEMsT0FBTyxDQUFDLEtBQUssQ0FBQyw2R0FBNkcsQ0FBQyxDQUFDO29CQUM3SCxNQUFNLENBQUMsS0FBSyxDQUFDLDZHQUE2RyxDQUFDLENBQUMsQ0FBQztpQkFDaEk7Z0JBQ0QsSUFBSSxLQUFJLENBQUMsS0FBSyxLQUFLLHVDQUFrQixDQUFDLEtBQUssRUFBRTtvQkFDekMsTUFBTSxDQUFDLEtBQUssQ0FBQyx5RkFBeUYsR0FBRyxLQUFJLENBQUMsS0FBSyxHQUFHLHdFQUF3RSxDQUFDLENBQUMsQ0FBQztpQkFDcE07Z0JBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQ0FBc0MsR0FBRyxLQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsR0FBRyxtQkFBbUIsR0FBRyxLQUFJLENBQUMsWUFBWSxHQUFHLEdBQUcsQ0FBQyxDQUFDO2dCQUczSCxJQUFJLE9BQU8sYUFBYSxDQUFDLGVBQWUsS0FBSyxVQUFVLEVBQUU7b0JBQ3JELElBQUksT0FBTyxTQUFBLENBQUM7b0JBQ1osSUFBSSxhQUFhLENBQUMsZUFBZSxDQUFDLHVCQUF1QixDQUFDLEVBQUU7d0JBQ3hELE9BQU8sR0FBRyxFQUFFLFFBQVEsRUFBRSx1QkFBdUIsRUFBRSxDQUFDO3FCQUNuRDt5QkFBTSxJQUFJLGFBQWEsQ0FBQyxlQUFlLENBQUMsd0JBQXdCLENBQUMsRUFBRTt3QkFDaEUsT0FBTyxHQUFHLEVBQUUsUUFBUSxFQUFFLHdCQUF3QixFQUFFLENBQUM7cUJBQ3BEO3lCQUFNLElBQUksYUFBYSxDQUFDLGVBQWUsQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFO3dCQUMvRCxPQUFPLEdBQUcsRUFBRSxRQUFRLEVBQUUsdUJBQXVCLEVBQUUsQ0FBQztxQkFDbkQ7b0JBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7b0JBQ2xELEtBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxhQUFhLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztpQkFDakY7cUJBQU07b0JBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxvRUFBb0UsQ0FBQyxDQUFDO29CQUNuRixLQUFJLENBQUMsYUFBYSxHQUFHLElBQUksYUFBYSxDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztpQkFDeEU7Z0JBRUQsS0FBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFFaEM7WUFBQyxPQUFPLEdBQUcsRUFBRTtnQkFDVixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDZjtZQUVELEtBQUksQ0FBQyxhQUFhLENBQUMsZUFBZSxHQUFHLFVBQUMsQ0FBQztnQkFDbkMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzdCLENBQUMsQ0FBQztZQUVGLEtBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxHQUFHLFVBQUMsQ0FBQztnQkFDM0IsT0FBTyxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM5QyxDQUFDLENBQUM7WUFFRixLQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sR0FBRztnQkFDekIsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsR0FBRyxLQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQztZQUNsRixDQUFDLENBQUM7WUFFRixLQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sR0FBRztnQkFDeEIsS0FBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3pCLENBQUMsQ0FBQztZQUVGLEtBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxHQUFHO2dCQUN6QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixHQUFHLEtBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFDO1lBQ2pGLENBQUMsQ0FBQztZQUVGLEtBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxHQUFHO2dCQUMxQixPQUFPLENBQUMsR0FBRyxDQUFDLCtCQUErQixHQUFHLEtBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxDQUFDO1lBQ2xGLENBQUMsQ0FBQztZQUVGLEtBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxHQUFHLFVBQUMsQ0FBQztnQkFDN0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUMvQyxDQUFDLENBQUM7WUFFRixLQUFJLENBQUMsS0FBSyxHQUFHLHVDQUFrQixDQUFDLFNBQVMsQ0FBQztZQUMxQyxPQUFPLEVBQUUsQ0FBQztRQUVkLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQU9ELDRCQUFJLEdBQUo7UUFBQSxpQkFlQztRQWRHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUMvQixJQUFJO2dCQUNBLElBQUksS0FBSSxDQUFDLEtBQUssS0FBSyx1Q0FBa0IsQ0FBQyxLQUFLLElBQUksS0FBSSxDQUFDLEtBQUssS0FBSyx1Q0FBa0IsQ0FBQyxRQUFRLEVBQUU7b0JBQ3ZGLE1BQU0sQ0FBQyxLQUFLLENBQUMseUdBQXlHLEdBQUcsS0FBSSxDQUFDLEtBQUssR0FBRyw0Q0FBNEMsQ0FBQyxDQUFDLENBQUM7aUJBQ3hMO2dCQUNELEtBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHO29CQUN4QixLQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7b0JBQ3JCLE9BQU8sRUFBRSxDQUFDO2dCQUNkLENBQUMsQ0FBQztnQkFDRixLQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDO2FBQzdCO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1IsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ2I7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFPRCw2QkFBSyxHQUFMO1FBQUEsaUJBWUM7UUFYRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsSUFBSTtnQkFDQSxJQUFJLEtBQUksQ0FBQyxLQUFLLEtBQUssdUNBQWtCLENBQUMsU0FBUyxFQUFFO29CQUM3QyxNQUFNLENBQUMsS0FBSyxDQUFDLDRGQUE0RixHQUFHLEtBQUksQ0FBQyxLQUFLLEdBQUcsMEVBQTBFLENBQUMsQ0FBQyxDQUFDO2lCQUN6TTtnQkFDRCxLQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUMzQixLQUFJLENBQUMsS0FBSyxHQUFHLHVDQUFrQixDQUFDLE1BQU0sQ0FBQzthQUMxQztZQUFDLE9BQU8sS0FBSyxFQUFFO2dCQUNaLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUNqQjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQU1ELDhCQUFNLEdBQU47UUFBQSxpQkFZQztRQVhHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUMvQixJQUFJO2dCQUNBLElBQUksS0FBSSxDQUFDLEtBQUssS0FBSyx1Q0FBa0IsQ0FBQyxNQUFNLEVBQUU7b0JBQzFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsMEZBQTBGLEdBQUcsS0FBSSxDQUFDLEtBQUssR0FBRyw0Q0FBNEMsQ0FBQyxDQUFDLENBQUM7aUJBQ3pLO2dCQUNELEtBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQzVCLEtBQUksQ0FBQyxLQUFLLEdBQUcsdUNBQWtCLENBQUMsU0FBUyxDQUFDO2FBQzdDO1lBQUMsT0FBTyxLQUFLLEVBQUU7Z0JBQ1osTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQ2pCO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBTUQsK0JBQU8sR0FBUCxVQUFRLGFBQWE7UUFFakIsSUFBSSxJQUFJLENBQUMsS0FBSyxLQUFLLHVDQUFrQixDQUFDLFFBQVEsRUFBRTtZQUM1QyxNQUFNLENBQUMsS0FBSyxDQUFDLDZGQUE2RixHQUFHLElBQUksQ0FBQyxLQUFLLEdBQUcsMkNBQTJDLENBQUMsQ0FBQyxDQUFDO1NBQzNLO1FBRUQsSUFBSSxDQUFDLFlBQVksR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXBELElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBRWxDLElBQUksT0FBTyxhQUFhLEtBQUssUUFBUSxFQUFFO1lBQ25DLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxhQUFhLENBQUM7WUFFekMsSUFBTSxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ2hFLElBQUksZ0JBQWdCLEVBQUU7Z0JBQ2xCLElBQUksQ0FBQyxZQUFZLEdBQUcsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUN2RTtTQUNKO2FBQU07WUFDSCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsYUFBYSxDQUFDLEVBQUUsQ0FBQztZQUM1QyxJQUFJLENBQUMsWUFBWSxHQUFHLGFBQWEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQ3BFO1FBRUQsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQztRQUU3QyxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDN0IsQ0FBQztJQU1ELDZCQUFLLEdBQUw7UUFBQSxpQkFhQztRQVpHLElBQU0sQ0FBQyxHQUFHO1lBQ04sT0FBTyxLQUFJLENBQUMsSUFBSSxDQUFDO1lBQ2pCLEtBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDO1lBQ2pCLEtBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1lBQ2YsT0FBTyxLQUFJLENBQUMsYUFBYSxDQUFDO1lBQzFCLEtBQUksQ0FBQyxLQUFLLEdBQUcsdUNBQWtCLENBQUMsS0FBSyxDQUFDO1FBQzFDLENBQUMsQ0FBQztRQUNGLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyx1Q0FBa0IsQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyx1Q0FBa0IsQ0FBQyxNQUFNLEVBQUU7WUFDekYsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxjQUFNLE9BQUEsQ0FBQyxFQUFFLEVBQUgsQ0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLGNBQU0sT0FBQSxDQUFDLEVBQUUsRUFBSCxDQUFHLENBQUMsQ0FBQztTQUNoRDthQUFNO1lBQ0gsQ0FBQyxFQUFFLENBQUM7U0FDUDtJQUNMLENBQUM7SUFNRCxnQ0FBUSxHQUFSO1FBQ0ksSUFBSSxJQUFJLENBQUMsS0FBSyxLQUFLLHVDQUFrQixDQUFDLFFBQVEsRUFBRTtZQUM1QyxNQUFNLENBQUMsS0FBSyxDQUFDLDhGQUE4RixHQUFHLElBQUksQ0FBQyxLQUFLLEdBQUcsMkNBQTJDLENBQUMsQ0FBQyxDQUFDO1NBQzVLO2FBQU07WUFDSCxJQUFNLENBQUMsR0FBc0IsUUFBUSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN6RCxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7WUFDekIsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFN0IsSUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2xELENBQUMsQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDO1lBQ2IsQ0FBQyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsRUFBRSxHQUFHLE9BQU8sQ0FBQztZQUMvQixDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDVixNQUFNLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUVoQyxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoQztJQUNMLENBQUM7SUFLRCwrQkFBTyxHQUFQO1FBQ0ksSUFBSSxJQUFJLENBQUMsS0FBSyxLQUFLLHVDQUFrQixDQUFDLFFBQVEsRUFBRTtZQUM1QyxNQUFNLENBQUMsS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUMsQ0FBQztTQUN6RTthQUFNO1lBQ0gsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDO1NBQ3BCO0lBQ0wsQ0FBQztJQWFELHNDQUFjLEdBQWQsVUFBZSxRQUFnQixFQUFFLE9BQWE7UUFBOUMsaUJBMkJDO1FBMUJHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUMvQixJQUFJLEtBQUksQ0FBQyxLQUFLLEtBQUssdUNBQWtCLENBQUMsUUFBUSxFQUFFO2dCQUM1QyxNQUFNLENBQUMsS0FBSyxDQUFDLG9HQUFvRyxHQUFHLEtBQUksQ0FBQyxLQUFLLEdBQUcsMkNBQTJDLENBQUMsQ0FBQyxDQUFDO2FBQ2xMO2lCQUFNO2dCQUNILElBQU0sTUFBSSxHQUFHLElBQUksY0FBYyxFQUFFLENBQUM7Z0JBQ2xDLE1BQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFFbEMsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7b0JBQzdCLEtBQWtCLFVBQW9CLEVBQXBCLEtBQUEsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBcEIsY0FBb0IsRUFBcEIsSUFBb0I7d0JBQWpDLElBQU0sR0FBRyxTQUFBO3dCQUNWLE1BQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7cUJBQzVDO2lCQUNKO2dCQUVELE1BQUksQ0FBQyxrQkFBa0IsR0FBRztvQkFDdEIsSUFBSSxNQUFJLENBQUMsVUFBVSxLQUFLLENBQUMsRUFBRTt3QkFDdkIsSUFBSSxNQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUU7NEJBRTFDLE9BQU8sQ0FBQyxNQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7eUJBQzlCOzZCQUFNOzRCQUNILE1BQU0sQ0FBQyxNQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7eUJBQ3ZCO3FCQUNKO2dCQUNMLENBQUMsQ0FBQztnQkFDRixNQUFJLENBQUMsSUFBSSxDQUFDLEtBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUN4QjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQWFELDZDQUFxQixHQUFyQixVQUFzQixRQUFnQixFQUFFLE9BQWE7UUFBckQsaUJBK0JDO1FBOUJHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUMvQixJQUFJLEtBQUksQ0FBQyxLQUFLLEtBQUssdUNBQWtCLENBQUMsUUFBUSxFQUFFO2dCQUM1QyxNQUFNLENBQUMsS0FBSyxDQUFDLDJHQUEyRyxHQUFHLEtBQUksQ0FBQyxLQUFLLEdBQUcsMkNBQTJDLENBQUMsQ0FBQyxDQUFDO2FBQ3pMO2lCQUFNO2dCQUNILElBQU0sTUFBSSxHQUFHLElBQUksY0FBYyxFQUFFLENBQUM7Z0JBQ2xDLE1BQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFFbEMsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7b0JBQzdCLEtBQWtCLFVBQW9CLEVBQXBCLEtBQUEsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBcEIsY0FBb0IsRUFBcEIsSUFBb0I7d0JBQWpDLElBQU0sR0FBRyxTQUFBO3dCQUNWLE1BQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7cUJBQzVDO2lCQUNKO2dCQUVELElBQU0sUUFBUSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ2hDLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEtBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSSxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQUMsQ0FBQztnQkFFdEQsTUFBSSxDQUFDLGtCQUFrQixHQUFHO29CQUN0QixJQUFJLE1BQUksQ0FBQyxVQUFVLEtBQUssQ0FBQyxFQUFFO3dCQUN2QixJQUFJLE1BQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsRUFBRTs0QkFFMUMsT0FBTyxDQUFDLE1BQUksQ0FBQyxZQUFZLENBQUMsQ0FBQzt5QkFDOUI7NkJBQU07NEJBQ0gsTUFBTSxDQUFDLE1BQUksQ0FBQyxNQUFNLENBQUMsQ0FBQzt5QkFDdkI7cUJBQ0o7Z0JBQ0wsQ0FBQyxDQUFDO2dCQUVGLE1BQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDdkI7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFLTyxxQ0FBYSxHQUFyQjtRQUNJLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFFL0UsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFFakIsSUFBSSxDQUFDLGVBQWUsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFN0QsSUFBSSxDQUFDLEtBQUssR0FBRyx1Q0FBa0IsQ0FBQyxRQUFRLENBQUM7SUFDN0MsQ0FBQztJQUVMLG9CQUFDO0FBQUQsQ0FwVkEsQUFvVkMsSUFBQTtBQXBWWSxzQ0FBYTs7Ozs7QUNkMUIsaURBQWdEO0FBQ2hELHlDQUF3QztBQUN4QyxxQ0FBb0M7QUFLcEMseUVBQTJGO0FBQzNGLDZFQUE0RTtBQUU1RSw2RUFBK0U7QUFDL0UsMkZBQTZGO0FBQzdGLGtGQUFvRjtBQUVwRixtQ0FBc0M7QUFPdEM7SUF5QkU7UUFWQSxXQUFNLEdBQUcsRUFBRSxDQUFDO1FBSVosYUFBUSxHQUFHLEtBQUssQ0FBQztRQUlqQiwwQkFBcUIsR0FBa0MsRUFBRSxDQUFDO1FBR3hELE9BQU8sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBTUQsOEJBQVcsR0FBWDtRQUNFLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxpQkFBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2pDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN0QixDQUFDO0lBNEJELGdDQUFhLEdBQWIsVUFBYyxhQUFtQyxFQUFFLE1BQU8sRUFBRSxNQUFPO1FBRWpFLElBQUksVUFBK0IsQ0FBQztRQUVwQyxJQUFJLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxPQUFPLE1BQU0sS0FBSyxVQUFVLENBQUMsRUFBRTtZQUk5QyxVQUFVLEdBQXlCLE1BQU8sQ0FBQztZQUUzQyxVQUFVLEdBQUc7Z0JBQ1gsV0FBVyxFQUFFLENBQUMsT0FBTyxVQUFVLENBQUMsV0FBVyxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxTQUFTO2dCQUNqRyxTQUFTLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxVQUFVLENBQUMsU0FBUyxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7Z0JBQzNKLFVBQVUsRUFBRSxDQUFDLE9BQU8sVUFBVSxDQUFDLFVBQVUsS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sVUFBVSxDQUFDLFVBQVUsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsaUNBQWUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsaUNBQWUsQ0FBQyxNQUFNO2dCQUNwTSxNQUFNLEVBQUUsQ0FBQyxPQUFPLFVBQVUsQ0FBQyxNQUFNLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUk7Z0JBQzdFLFlBQVksRUFBRSxDQUFDLE9BQU8sVUFBVSxDQUFDLFlBQVksS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDL0YsWUFBWSxFQUFFLENBQUMsT0FBTyxVQUFVLENBQUMsWUFBWSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUMvRixVQUFVLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxVQUFVLENBQUMsVUFBVSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7Z0JBQzlKLFdBQVcsRUFBRSxDQUFDLE9BQU8sVUFBVSxDQUFDLFdBQVcsS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsU0FBUzthQUNsRyxDQUFDO1NBQ0g7YUFBTTtZQUlMLFVBQVUsR0FBRztnQkFDWCxVQUFVLEVBQUUsaUNBQWUsQ0FBQyxNQUFNO2dCQUNsQyxNQUFNLEVBQUUsSUFBSTtnQkFDWixZQUFZLEVBQUUsSUFBSTtnQkFDbEIsWUFBWSxFQUFFLElBQUk7Z0JBQ2xCLFVBQVUsRUFBRSxTQUFTO2FBQ3RCLENBQUM7U0FDSDtRQUVELElBQU0sU0FBUyxHQUFjLElBQUkscUJBQVMsQ0FBQyxhQUFhLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRTVFLElBQUksaUJBQXFELENBQUM7UUFDMUQsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsT0FBTyxNQUFNLEtBQUssVUFBVSxDQUFDLEVBQUU7WUFDOUMsaUJBQWlCLEdBQUcsTUFBTSxDQUFDO1NBQzVCO2FBQU0sSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFO1lBQ25CLGlCQUFpQixHQUFHLE1BQU0sQ0FBQztTQUM1QjtRQUVELFNBQVMsQ0FBQyxVQUFVLEVBQUU7YUFDbkIsSUFBSSxDQUFDO1lBQ0osSUFBSSxpQkFBaUIsS0FBSyxTQUFTLEVBQUU7Z0JBQ25DLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQzlCO1lBQ0QsU0FBUyxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDM0MsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUMsS0FBSztZQUNiLElBQUksaUJBQWlCLEtBQUssU0FBUyxFQUFFO2dCQUNuQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUMxQjtZQUNELFNBQVMsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzFDLENBQUMsQ0FBQyxDQUFDO1FBRUwsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQVdELHFDQUFrQixHQUFsQixVQUFtQixhQUFtQyxFQUFFLFVBQWdDO1FBQXhGLGlCQW1CQztRQWxCQyxPQUFPLElBQUksT0FBTyxDQUFZLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFFNUMsSUFBSSxTQUFvQixDQUFDO1lBRXpCLElBQU0sUUFBUSxHQUFHLFVBQUMsS0FBWTtnQkFDNUIsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFO29CQUNYLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDZjtxQkFBTTtvQkFDTCxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7aUJBQ3BCO1lBQ0gsQ0FBQyxDQUFDO1lBRUYsSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFO2dCQUNoQixTQUFTLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLEVBQUUsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2FBQ3JFO2lCQUFNO2dCQUNMLFNBQVMsR0FBRyxLQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsRUFBRSxRQUFRLENBQUMsQ0FBQzthQUN6RDtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQU9ELG9DQUFpQixHQUFqQixVQUFrQixNQUFjO1FBQzlCLE9BQU8sSUFBSSw2QkFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFPRCwwQ0FBdUIsR0FBdkI7UUFDRSxJQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO1FBQzlCLElBQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUM7UUFFakMsSUFBSSxDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sS0FBSyxlQUFlLENBQUM7WUFDekQsQ0FBQyxPQUFPLEtBQUssU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEtBQUssZ0JBQWdCLENBQUMsSUFBSSxDQUFDLE9BQU8sS0FBSyxpQkFBaUIsQ0FBQztZQUM1RixDQUFDLE9BQU8sS0FBSyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sS0FBSyxjQUFjLENBQUM7WUFDckQsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLEVBQUU7WUFDeEIsT0FBTyxDQUFDLENBQUM7U0FDVjthQUFNO1lBQ0wsT0FBTyxDQUFDLENBQUM7U0FDVjtJQUNILENBQUM7SUFNRCw2QkFBVSxHQUFWO1FBQ0UsT0FBTyxJQUFJLE9BQU8sQ0FBVyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQzNDLFNBQVMsQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBQyxXQUFXO2dCQUN6RCxJQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7Z0JBQzdCLFdBQVcsQ0FBQyxPQUFPLENBQUMsVUFBQSxVQUFVO29CQUM1QixJQUFJLFVBQVUsQ0FBQyxJQUFJLEtBQUssWUFBWSxJQUFJLFVBQVUsQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFO3dCQUN4RSxPQUFPLENBQUMsSUFBSSxDQUFDOzRCQUNYLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTs0QkFDckIsUUFBUSxFQUFFLFVBQVUsQ0FBQyxRQUFROzRCQUM3QixLQUFLLEVBQUUsVUFBVSxDQUFDLEtBQUs7eUJBQ3hCLENBQUMsQ0FBQztxQkFDSjtnQkFDSCxDQUFDLENBQUMsQ0FBQztnQkFDSCxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbkIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUMsS0FBSztnQkFDYixPQUFPLENBQUMsS0FBSyxDQUFDLHVCQUF1QixFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUM5QyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFrREQsK0JBQVksR0FBWixVQUFhLE9BQTRCO1FBQXpDLGlCQXVCQztRQXRCQyxPQUFPLElBQUksT0FBTyxDQUFjLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDOUMsS0FBSSxDQUFDLHdCQUF3QixDQUFDLE9BQU8sQ0FBQztpQkFDbkMsSUFBSSxDQUFDLFVBQUEsV0FBVztnQkFDZixTQUFTLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUM7cUJBQzdDLElBQUksQ0FBQyxVQUFBLFdBQVc7b0JBQ2YsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUN2QixDQUFDLENBQUM7cUJBQ0QsS0FBSyxDQUFDLFVBQUEsS0FBSztvQkFDVixJQUFJLFNBQTRCLENBQUM7b0JBQ2pDLElBQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztvQkFDdEMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsRUFBRTt3QkFDdkMsU0FBUyxHQUFHLGlDQUFpQixDQUFDLG9CQUFvQixDQUFDO3FCQUNwRDt5QkFBTTt3QkFDTCxTQUFTLEdBQUcsaUNBQWlCLENBQUMscUJBQXFCLENBQUM7cUJBQ3JEO29CQUNELE1BQU0sQ0FBQyxJQUFJLDZCQUFhLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7Z0JBQ3JELENBQUMsQ0FBQyxDQUFDO1lBQ1AsQ0FBQyxDQUFDO2lCQUNELEtBQUssQ0FBQyxVQUFDLEtBQW9CO2dCQUMxQixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEIsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFPRCxpQ0FBYyxHQUFkO1FBQ0UsT0FBTyxDQUFDLEdBQUcsR0FBRyxjQUFRLENBQUMsQ0FBQztRQUN4QixPQUFPLENBQUMsS0FBSyxHQUFHLGNBQVEsQ0FBQyxDQUFDO1FBQzFCLE9BQU8sQ0FBQyxJQUFJLEdBQUcsY0FBUSxDQUFDLENBQUM7UUFDekIsT0FBTyxDQUFDLElBQUksR0FBRyxjQUFRLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBVUQsMkNBQXdCLEdBQXhCLFVBQXlCLGFBQTRDO1FBQ25FLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxhQUFhLENBQUM7SUFDN0MsQ0FBQztJQVFELDJDQUF3QixHQUF4QixVQUF5QixtQkFBd0M7UUFBakUsaUJBZ0lDO1FBL0hDLE9BQU8sSUFBSSxPQUFPLENBQXlCLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDekQsSUFBSSxLQUFLLEVBQUUsS0FBSyxDQUFDO1lBRWpCLElBQUksbUJBQW1CLENBQUMsV0FBVyxLQUFLLElBQUksSUFBSSxtQkFBbUIsQ0FBQyxXQUFXLEtBQUssS0FBSyxFQUFFO2dCQUN6RixLQUFLLEdBQUcsS0FBSyxDQUFDO2FBQ2Y7aUJBQU0sSUFBSSxtQkFBbUIsQ0FBQyxXQUFXLEtBQUssU0FBUyxFQUFFO2dCQUN4RCxLQUFLLEdBQUcsSUFBSSxDQUFDO2FBQ2Q7aUJBQU07Z0JBQ0wsS0FBSyxHQUFHLG1CQUFtQixDQUFDLFdBQVcsQ0FBQzthQUN6QztZQUVELElBQUksbUJBQW1CLENBQUMsV0FBVyxLQUFLLElBQUksSUFBSSxtQkFBbUIsQ0FBQyxXQUFXLEtBQUssS0FBSyxFQUFFO2dCQUN6RixLQUFLLEdBQUcsS0FBSyxDQUFDO2FBQ2Y7aUJBQU07Z0JBQ0wsS0FBSyxHQUFHO29CQUNOLE1BQU0sRUFBRTt3QkFDTixLQUFLLEVBQUUsR0FBRztxQkFDWDtvQkFDRCxLQUFLLEVBQUU7d0JBQ0wsS0FBSyxFQUFFLEdBQUc7cUJBQ1g7aUJBQ0YsQ0FBQzthQUNIO1lBRUQsSUFBTSxnQkFBZ0IsR0FBMkI7Z0JBQy9DLEtBQUssT0FBQTtnQkFDTCxLQUFLLE9BQUE7YUFDTixDQUFDO1lBRUYsSUFBSSxPQUFPLGdCQUFnQixDQUFDLEtBQUssS0FBSyxRQUFRLEVBQUU7Z0JBQzlDLGdCQUFnQixDQUFDLEtBQUssR0FBRyxFQUFFLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDO2FBQzFFO1lBRUQsSUFBSSxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUU7Z0JBRTFCLElBQUksQ0FBQyxDQUFDLG1CQUFtQixDQUFDLFVBQVUsRUFBRTtvQkFDcEMsSUFBTSxjQUFjLEdBQUcsbUJBQW1CLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDL0UsSUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUN4QyxJQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3hDLGdCQUFnQixDQUFDLEtBQWEsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztvQkFDbkQsZ0JBQWdCLENBQUMsS0FBYSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO2lCQUN2RDtnQkFFRCxJQUFJLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLEVBQUU7b0JBQ2xDLGdCQUFnQixDQUFDLEtBQWEsQ0FBQyxTQUFTLEdBQUcsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLENBQUMsU0FBUyxFQUFFLENBQUM7aUJBQ3RGO2dCQUVELElBQUksQ0FBQyxDQUFDLG1CQUFtQixDQUFDLFdBQVcsSUFBSSxPQUFPLG1CQUFtQixDQUFDLFdBQVcsS0FBSyxRQUFRLEVBQUU7b0JBRTVGLElBQUksbUJBQW1CLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTt3QkFFaEQsSUFBSSxRQUFRLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxRQUFRLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRTs0QkFDN0QsSUFBTSxLQUFLLEdBQUcsSUFBSSw2QkFBYSxDQUFDLGlDQUFpQixDQUFDLDRCQUE0QixFQUFFLDZFQUE2RSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQzs0QkFDL0ssT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQzs0QkFDckIsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO3lCQUNmOzZCQUFNOzRCQUVMLElBQUksQ0FBQyxDQUFDLEtBQUksQ0FBQyxxQkFBcUIsQ0FBQywwQkFBMEIsRUFBRTtnQ0FJM0QsSUFBTSxXQUFXLEdBQUcsS0FBSSxDQUFDLHFCQUFxQixDQUFDLDBCQUEwQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQ0FDcEcsYUFBYSxDQUFDLHdCQUF3QixDQUFDLFdBQVcsRUFBRSxVQUFDLE1BQU07b0NBQ3pELElBQUksTUFBTSxLQUFLLG1CQUFtQixFQUFFO3dDQUNsQyxhQUFhLENBQUMsb0JBQW9CLENBQUMsVUFBQyxLQUFLLEVBQUUsaUJBQWlCOzRDQUMxRCxJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUksS0FBSyxLQUFLLG1CQUFtQixFQUFFO2dEQUM1QyxJQUFNLE9BQUssR0FBRyxJQUFJLDZCQUFhLENBQUMsaUNBQWlCLENBQUMscUJBQXFCLEVBQUUscURBQXFELENBQUMsQ0FBQztnREFDaEksT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFLLENBQUMsQ0FBQztnREFDckIsTUFBTSxDQUFDLE9BQUssQ0FBQyxDQUFDOzZDQUNmO2lEQUFNO2dEQUNMLGdCQUFnQixDQUFDLEtBQUssR0FBRyxpQkFBaUIsQ0FBQztnREFDM0MsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7NkNBQzNCO3dDQUNILENBQUMsQ0FBQyxDQUFDO3FDQUNKO29DQUNELElBQUksTUFBTSxLQUFLLG9CQUFvQixFQUFFO3dDQUNuQyxJQUFNLEtBQUssR0FBRyxJQUFJLDZCQUFhLENBQUMsaUNBQWlCLENBQUMseUJBQXlCLEVBQUUsc0NBQXNDLENBQUMsQ0FBQzt3Q0FDckgsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQzt3Q0FDckIsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO3FDQUNmO29DQUNELElBQUksTUFBTSxLQUFLLGVBQWUsRUFBRTt3Q0FDOUIsSUFBTSxLQUFLLEdBQUcsSUFBSSw2QkFBYSxDQUFDLGlDQUFpQixDQUFDLDhCQUE4QixFQUFXLEtBQUksQ0FBQyxxQkFBcUIsQ0FBQywwQkFBMkIsQ0FBQyxDQUFDO3dDQUNuSixPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO3dDQUNyQixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7cUNBQ2Y7Z0NBQ0gsQ0FBQyxDQUFDLENBQUM7NkJBQ0o7aUNBQU07Z0NBSUwsaUJBQWlCLENBQUMsV0FBVyxDQUFDLFVBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxpQkFBaUI7b0NBQy9ELElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRTt3Q0FDWCxJQUFJLEtBQUssS0FBSyxlQUFlLEVBQUU7NENBQzdCLElBQU0sT0FBSyxHQUFHLElBQUksNkJBQWEsQ0FBQyxpQ0FBaUIsQ0FBQyw4QkFBOEIsRUFBRSw2RkFBNkYsQ0FBQyxDQUFDOzRDQUNqTCxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQUssQ0FBQyxDQUFDOzRDQUNyQixNQUFNLENBQUMsT0FBSyxDQUFDLENBQUM7eUNBQ2Y7NkNBQU0sSUFBSSxLQUFLLEtBQUssb0JBQW9CLEVBQUU7NENBQ3pDLElBQU0sT0FBSyxHQUFHLElBQUksNkJBQWEsQ0FBQyxpQ0FBaUIsQ0FBQyx5QkFBeUIsRUFBRSxzQ0FBc0MsQ0FBQyxDQUFDOzRDQUNySCxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQUssQ0FBQyxDQUFDOzRDQUNyQixNQUFNLENBQUMsT0FBSyxDQUFDLENBQUM7eUNBQ2Y7NkNBQU0sSUFBSSxLQUFLLEtBQUssbUJBQW1CLEVBQUU7NENBQ3hDLElBQU0sT0FBSyxHQUFHLElBQUksNkJBQWEsQ0FBQyxpQ0FBaUIsQ0FBQyxxQkFBcUIsRUFBRSxxREFBcUQsQ0FBQyxDQUFDOzRDQUNoSSxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQUssQ0FBQyxDQUFDOzRDQUNyQixNQUFNLENBQUMsT0FBSyxDQUFDLENBQUM7eUNBQ2Y7cUNBQ0Y7eUNBQU07d0NBQ0wsZ0JBQWdCLENBQUMsS0FBSyxHQUFHLGlCQUFpQixDQUFDLEtBQUssQ0FBQzt3Q0FDakQsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7cUNBQzNCO2dDQUNILENBQUMsQ0FBQyxDQUFDOzZCQUNKOzRCQUVELG1CQUFtQixDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUM7eUJBRTVDO3FCQUNGO3lCQUFNO3dCQUVMLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsQ0FBQzt3QkFDaEYsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7cUJBQzNCO2lCQUNGO3FCQUFNO29CQUNMLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO2lCQUMzQjthQUNGO2lCQUFNO2dCQUNMLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO2FBQzNCO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBS0QsMEJBQU8sR0FBUCxVQUFRLGVBQXVDO1FBQzdDLElBQU0sTUFBTSxHQUFHO1lBQ2IsU0FBUyxFQUFFLElBQUk7WUFDZixnQkFBZ0IsRUFBRSxLQUFLO1lBQ3ZCLEVBQUUsRUFBRTtnQkFDRixHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUs7Z0JBQ2YsU0FBUyxFQUFFLEtBQUs7Z0JBQ2hCLFdBQVcsRUFBRSxlQUFlO2dCQUM1QixZQUFZLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7Z0JBQ2hELGNBQWMsRUFBRSxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztnQkFDcEQsYUFBYSxFQUFFLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2FBQ25EO1lBQ0QsR0FBRyxFQUFFO2dCQUNILGNBQWMsRUFBRSxLQUFLO2dCQUNyQixpQkFBaUIsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO2dCQUN0RSxvQkFBb0IsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO2dCQUM1RSxzQkFBc0IsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO2dCQUNoRixlQUFlLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDbEUsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDeEUsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDcEUsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDcEUsV0FBVyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO2dCQUN6RCxZQUFZLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDOUQsVUFBVSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO2FBQ3pEO1NBQ0YsQ0FBQztRQUNGLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBS0QsMEJBQU8sR0FBUDtRQUNFLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUtELDhCQUFXLEdBQVgsVUFBWSxNQUFjLEVBQUUsTUFBVyxFQUFFLFFBQVM7UUFDaEQsSUFBSSxNQUFNLElBQUksTUFBTSxZQUFZLFFBQVEsRUFBRTtZQUN4QyxRQUFRLEdBQUcsTUFBTSxDQUFDO1lBQ2xCLE1BQU0sR0FBRyxFQUFFLENBQUM7U0FDYjtRQUNELE9BQU8sQ0FBQyxLQUFLLENBQUMsNEJBQTRCLEdBQUcsTUFBTSxHQUFHLGFBQWEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ3BHLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUtELHFDQUFrQixHQUFsQixVQUFtQixXQUFnQjtRQUNqQyxJQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxXQUFXO1lBQ3ZCLFdBQVcsQ0FBQyxPQUFPLEtBQUssU0FBUyxJQUFJLE9BQU8sV0FBVyxDQUFDLE9BQU8sS0FBSyxTQUFTO1lBQzdFLFdBQVcsQ0FBQyxFQUFFLEtBQUssU0FBUyxJQUFJLE9BQU8sV0FBVyxDQUFDLEVBQUUsS0FBSyxRQUFRO1lBQ2xFLFdBQVcsQ0FBQyxJQUFJLEtBQUssU0FBUyxJQUFJLE9BQU8sV0FBVyxDQUFDLElBQUksS0FBSyxRQUFRO1lBQ3RFLFdBQVcsQ0FBQyxLQUFLLEtBQUssU0FBUyxJQUFJLE9BQU8sV0FBVyxDQUFDLEtBQUssS0FBSyxRQUFRO1lBQ3hFLFdBQVcsQ0FBQyxLQUFLLEtBQUssU0FBUyxJQUFJLE9BQU8sV0FBVyxDQUFDLEtBQUssS0FBSyxTQUFTO1lBQ3pFLFdBQVcsQ0FBQyxVQUFVLEtBQUssU0FBUyxJQUFJLE9BQU8sV0FBVyxDQUFDLFVBQVUsS0FBSyxRQUFRLENBQUMsQ0FBQztRQUN0RixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFLRCwyQkFBUSxHQUFSO1FBQ0UsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3BCLENBQUM7SUFLRCw0QkFBUyxHQUFUO1FBQ0UsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFLRCw4QkFBVyxHQUFYO1FBQ0UsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFLTyxxQ0FBa0IsR0FBMUI7UUFDRSxPQUFPLENBQUMsSUFBSSxDQUFDLDJCQUEyQixDQUFDLENBQUM7UUFDMUMsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFLEVBQUU7WUFDMUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1NBQ2pDO2FBQU07WUFDTCxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztTQUNoRDtJQUNILENBQUM7SUFFTyx1Q0FBb0IsR0FBNUI7UUFDRSxPQUFPLENBQUMsSUFBSSxDQUFDLDBDQUEwQyxDQUFDLENBQUM7UUFDekQsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFLEVBQUU7WUFDMUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1NBQ2pDO2FBQU07WUFDTCxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztTQUNoRDtJQUNILENBQUM7SUFFTyxzQ0FBbUIsR0FBM0I7UUFDRSxPQUFPLENBQUMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVPLGtDQUFlLEdBQXZCO1FBQ0UsSUFBSSxJQUFJLENBQUMsT0FBTyxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsT0FBTyxZQUFZLGlCQUFPLEVBQUU7WUFDakUsT0FBTyxJQUFJLENBQUM7U0FDYjthQUFNO1lBQ0wsT0FBTyxDQUFDLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO1lBQzNDLE9BQU8sS0FBSyxDQUFDO1NBQ2Q7SUFDSCxDQUFDO0lBRUgsZUFBQztBQUFELENBOWlCQSxBQThpQkMsSUFBQTtBQTlpQlksNEJBQVE7Ozs7Ozs7Ozs7Ozs7OztBQ3BCckIscUNBQW9DO0FBQ3BDLG1DQUFrQztBQUNsQyxpREFBZ0Q7QUFNaEQsc0VBQXFFO0FBQ3JFLGtGQUFpRjtBQUNqRix5RUFBMkY7QUFPM0Y7SUFBK0IsNkJBQWE7SUF3QnhDLG1CQUFZLE1BQTRCLEVBQUUsVUFBK0IsRUFBVSxRQUFrQjtRQUFyRyxZQUNJLGtCQUFNLElBQUksZUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxpQkFBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUUsbUJBQW1CLEVBQUUsVUFBVSxFQUFFLGdCQUFnQixFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsTUFBTSxDQUFDLFNBUXhKO1FBVGtGLGNBQVEsR0FBUixRQUFRLENBQVU7UUFuQnJHLG1CQUFhLEdBQUcsS0FBSyxDQUFDO1FBS3RCLDBCQUFvQixHQUFHLEtBQUssQ0FBQztRQU9yQixrQkFBWSxHQUFHLEtBQUssQ0FBQztRQVN6QixLQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUU3QixLQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsc0NBQXNDLEVBQUUsVUFBQyxNQUFjO1lBQ3JFLElBQU0sV0FBVyxHQUFHLElBQUkseUJBQVcsQ0FBQyxJQUFJLEVBQUUsS0FBSSxFQUFFLGlCQUFpQixFQUFFLEtBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDeEYsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1lBQ3BELFdBQVcsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQ3ZDLENBQUMsQ0FBQyxDQUFDOztJQUNQLENBQUM7SUFPRCxnQ0FBWSxHQUFaLFVBQWEsS0FBYztRQUN2QixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDakQsT0FBTyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ25HLENBQUM7SUFPRCxnQ0FBWSxHQUFaLFVBQWEsS0FBYztRQUN2QixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDakQsT0FBTyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ25HLENBQUM7SUFNRCxxQ0FBaUIsR0FBakIsVUFBa0IsS0FBZTtRQUM3QixLQUFLLEdBQUcsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQzdDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxLQUFLLENBQUM7UUFDbEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBTUQsc0JBQUUsR0FBRixVQUFHLElBQVksRUFBRSxPQUErQjtRQUFoRCxpQkErQkM7UUE5QkcsaUJBQU0sRUFBRSxZQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN4QixJQUFJLElBQUksS0FBSyxlQUFlLEVBQUU7WUFDMUIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLHNCQUFzQixFQUFFO2dCQUNyRCxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxJQUFJLHlCQUFXLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDeEc7aUJBQU07Z0JBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLDZCQUE2QixFQUFFO29CQUM3QyxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxJQUFJLHlCQUFXLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSxlQUFlLEVBQUUsS0FBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3pHLENBQUMsQ0FBQyxDQUFDO2FBQ047U0FDSjtRQUNELElBQUksSUFBSSxLQUFLLG9CQUFvQixFQUFFO1lBQy9CLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSztnQkFDdkUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsV0FBVyxHQUFHLENBQUM7Z0JBQ3BDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sS0FBSyxLQUFLO2dCQUNyQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssS0FBSztnQkFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBVSxLQUFLLENBQUMsRUFBRTtnQkFDdkMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxJQUFJLHFDQUFpQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN0SDtTQUNKO1FBQ0QsSUFBSSxJQUFJLEtBQUssZUFBZSxFQUFFO1lBQzFCLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRTtnQkFDcEIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLENBQUM7YUFDdEM7U0FDSjtRQUNELElBQUksSUFBSSxLQUFLLGNBQWMsRUFBRTtZQUN6QixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7Z0JBQ25CLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxDQUFDO2FBQ3JDO1NBQ0o7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBTUQsd0JBQUksR0FBSixVQUFLLElBQVksRUFBRSxPQUErQjtRQUFsRCxpQkErQkM7UUE5QkcsaUJBQU0sSUFBSSxZQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMxQixJQUFJLElBQUksS0FBSyxlQUFlLEVBQUU7WUFDMUIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLHNCQUFzQixFQUFFO2dCQUNyRCxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxJQUFJLHlCQUFXLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDeEc7aUJBQU07Z0JBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLDZCQUE2QixFQUFFO29CQUMvQyxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxJQUFJLHlCQUFXLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSxlQUFlLEVBQUUsS0FBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3pHLENBQUMsQ0FBQyxDQUFDO2FBQ047U0FDSjtRQUNELElBQUksSUFBSSxLQUFLLG9CQUFvQixFQUFFO1lBQy9CLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSztnQkFDdkUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsV0FBVyxHQUFHLENBQUM7Z0JBQ3BDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sS0FBSyxLQUFLO2dCQUNyQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssS0FBSztnQkFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBVSxLQUFLLENBQUMsRUFBRTtnQkFDdkMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxJQUFJLHFDQUFpQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN0SDtTQUNKO1FBQ0QsSUFBSSxJQUFJLEtBQUssZUFBZSxFQUFFO1lBQzFCLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRTtnQkFDcEIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLENBQUM7YUFDdEM7U0FDSjtRQUNELElBQUksSUFBSSxLQUFLLGNBQWMsRUFBRTtZQUN6QixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7Z0JBQ25CLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxDQUFDO2FBQ3JDO1NBQ0o7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBUUQsOEJBQVUsR0FBVjtRQUFBLGlCQXFMQztRQXBMRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFFL0IsSUFBTSxhQUFhLEdBQUcsVUFBQyxhQUE0QjtnQkFDL0MsS0FBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7Z0JBQ3pCLEtBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO2dCQUMzQixNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDMUIsQ0FBQyxDQUFDO1lBRUYsSUFBTSxlQUFlLEdBQUcsVUFBQyxXQUF3QjtnQkFDN0MsS0FBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7Z0JBQzFCLEtBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO2dCQUUxQixJQUFJLEtBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsS0FBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsRUFBRTtvQkFDL0QsV0FBVyxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDekQsV0FBVyxDQUFDLFFBQVEsQ0FBb0IsS0FBSSxDQUFDLFVBQVUsQ0FBQyxXQUFZLENBQUMsQ0FBQztpQkFDekU7Z0JBRUQsSUFBSSxLQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLEtBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEVBQUU7b0JBQy9ELFdBQVcsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3pELFdBQVcsQ0FBQyxRQUFRLENBQW9CLEtBQUksQ0FBQyxVQUFVLENBQUMsV0FBWSxDQUFDLENBQUM7aUJBQ3pFO2dCQUdELElBQUksQ0FBQyxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTtvQkFDbkMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUM7aUJBQy9HO2dCQUNELElBQUksQ0FBQyxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTtvQkFDbkMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUM7aUJBQy9HO2dCQUVELEtBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUN4QyxJQUFJLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsRUFBRTtvQkFHaEMsS0FBSSxDQUFDLE1BQU0sQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO2lCQUMzQztnQkFDRCxLQUFJLENBQUMsTUFBTSxDQUFDLDJCQUEyQixHQUFHLElBQUksQ0FBQztnQkFDL0MsS0FBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLHlCQUF5QixFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUV4RCxJQUFJLENBQUMsQ0FBQyxLQUFJLENBQUMsaUJBQWlCLEVBQUU7b0JBQzFCLEtBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxFQUFtQixLQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2lCQUM5RztnQkFDRCxPQUFPLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQztnQkFFOUIsT0FBTyxFQUFFLENBQUM7WUFDZCxDQUFDLENBQUM7WUFFRixLQUFJLENBQUMsUUFBUSxDQUFDLHdCQUF3QixDQUFDLEtBQUksQ0FBQyxVQUFVLENBQUM7aUJBQ2xELElBQUksQ0FBQyxVQUFBLFdBQVc7Z0JBRWIsSUFBTSxxQkFBcUIsR0FBRztvQkFDMUIsZ0JBQWdCLEVBQUUsV0FBVztvQkFDN0IsbUJBQW1CLEVBQUUsS0FBSSxDQUFDLFVBQVU7aUJBQ3ZDLENBQUM7Z0JBRUYsS0FBSSxDQUFDLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO2dCQUU1RCxJQUFNLGNBQWMsR0FBMkIsRUFBRSxDQUFDO2dCQUNsRCxJQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQztnQkFFaEMsSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLEVBQUU7b0JBQ3hELElBQU0sd0JBQXNCLEdBQUcsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUM5RixjQUFjLENBQUMsS0FBSyxHQUFHLEtBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsd0JBQXNCLENBQUM7b0JBQ25GLGNBQWMsQ0FBQyxLQUFLLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQztvQkFDekMsSUFBSSxXQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO29CQUMzQixLQUFJLENBQUMsd0JBQXdCLENBQUMsa0JBQWtCLENBQUMsQ0FBQztvQkFFbEQsU0FBUyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDO3lCQUM5QyxJQUFJLENBQUMsVUFBQSxXQUFXO3dCQUNiLEtBQUksQ0FBQywwQkFBMEIsQ0FBQyxXQUFTLEVBQUUsa0JBQWtCLENBQUMsQ0FBQzt3QkFFL0QsSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLEVBQUU7NEJBRXpELGNBQWMsQ0FBQyxLQUFLLEdBQUcsd0JBQXNCLENBQUM7NEJBQzlDLGNBQWMsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDOzRCQUM3QixXQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDOzRCQUN2QixLQUFJLENBQUMsd0JBQXdCLENBQUMsa0JBQWtCLENBQUMsQ0FBQzs0QkFFbEQsU0FBUyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDO2lDQUM5QyxJQUFJLENBQUMsVUFBQSxlQUFlO2dDQUNqQixLQUFJLENBQUMsMEJBQTBCLENBQUMsV0FBUyxFQUFFLGtCQUFrQixDQUFDLENBQUM7Z0NBQy9ELFdBQVcsQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0NBQzFELGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBQzs0QkFDakMsQ0FBQyxDQUFDO2lDQUNELEtBQUssQ0FBQyxVQUFBLEtBQUs7Z0NBQ1IsS0FBSSxDQUFDLDBCQUEwQixDQUFDLFdBQVMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO2dDQUMvRCxJQUFJLFNBQVMsRUFBRSxZQUFZLENBQUM7Z0NBQzVCLFFBQVEsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRTtvQ0FDOUIsS0FBSyxlQUFlO3dDQUNoQixTQUFTLEdBQUcsaUNBQWlCLENBQUMsNEJBQTRCLENBQUM7d0NBQzNELFlBQVksR0FBRyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7d0NBQ2hDLGFBQWEsQ0FBQyxJQUFJLDZCQUFhLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7d0NBQzFELE1BQU07b0NBQ1YsS0FBSyxpQkFBaUI7d0NBQ2xCLFNBQVMsR0FBRyxpQ0FBaUIsQ0FBQyxvQkFBb0IsQ0FBQzt3Q0FDbkQsWUFBWSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQzt3Q0FDaEMsYUFBYSxDQUFDLElBQUksNkJBQWEsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQzt3Q0FDMUQsTUFBTTtvQ0FDVixLQUFLLHNCQUFzQjt3Q0FDdkIsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxLQUFLLFVBQVUsRUFBRTs0Q0FDL0MsU0FBUyxHQUFHLGlDQUFpQixDQUFDLDRCQUE0QixDQUFDOzRDQUMzRCxZQUFZLEdBQUcsb0NBQW9DLEdBQTBELFdBQVcsQ0FBQyxLQUFNLENBQUMsUUFBVyxDQUFDLEtBQUssR0FBRyxhQUFhLENBQUM7eUNBQ3JLOzZDQUFNOzRDQUNILFNBQVMsR0FBRyxpQ0FBaUIsQ0FBQywwQkFBMEIsQ0FBQzs0Q0FDekQsWUFBWSxHQUFHLHNFQUFzRSxHQUFHLEtBQUssQ0FBQyxVQUFVLEdBQUcsR0FBRyxDQUFDO3lDQUNsSDt3Q0FDRCxhQUFhLENBQUMsSUFBSSw2QkFBYSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO3dDQUMxRCxNQUFNO2lDQUNiOzRCQUNMLENBQUMsQ0FBQyxDQUFDO3lCQUNWOzZCQUFNOzRCQUNILGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBQzt5QkFDaEM7b0JBQ0wsQ0FBQyxDQUFDO3lCQUNELEtBQUssQ0FBQyxVQUFBLEtBQUs7d0JBQ1IsS0FBSSxDQUFDLDBCQUEwQixDQUFDLFdBQVMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO3dCQUMvRCxJQUFJLFNBQVMsRUFBRSxZQUFZLENBQUM7d0JBQzVCLFFBQVEsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRTs0QkFDOUIsS0FBSyxlQUFlO2dDQUNoQixTQUFTLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQztvQ0FDaEMsS0FBSyxFQUFFLEtBQUs7b0NBQ1osS0FBSyxFQUFFLFdBQVcsQ0FBQyxLQUFLO2lDQUMzQixDQUFDO3FDQUNHLElBQUksQ0FBQyxVQUFBLFdBQVc7b0NBQ2IsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFDLEtBQUs7d0NBQ3ZDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQ0FDakIsQ0FBQyxDQUFDLENBQUM7b0NBQ0gsU0FBUyxHQUFHLGlDQUFpQixDQUFDLDRCQUE0QixDQUFDO29DQUMzRCxZQUFZLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO29DQUNoQyxhQUFhLENBQUMsSUFBSSw2QkFBYSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO2dDQUM5RCxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBQSxDQUFDO29DQUNOLFNBQVMsR0FBRyxpQ0FBaUIsQ0FBQyw0QkFBNEIsQ0FBQztvQ0FDM0QsWUFBWSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztvQ0FDaEMsYUFBYSxDQUFDLElBQUksNkJBQWEsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztnQ0FDOUQsQ0FBQyxDQUFDLENBQUM7Z0NBQ1AsTUFBTTs0QkFDVixLQUFLLGlCQUFpQjtnQ0FDbEIsU0FBUyxHQUFHLEtBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLGlDQUFpQixDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxpQ0FBaUIsQ0FBQyxvQkFBb0IsQ0FBQztnQ0FDMUgsWUFBWSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQ0FDaEMsYUFBYSxDQUFDLElBQUksNkJBQWEsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztnQ0FDMUQsTUFBTTs0QkFDVixLQUFLLHNCQUFzQjtnQ0FDdkIsU0FBUyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUM7b0NBQ2hDLEtBQUssRUFBRSxLQUFLO29DQUNaLEtBQUssRUFBRSxXQUFXLENBQUMsS0FBSztpQ0FDM0IsQ0FBQztxQ0FDRyxJQUFJLENBQUMsVUFBQSxXQUFXO29DQUNiLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBQyxLQUFLO3dDQUN2QyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7b0NBQ2pCLENBQUMsQ0FBQyxDQUFDO29DQUNILElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsS0FBSyxVQUFVLEVBQUU7d0NBQy9DLFNBQVMsR0FBRyxpQ0FBaUIsQ0FBQyw0QkFBNEIsQ0FBQzt3Q0FDM0QsWUFBWSxHQUFHLG9DQUFvQyxHQUEwRCxXQUFXLENBQUMsS0FBTSxDQUFDLFFBQVcsQ0FBQyxLQUFLLEdBQUcsYUFBYSxDQUFDO3FDQUNySzt5Q0FBTTt3Q0FDSCxTQUFTLEdBQUcsaUNBQWlCLENBQUMsMEJBQTBCLENBQUM7d0NBQ3pELFlBQVksR0FBRyxzRUFBc0UsR0FBRyxLQUFLLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQztxQ0FDbEg7b0NBQ0QsYUFBYSxDQUFDLElBQUksNkJBQWEsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztnQ0FDOUQsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUEsQ0FBQztvQ0FDTixJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLEtBQUssVUFBVSxFQUFFO3dDQUMvQyxTQUFTLEdBQUcsaUNBQWlCLENBQUMsNEJBQTRCLENBQUM7d0NBQzNELFlBQVksR0FBRyxvQ0FBb0MsR0FBMEQsV0FBVyxDQUFDLEtBQU0sQ0FBQyxRQUFXLENBQUMsS0FBSyxHQUFHLGFBQWEsQ0FBQztxQ0FDcks7eUNBQU07d0NBQ0gsU0FBUyxHQUFHLGlDQUFpQixDQUFDLDBCQUEwQixDQUFDO3dDQUN6RCxZQUFZLEdBQUcsc0VBQXNFLEdBQUcsS0FBSyxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUM7cUNBQ2xIO29DQUNELGFBQWEsQ0FBQyxJQUFJLDZCQUFhLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7Z0NBQzlELENBQUMsQ0FBQyxDQUFDO2dDQUNQLE1BQU07eUJBQ2I7b0JBQ0wsQ0FBQyxDQUFDLENBQUM7aUJBQ1Y7cUJBQU07b0JBQ0gsTUFBTSxDQUFDLElBQUksNkJBQWEsQ0FBQyxpQ0FBaUIsQ0FBQyxtQkFBbUIsRUFDMUQsa0lBQWtJLENBQUMsQ0FBQyxDQUFDO2lCQUM1STtZQUNMLENBQUMsQ0FBQztpQkFDRCxLQUFLLENBQUMsVUFBQyxLQUFvQjtnQkFDeEIsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pCLENBQUMsQ0FBQyxDQUFDO1FBQ1gsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBS0QsaUNBQWEsR0FBYixVQUFjLE9BQWdCO1FBQzFCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztJQUNsQyxDQUFDO0lBS0QsNkJBQVMsR0FBVCxVQUFVLElBQVksRUFBRSxVQUFpQjtRQUNyQyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUtELGlEQUE2QixHQUE3QjtRQUNJLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsZUFBZSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUNsRCxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztTQUNuQztJQUNMLENBQUM7SUFLTyw0Q0FBd0IsR0FBaEMsVUFBaUMsUUFBZ0I7UUFBakQsaUJBSUM7UUFIRyxJQUFJLENBQUMsdUJBQXVCLEdBQUcsVUFBVSxDQUFDO1lBQ3RDLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLG9CQUFvQixFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2hELENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNqQixDQUFDO0lBRU8sOENBQTBCLEdBQWxDLFVBQW1DLFNBQWlCLEVBQUUsUUFBZ0I7UUFDbEUsWUFBWSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsU0FBUyxDQUFDLEdBQUcsUUFBUSxFQUFFO1lBRXJDLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLG9CQUFvQixFQUFFLEVBQUUsQ0FBQyxDQUFDO1NBQy9DO0lBQ0wsQ0FBQztJQUVMLGdCQUFDO0FBQUQsQ0FqWEEsQUFpWEMsQ0FqWDhCLDZCQUFhLEdBaVgzQztBQWpYWSw4QkFBUzs7Ozs7QUNsQnRCLDJDQUEwQztBQUsxQywyQ0FBMEM7QUFPMUMsOEVBQTZFO0FBRTdFLDRFQUEyRTtBQUMzRSxnR0FBK0Y7QUFDL0Ysc0VBQXFFO0FBQ3JFLHNFQUFxRTtBQUNyRSx5RUFBMkY7QUFDM0YsNkVBQTRFO0FBRTVFLG1DQUFzQztBQUN0QyxtREFBc0Q7QUFRdEQ7SUE2Q0ksaUJBQVksUUFBa0I7UUE5QjlCLG1CQUFjLEdBQW9CLEVBQUUsQ0FBQztRQU1yQyx5QkFBb0IsR0FBb0IsRUFBRSxDQUFDO1FBSzNDLHNCQUFpQixHQUF1QixFQUFFLENBQUM7UUFZM0MsMEJBQXFCLEdBQUcsS0FBSyxDQUFDO1FBRXRCLE9BQUUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBTTVCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO0lBQzdCLENBQUM7SUFnQ0QseUJBQU8sR0FBUCxVQUFRLEtBQWEsRUFBRSxRQUFjO1FBQXJDLGlCQXFCQztRQXBCRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFFL0IsS0FBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUV6QixJQUFJLEtBQUksQ0FBQyxRQUFRLENBQUMsdUJBQXVCLEVBQUUsRUFBRTtnQkFFekMsS0FBSSxDQUFDLE9BQU8sR0FBRztvQkFDWCxTQUFTLEVBQUUsS0FBSSxDQUFDLFNBQVM7b0JBQ3pCLGFBQWEsRUFBRSxLQUFLO29CQUNwQixRQUFRLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO2lCQUNsRSxDQUFDO2dCQUNGLEtBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDO29CQUN4QixPQUFPLEVBQUUsQ0FBQztnQkFDZCxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBQSxLQUFLO29CQUNWLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDbEIsQ0FBQyxDQUFDLENBQUM7YUFDTjtpQkFBTTtnQkFDSCxNQUFNLENBQUMsSUFBSSw2QkFBYSxDQUFDLGlDQUFpQixDQUFDLHFCQUFxQixFQUFFLFVBQVUsR0FBRyxRQUFRLENBQUMsSUFBSSxHQUFHLEdBQUcsR0FBRyxRQUFRLENBQUMsT0FBTyxHQUFHLCtCQUErQixDQUFDLENBQUMsQ0FBQzthQUM3SjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQTZCRCw0QkFBVSxHQUFWO1FBQ0ksSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQXNCRCwyQkFBUyxHQUFULFVBQVUsTUFBYyxFQUFFLGFBQW1DLEVBQUUsTUFBb0UsRUFBRSxNQUE2QztRQUM5SyxJQUFJLFVBQVUsR0FBeUIsRUFBRSxDQUFDO1FBQzFDLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxPQUFPLE1BQU0sS0FBSyxVQUFVLEVBQUU7WUFDMUMsVUFBVSxHQUFHO2dCQUNULFVBQVUsRUFBRSxDQUFDLE9BQU8sTUFBTSxDQUFDLFVBQVUsS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sTUFBTSxDQUFDLFVBQVUsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsaUNBQWUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsaUNBQWUsQ0FBQyxNQUFNO2dCQUN4TCxnQkFBZ0IsRUFBRSxDQUFDLE9BQU8sTUFBTSxDQUFDLGdCQUFnQixLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLElBQUk7Z0JBQ25HLGdCQUFnQixFQUFFLENBQUMsT0FBTyxNQUFNLENBQUMsZ0JBQWdCLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsSUFBSTthQUN0RyxDQUFDO1NBQ0w7YUFBTTtZQUNILFVBQVUsR0FBRztnQkFDVCxVQUFVLEVBQUUsaUNBQWUsQ0FBQyxNQUFNO2dCQUNsQyxnQkFBZ0IsRUFBRSxJQUFJO2dCQUN0QixnQkFBZ0IsRUFBRSxJQUFJO2FBQ3pCLENBQUM7U0FDTDtRQUVELElBQUksaUJBQXFELENBQUM7UUFDMUQsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsT0FBTyxNQUFNLEtBQUssVUFBVSxDQUFDLEVBQUU7WUFDNUMsaUJBQWlCLEdBQUcsTUFBTSxDQUFDO1NBQzlCO2FBQU0sSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFO1lBQ2pCLGlCQUFpQixHQUFHLE1BQU0sQ0FBQztTQUM5QjtRQUVELE9BQU8sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUVqRSxNQUFNLENBQUMsU0FBUyxFQUFFO2FBQ2IsSUFBSSxDQUFDO1lBQ0YsT0FBTyxDQUFDLElBQUksQ0FBQywwQkFBMEIsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzFFLElBQUksaUJBQWlCLEtBQUssU0FBUyxFQUFFO2dCQUNqQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQzthQUNoQztRQUNMLENBQUMsQ0FBQzthQUNELEtBQUssQ0FBQyxVQUFBLEtBQUs7WUFDUixJQUFJLGlCQUFpQixLQUFLLFNBQVMsRUFBRTtnQkFDakMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDNUI7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUNQLElBQU0sVUFBVSxHQUFHLElBQUksdUJBQVUsQ0FBQyxNQUFNLEVBQUUsYUFBYSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ3JFLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUU7WUFDNUIsTUFBTSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFtQixVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7U0FDN0c7UUFDRCxPQUFPLFVBQVUsQ0FBQztJQUN0QixDQUFDO0lBU0QsZ0NBQWMsR0FBZCxVQUFlLE1BQWMsRUFBRSxhQUFtQyxFQUFFLFVBQWlDO1FBQXJHLGlCQW9CQztRQW5CRyxPQUFPLElBQUksT0FBTyxDQUFhLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFFM0MsSUFBSSxVQUFzQixDQUFDO1lBRTNCLElBQU0sUUFBUSxHQUFHLFVBQUMsS0FBWTtnQkFDMUIsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFO29CQUNULE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDakI7cUJBQU07b0JBQ0gsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2lCQUN2QjtZQUNMLENBQUMsQ0FBQztZQUVGLElBQUksQ0FBQyxDQUFDLFVBQVUsRUFBRTtnQkFDZCxVQUFVLEdBQUcsS0FBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQzthQUM1RTtpQkFBTTtnQkFDSCxVQUFVLEdBQUcsS0FBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsYUFBYSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2FBQ2hFO1FBRUwsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBYUQsNkJBQVcsR0FBWCxVQUFZLFVBQXNCO1FBQzlCLElBQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQztRQUUvRCxPQUFPLENBQUMsSUFBSSxDQUFDLHFCQUFxQixHQUFHLFlBQVksQ0FBQyxDQUFDO1FBRW5ELElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUNyQixzQkFBc0IsRUFDdEIsRUFBRSxNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLEVBQ3JELFVBQUMsS0FBSyxFQUFFLFFBQVE7WUFDWixJQUFJLEtBQUssRUFBRTtnQkFDUCxPQUFPLENBQUMsS0FBSyxDQUFDLDJCQUEyQixHQUFHLFlBQVksRUFBRSxLQUFLLENBQUMsQ0FBQzthQUNwRTtpQkFBTTtnQkFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLDhCQUE4QixHQUFHLFlBQVksQ0FBQyxDQUFDO2FBQy9EO1lBQ0QsVUFBVSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQ3RDLFVBQVUsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUMzQyxDQUFDLENBQ0osQ0FBQztRQUNGLFVBQVUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQ3RELENBQUM7SUFnQkQseUJBQU8sR0FBUCxVQUFRLFNBQW9CO1FBQTVCLGlCQWlDQztRQWhDRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsU0FBUyxDQUFDLE9BQU8sR0FBRyxLQUFJLENBQUM7WUFDekIsU0FBUyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsS0FBSSxDQUFDO1lBRWhDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLHNCQUFzQixFQUFFO2dCQUUxQyxLQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzVDLFNBQVMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO3FCQUNyQixJQUFJLENBQUM7b0JBQ0YsT0FBTyxFQUFFLENBQUM7Z0JBQ2QsQ0FBQyxDQUFDO3FCQUNELEtBQUssQ0FBQyxVQUFBLEtBQUs7b0JBQ1IsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNsQixDQUFDLENBQUMsQ0FBQzthQUNWO2lCQUFNO2dCQUVILFNBQVMsQ0FBQyxVQUFVLEVBQUU7cUJBQ2pCLElBQUksQ0FBQztvQkFDRixLQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7b0JBQzVDLFNBQVMsQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO29CQUMxQyxTQUFTLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTt5QkFDckIsSUFBSSxDQUFDO3dCQUNGLE9BQU8sRUFBRSxDQUFDO29CQUNkLENBQUMsQ0FBQzt5QkFDRCxLQUFLLENBQUMsVUFBQSxLQUFLO3dCQUNSLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDbEIsQ0FBQyxDQUFDLENBQUM7Z0JBQ1gsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUMsS0FBSztvQkFDWCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ2xCLENBQUMsQ0FBQyxDQUFDO2FBQ1Y7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFzQkQsMkJBQVMsR0FBVCxVQUFVLFNBQW9CO1FBRTFCLElBQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7UUFFaEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUU7WUFDcEIsT0FBTyxDQUFDLEtBQUssQ0FBQyw0REFBNEQsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNwRixPQUFPO1NBQ1Y7YUFBTSxJQUFJLE1BQU0sQ0FBQyxVQUFVLEtBQUssSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUM5QyxPQUFPLENBQUMsS0FBSyxDQUFDLGtGQUFrRjtnQkFDNUYsbUZBQW1GLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDakcsT0FBTztTQUNWO2FBQU07WUFFSCxPQUFPLENBQUMsSUFBSSxDQUFDLDRCQUE0QixHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1lBRWxGLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLGdCQUFnQixFQUFFLFVBQUMsS0FBSyxFQUFFLFFBQVE7Z0JBQ3hELElBQUksS0FBSyxFQUFFO29CQUNQLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7aUJBQ3hCO3FCQUFNO29CQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsNkJBQTZCLENBQUMsQ0FBQztpQkFDL0M7WUFDTCxDQUFDLENBQUMsQ0FBQztZQUVILE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzNCLE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7WUFFaEMsSUFBTSxXQUFXLEdBQUcsSUFBSSx5QkFBVyxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsQ0FBQztZQUN2RyxTQUFTLENBQUMsU0FBUyxDQUFDLGlCQUFpQixFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztZQUN0RCxXQUFXLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztTQUN0QztJQUNMLENBQUM7SUFlRCx3QkFBTSxHQUFOLFVBQU8sTUFBcUI7UUFBNUIsaUJBNkJDO1FBNUJHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUUvQixJQUFNLGFBQWEsR0FBRyxFQUFFLENBQUM7WUFFekIsSUFBSSxNQUFNLENBQUMsRUFBRSxJQUFJLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDbkMsSUFBTSxlQUFhLEdBQWEsRUFBRSxDQUFDO2dCQUVuQyxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFBLFVBQVU7b0JBQ3hCLGVBQWEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUNoRCxDQUFDLENBQUMsQ0FBQztnQkFDSCxhQUFhLENBQUMsSUFBSSxDQUFDLEdBQUcsZUFBYSxDQUFDO2FBQ3ZDO2lCQUFNO2dCQUNILGFBQWEsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7YUFDNUI7WUFFRCxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3ZELGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFFdkQsS0FBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsYUFBYSxFQUFFO2dCQUNyQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUM7YUFDekMsRUFBRSxVQUFDLEtBQUssRUFBRSxRQUFRO2dCQUNmLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRTtvQkFDVCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7aUJBQ2pCO3FCQUFNO29CQUNILE9BQU8sRUFBRSxDQUFDO2lCQUNiO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFPRCxvQkFBRSxHQUFGLFVBQUcsSUFBWSxFQUFFLE9BQTBJO1FBRXZKLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxVQUFBLEtBQUs7WUFDbEIsSUFBSSxLQUFLLEVBQUU7Z0JBQ1AsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxHQUFHLDBCQUEwQixFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQ3RFO2lCQUFNO2dCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksR0FBRywwQkFBMEIsQ0FBQyxDQUFDO2FBQy9EO1lBQ0QsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25CLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxJQUFJLEtBQUssd0JBQXdCLElBQUksSUFBSSxLQUFLLHVCQUF1QixFQUFFO1lBQ3ZFLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUM7WUFFbEMsS0FBSyxJQUFNLFlBQVksSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUU7Z0JBQy9DLElBQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUM7Z0JBQ3hELElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRTtvQkFDM0MsR0FBRyxDQUFDLG9CQUFvQixFQUFFLENBQUM7aUJBQzlCO2FBQ0o7U0FDSjtRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFNRCxzQkFBSSxHQUFKLFVBQUssSUFBWSxFQUFFLE9BQTBJO1FBQ3pKLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxVQUFBLEtBQUs7WUFDcEIsSUFBSSxLQUFLLEVBQUU7Z0JBQ1AsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxHQUFHLDBCQUEwQixFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQ3RFO2lCQUFNO2dCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksR0FBRywwQkFBMEIsQ0FBQyxDQUFDO2FBQy9EO1lBQ0QsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25CLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxJQUFJLEtBQUssd0JBQXdCLElBQUksSUFBSSxLQUFLLHVCQUF1QixFQUFFO1lBQ3ZFLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUM7WUFHbEMsS0FBSyxJQUFNLFlBQVksSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUU7Z0JBQy9DLElBQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUM7Z0JBQ3hELElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRTtvQkFDM0MsR0FBRyxDQUFDLHdCQUF3QixFQUFFLENBQUM7aUJBQ2xDO2FBQ0o7U0FDSjtRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFNRCxxQkFBRyxHQUFILFVBQUksSUFBWSxFQUFFLE9BQTJJO1FBRXpKLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDVixJQUFJLENBQUMsRUFBRSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3BDO2FBQU07WUFDSCxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7U0FDOUI7UUFFRCxJQUFJLElBQUksS0FBSyx3QkFBd0IsSUFBSSxJQUFJLEtBQUssdUJBQXVCLEVBQUU7WUFDdkUsSUFBSSxDQUFDLHFCQUFxQixHQUFHLEtBQUssQ0FBQztZQUduQyxLQUFLLElBQU0sWUFBWSxJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtnQkFDL0MsSUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFDeEQsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFO29CQUM1QixHQUFHLENBQUMscUJBQXFCLEVBQUUsQ0FBQztpQkFDL0I7YUFDSjtTQUNKO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQVFELHFDQUFtQixHQUFuQixVQUFvQixRQUEyQjtRQUEvQyxpQkFZQztRQVZHLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUM7YUFFOUIsSUFBSSxDQUFDLFVBQUEsVUFBVTtZQUNaLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxHQUFHLFFBQVEsQ0FBQyxFQUFFLEdBQUcscUNBQXFDLENBQUMsQ0FBQztRQUN0RixDQUFDLENBQUM7YUFDRCxLQUFLLENBQUMsVUFBQSxhQUFhO1lBQ2hCLElBQU0sVUFBVSxHQUFHLElBQUksdUJBQVUsQ0FBQyxLQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDbEQsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxVQUFVLENBQUM7WUFDakQsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxJQUFJLGlDQUFlLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSxtQkFBbUIsRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BILENBQUMsQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUtELG1DQUFpQixHQUFqQixVQUFrQixHQUFHO1FBQXJCLGlCQW9CQztRQW5CRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxvQkFBb0IsR0FBRyxHQUFHLENBQUMsSUFBSSxHQUFHLHFDQUFxQztZQUN0RywrQkFBK0IsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQzthQUVyRixJQUFJLENBQUMsVUFBQSxVQUFVO1lBQ1osSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRTtnQkFDckIsSUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQztnQkFFakMsSUFBTSxXQUFXLEdBQUcsSUFBSSx5QkFBVyxDQUFDLElBQUksRUFBRSxLQUFJLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDdkYsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO2dCQUNwRCxXQUFXLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztnQkFFbkMsT0FBTyxLQUFJLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ3JEO1lBQ0QsT0FBTyxLQUFJLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3ZELEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLHFCQUFxQixFQUFFLENBQUMsSUFBSSxpQ0FBZSxDQUFDLEtBQUssRUFBRSxLQUFJLEVBQUUscUJBQXFCLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEksQ0FBQyxDQUFDO2FBQ0QsS0FBSyxDQUFDLFVBQUEsYUFBYTtZQUNoQixPQUFPLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUtELHdDQUFzQixHQUF0QixVQUF1QixRQUEyQjtRQUFsRCxpQkFtQ0M7UUFqQ0csSUFBTSxvQkFBb0IsR0FBRyxVQUFDLFVBQVU7WUFDcEMsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsR0FBRyxVQUFVLENBQUM7WUFFN0QsSUFBSSxDQUFDLEtBQUksQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFO2dCQUt4RCxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxJQUFJLHlCQUFXLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSxlQUFlLEVBQUUsVUFBVSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDOUc7WUFFRCxLQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDakUsQ0FBQyxDQUFDO1FBSUYsSUFBSSxVQUFzQixDQUFDO1FBQzNCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLHFCQUFxQixHQUFHLFFBQVEsQ0FBQyxFQUFFLEdBQUcsMkNBQTJDO1lBQ25ILCtCQUErQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO2FBRXJGLElBQUksQ0FBQyxVQUFBLEdBQUc7WUFFTCxVQUFVLEdBQUcsR0FBRyxDQUFDO1lBQ2pCLFFBQVEsQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQztZQUM3QixVQUFVLENBQUMsT0FBTyxHQUFHLFFBQVEsQ0FBQztZQUM5QixVQUFVLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQy9DLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3JDLENBQUMsQ0FBQzthQUNELEtBQUssQ0FBQyxVQUFBLGFBQWE7WUFFaEIsVUFBVSxHQUFHLElBQUksdUJBQVUsQ0FBQyxLQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDNUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDckMsQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBS0QsMENBQXdCLEdBQXhCLFVBQXlCLEdBQUc7UUFBNUIsaUJBa0JDO1FBakJHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLHFCQUFxQixHQUFHLEdBQUcsQ0FBQyxJQUFJLEdBQUcsNkNBQTZDO1lBQy9HLCtCQUErQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO2FBRXJGLElBQUksQ0FBQyxVQUFBLFVBQVU7WUFFWixJQUFNLFdBQVcsR0FBRyxJQUFJLHlCQUFXLENBQUMsSUFBSSxFQUFFLEtBQUksRUFBRSxpQkFBaUIsRUFBRSxVQUFVLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNsRyxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7WUFDcEQsV0FBVyxDQUFDLG9CQUFvQixFQUFFLENBQUM7WUFHbkMsSUFBTSxRQUFRLEdBQVcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7WUFDcEQsT0FBTyxLQUFJLENBQUMsb0JBQW9CLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0MsVUFBVSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN0QyxDQUFDLENBQUM7YUFDRCxLQUFLLENBQUMsVUFBQSxhQUFhO1lBQ2hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDakMsQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBS0Qsc0NBQW9CLEdBQXBCLFVBQXFCLEdBQUc7SUFxQnhCLENBQUM7SUFLRCw4QkFBWSxHQUFaLFVBQWEsR0FBRztRQUFoQixpQkFjQztRQVpHLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUVuRCxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsY0FBYyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEdBQUcsNkRBQTZEO2NBQ2hILElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLCtCQUErQixHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDO2FBRXRILElBQUksQ0FBQyxVQUFBLFVBQVU7WUFDWixLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxJQUFJLHlCQUFXLENBQUMsS0FBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDckYsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLHlCQUFXLENBQUMsS0FBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsQ0FBQyxDQUFDO2FBQ0QsS0FBSyxDQUFDLFVBQUEsYUFBYTtZQUNoQixPQUFPLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUtELGtDQUFnQixHQUFoQixVQUFpQixHQUFHO1FBQ2hCLElBQU0sU0FBUyxHQUFHO1lBQ2QsU0FBUyxFQUFFLEdBQUcsQ0FBQyxTQUFTO1lBQ3hCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTTtZQUNsQixhQUFhLEVBQUUsR0FBRyxDQUFDLGFBQWE7U0FDbkMsQ0FBQztRQUNGLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxvQ0FBb0MsR0FBRyxHQUFHLENBQUMsWUFBWSxHQUFHLG1DQUFtQyxHQUFHLFNBQVMsQ0FBQzthQUUxSSxJQUFJLENBQUMsVUFBQSxVQUFVO1lBQ1osSUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQztZQUNqQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUMsZUFBZSxDQUFDLFNBQVMsRUFBRSxVQUFDLEtBQUs7Z0JBQ3BELElBQUksS0FBSyxFQUFFO29CQUNQLE9BQU8sQ0FBQyxLQUFLLENBQUMsNkJBQTZCLEdBQUcsTUFBTSxDQUFDLFFBQVE7MEJBQ3ZELHNCQUFzQixHQUFHLEdBQUcsQ0FBQyxZQUFZLEdBQUcsSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDO2lCQUNuRTtZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDO2FBQ0QsS0FBSyxDQUFDLFVBQUEsYUFBYTtZQUNoQixPQUFPLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUtELGlDQUFlLEdBQWYsVUFBZ0IsR0FBRztRQUNmLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3ZELElBQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDbkIsSUFBSSxDQUFDLEtBQUssU0FBUyxFQUFFO1lBQ2pCLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGdCQUFnQixFQUFFLENBQUM7b0JBQ2pDLE9BQU8sRUFBRSxDQUFDO2lCQUNiLENBQUMsQ0FBQyxDQUFDO1NBQ1A7YUFBTTtZQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMscUNBQXFDLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDNUQ7SUFDTCxDQUFDO0lBS0Qsa0NBQWdCLEdBQWhCO1FBRUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFFbEIsT0FBTyxDQUFDLElBQUksQ0FBQywwRkFBMEYsQ0FBQyxDQUFDO1lBRXpHLElBQU0sR0FBRyxHQUFHLFVBQVUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDM0YsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLHNFQUFzRSxHQUFHLEdBQUcsR0FBRywwQ0FBMEMsQ0FBQyxFQUFFO2dCQUMzSSxRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsR0FBRyxxQkFBcUIsQ0FBQyxDQUFDO2FBQ2hEO1lBQ0QsT0FBTztTQUNWO1FBRUQsT0FBTyxDQUFDLElBQUksQ0FBQyw2QkFBNkIsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDN0QsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFO1lBQy9DLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLG1CQUFtQixDQUFDLENBQUM7U0FDekM7SUFDTCxDQUFDO0lBS0QsOEJBQVksR0FBWixVQUFhLE1BQU07UUFFZixPQUFPLENBQUMsS0FBSyxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDeEQsSUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQztRQUN6QixJQUFJLEdBQUcsRUFBRTtZQUNMLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGFBQWEsRUFBRSxDQUFDO29CQUM5QixLQUFLLEVBQUUsR0FBRztpQkFDYixDQUFDLENBQUMsQ0FBQztTQUNQO2FBQU07WUFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLHlDQUF5QyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQ25FO0lBQ0wsQ0FBQztJQUtELG9DQUFrQixHQUFsQixVQUFtQixRQUFRO1FBQ3ZCLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGtCQUFrQixFQUFFLENBQUMsSUFBSSwrQkFBYyxDQUFDLElBQUksRUFBRSxrQkFBa0IsRUFBRSxRQUFRLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEgsQ0FBQztJQUtELG9DQUFrQixHQUFsQixVQUFtQixRQUFRO1FBQ3ZCLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGtCQUFrQixFQUFFLENBQUMsSUFBSSwrQkFBYyxDQUFDLElBQUksRUFBRSxrQkFBa0IsRUFBRSxRQUFRLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEgsQ0FBQztJQUtELDJCQUFTLEdBQVQsVUFBVSxJQUFZLEVBQUUsVUFBaUI7UUFDckMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFLRCx1QkFBSyxHQUFMLFVBQU0sTUFBZSxFQUFFLE1BQWM7UUFBckMsaUJBbUNDO1FBakNHLE1BQU0sR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQ2xCLE9BQU8sQ0FBQyxJQUFJLENBQUMsMEJBQTBCLEdBQUcsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBRXhELElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxJQUFJLENBQUMsTUFBTSxFQUFFO2dCQUN0QyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsVUFBQyxLQUFLLEVBQUUsUUFBUTtvQkFDbkQsSUFBSSxLQUFLLEVBQUU7d0JBQ1AsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztxQkFDeEI7b0JBQ0QsS0FBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDNUIsQ0FBQyxDQUFDLENBQUM7YUFDTjtpQkFBTTtnQkFDSCxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDO2FBQzNCO1lBRUQsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUU7Z0JBRTFCLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7Z0JBQzNDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsc0JBQXNCLEVBQUU7b0JBRS9DLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsc0NBQXNDLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO2lCQUN6RjthQUNKO1lBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFO2dCQUUzQixJQUFNLHNCQUFzQixHQUFHLElBQUksbURBQXdCLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUMxRSxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQztnQkFDbkUsc0JBQXNCLENBQUMsb0JBQW9CLEVBQUUsQ0FBQzthQUNqRDtTQUNKO2FBQU07WUFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLHdDQUF3QyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUMzRTtJQUNMLENBQUM7SUFLTyw0QkFBVSxHQUFsQixVQUFtQixLQUFhO1FBQWhDLGlCQTREQztRQTNERyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsS0FBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsVUFBQyxLQUFLO2dCQUN4QixJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUU7b0JBQ1QsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2lCQUNqQjtxQkFBTTtvQkFFSCxJQUFNLFVBQVUsR0FBRzt3QkFDZixLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTt3QkFDN0IsT0FBTyxFQUFFLEtBQUksQ0FBQyxTQUFTO3dCQUN2QixRQUFRLEVBQUUsQ0FBQyxDQUFDLEtBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRTt3QkFDOUQsTUFBTSxFQUFFLEtBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFO3dCQUNqQyxRQUFRLEVBQUUsS0FBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUU7cUJBQ3hDLENBQUM7b0JBRUYsS0FBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxVQUFDLEtBQUssRUFBRSxRQUFRO3dCQUM5RCxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUU7NEJBQ1QsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO3lCQUNqQjs2QkFBTTs0QkFHSCxLQUFJLENBQUMsVUFBVSxHQUFHLElBQUksdUJBQVUsQ0FBQyxLQUFJLENBQUMsQ0FBQzs0QkFDdkMsS0FBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQzs0QkFDM0MsS0FBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQzs0QkFHekMsSUFBTSxRQUFNLEdBQUc7Z0NBQ1gsV0FBVyxFQUFFLElBQUksS0FBSyxFQUFjO2dDQUNwQyxPQUFPLEVBQUUsSUFBSSxLQUFLLEVBQVU7NkJBQy9CLENBQUM7NEJBQ0YsSUFBTSxvQkFBb0IsR0FBd0IsUUFBUSxDQUFDLEtBQUssQ0FBQzs0QkFDakUsb0JBQW9CLENBQUMsT0FBTyxDQUFDLFVBQUEsV0FBVztnQ0FDcEMsSUFBTSxVQUFVLEdBQUcsSUFBSSx1QkFBVSxDQUFDLEtBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztnQ0FDckQsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsR0FBRyxVQUFVLENBQUM7Z0NBQzdELFFBQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dDQUNwQyxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFO29DQUNyQixLQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxJQUFJLENBQUM7b0NBQzdELFFBQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztpQ0FDMUM7NEJBQ0wsQ0FBQyxDQUFDLENBQUM7NEJBR0gsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxJQUFJLGlDQUFlLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSxtQkFBbUIsRUFBRSxLQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQzs0QkFHckgsUUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsVUFBQSxVQUFVO2dDQUNqQyxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLElBQUksaUNBQWUsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLG1CQUFtQixFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7NEJBQ3BILENBQUMsQ0FBQyxDQUFDOzRCQUdILFFBQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQUEsTUFBTTtnQ0FDekIsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFLENBQUMsSUFBSSx5QkFBVyxDQUFDLEtBQUssRUFBRSxLQUFJLEVBQUUsZUFBZSxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7NEJBQ3BHLENBQUMsQ0FBQyxDQUFDOzRCQUVILE9BQU8sRUFBRSxDQUFDO3lCQUNiO29CQUNMLENBQUMsQ0FBQyxDQUFDO2lCQUNOO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTyxzQ0FBb0IsR0FBNUIsVUFBNkIsUUFBYTtRQUN0QyxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsRUFBRTtZQUM5QixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDbkM7YUFBTTtZQUNILE9BQU8sUUFBUSxDQUFDO1NBQ25CO0lBQ0wsQ0FBQztJQUVPLCtCQUFhLEdBQXJCLFVBQXNCLFlBQW9CLEVBQUUsWUFBb0I7UUFBaEUsaUJBZ0JDO1FBZkcsT0FBTyxJQUFJLE9BQU8sQ0FBYSxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQzNDLElBQU0sVUFBVSxHQUFHLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN4RCxJQUFJLENBQUMsQ0FBQyxVQUFVLEVBQUU7Z0JBRWQsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ3ZCO2lCQUFNO2dCQUNILElBQUksS0FBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLEtBQUssWUFBWSxFQUFFO29CQUUvQyxPQUFPLENBQUMsS0FBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2lCQUM1QjtxQkFBTTtvQkFFSCxNQUFNLENBQUMsSUFBSSw2QkFBYSxDQUFDLGlDQUFpQixDQUFDLGFBQWEsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO2lCQUM1RTthQUNKO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8scUNBQW1CLEdBQTNCLFVBQTRCLFlBQW9CLEVBQUUsWUFBb0I7UUFBdEUsaUJBV0M7UUFWRyxPQUFPLElBQUksT0FBTyxDQUFhLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDM0MsSUFBTSxVQUFVLEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3hELElBQUksQ0FBQyxDQUFDLFVBQVUsRUFBRTtnQkFFZCxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDdkI7aUJBQU07Z0JBRUgsTUFBTSxDQUFDLElBQUksNkJBQWEsQ0FBQyxpQ0FBaUIsQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQzthQUM1RTtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLDhCQUFZLEdBQXBCLFVBQXFCLEtBQWE7UUFDOUIsSUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDM0IsSUFBSSxDQUFDLFNBQVMsR0FBVyxHQUFHLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMzRCxJQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM5QyxJQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUVsRCxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUU7WUFDVixJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7U0FDakM7UUFDRCxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUU7WUFDWixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7U0FDakM7UUFFRCxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssR0FBRyxRQUFRLEdBQUcsR0FBRyxDQUFDLElBQUksR0FBRyxXQUFXLENBQUM7SUFDNUQsQ0FBQztJQUVMLGNBQUM7QUFBRCxDQXA0QkEsQUFvNEJDLElBQUE7QUFwNEJZLDBCQUFPOzs7OztBQ3pCcEIsMkVBQTBFO0FBQzFFLDRGQUEyRjtBQUczRixtREFBc0Q7QUFFdEQsZ0ZBQWtGO0FBUWxGO0lBOEVJLGdCQUFZLE9BQWdCLEVBQUUsT0FBMEQ7UUFBeEYsaUJBcUNDO1FBMUVELE9BQUUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBTWhCLHdCQUFtQixHQUFHLEtBQUssQ0FBQztRQUtwQyxnQ0FBMkIsR0FBRyxLQUFLLENBQUM7UUFJcEMsMkJBQXNCLEdBQUcsS0FBSyxDQUFDO1FBd0IzQixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUV2QixJQUFJLE9BQU8sQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFFOUIsSUFBSSxDQUFDLGlCQUFpQixHQUF5QixPQUFPLENBQUM7WUFDdkQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO1lBQzFDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQztZQUNqRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUM7WUFDakQsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUM7WUFDMUcsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsU0FBUyxDQUFDO1NBQzdHO2FBQU07WUFFSCxJQUFJLENBQUMsa0JBQWtCLEdBQTBCLE9BQU8sQ0FBQztZQUV6RCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRTtnQkFDcEIsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQUU7b0JBQ3JCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO29CQUN6QixJQUFJLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQztpQkFDL0I7cUJBQU07b0JBQ0gsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7b0JBQ3pCLElBQUksQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDO2lCQUMvQjtnQkFDRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUM7YUFDMUU7aUJBQU07Z0JBQ0gsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7Z0JBQ3hCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQzthQUMzQjtZQUNELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQ3RDO1FBRUQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMscUJBQXFCLEVBQUU7WUFDOUIsS0FBSSxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDdkQsT0FBTyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsR0FBRyxLQUFJLENBQUMsV0FBVyxHQUFHLHVCQUF1QixHQUFHLEtBQUksQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDMUcsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBUUQsK0JBQWMsR0FBZDtRQUNJLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUM1QixDQUFDO0lBS0QsK0JBQWMsR0FBZCxVQUFlLFdBQXdCO1FBQ25DLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQ25DLENBQUM7SUFLRCwwQ0FBeUIsR0FBekI7UUFDSSxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFLRCw4QkFBYSxHQUFiO1FBQ0ksT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQzNCLENBQUM7SUFLRCxxQ0FBb0IsR0FBcEI7UUFDSSxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO0lBQzFDLENBQUM7SUFLRCxvQ0FBbUIsR0FBbkIsVUFBb0IsS0FBYztRQUM5QixJQUFJLENBQUMsbUJBQW1CLEdBQUcsS0FBSyxDQUFDO0lBQ3JDLENBQUM7SUFLRCx5Q0FBd0IsR0FBeEIsVUFBeUIsa0JBQXlDO1FBQzlELElBQUksQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztJQUNqRCxDQUFDO0lBS0QsMEJBQVMsR0FBVDtRQUFBLGlCQVVDO1FBVEcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQy9CLEtBQUksQ0FBQyxxQkFBcUIsRUFBRTtpQkFDdkIsSUFBSSxDQUFDO2dCQUNGLE9BQU8sRUFBRSxDQUFDO1lBQ2QsQ0FBQyxDQUFDO2lCQUNELEtBQUssQ0FBQyxVQUFBLEtBQUs7Z0JBQ1IsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xCLENBQUMsQ0FBQyxDQUFDO1FBQ1gsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBS0Qsd0JBQU8sR0FBUDtRQUFBLGlCQXNCQztRQXJCRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsSUFBSSxLQUFJLENBQUMsMkJBQTJCLEVBQUU7Z0JBQ2xDLEtBQUksQ0FBQyxrQkFBa0IsRUFBRTtxQkFDcEIsSUFBSSxDQUFDO29CQUNGLE9BQU8sRUFBRSxDQUFDO2dCQUNkLENBQUMsQ0FBQztxQkFDRCxLQUFLLENBQUMsVUFBQSxLQUFLO29CQUNSLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDbEIsQ0FBQyxDQUFDLENBQUM7YUFDVjtpQkFBTTtnQkFDSCxLQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyx5QkFBeUIsRUFBRTtvQkFDcEMsS0FBSSxDQUFDLE9BQU8sRUFBRTt5QkFDVCxJQUFJLENBQUM7d0JBQ0YsT0FBTyxFQUFFLENBQUM7b0JBQ2QsQ0FBQyxDQUFDO3lCQUNELEtBQUssQ0FBQyxVQUFBLEtBQUs7d0JBQ1IsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUNsQixDQUFDLENBQUMsQ0FBQztnQkFDWCxDQUFDLENBQUMsQ0FBQzthQUNOO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBS0Qsa0NBQWlCLEdBQWpCO1FBQ0ksSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ2pCLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDN0I7UUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDbEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUMzQjtRQUVELElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUV2QixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsR0FBRyxvQ0FBb0MsR0FBRyxJQUFJLENBQUMsUUFBUSxHQUFHLGlCQUFpQixDQUFDLENBQUM7SUFDcEosQ0FBQztJQUtELG1DQUFrQixHQUFsQjtRQUNJLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNsQixJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFDLEtBQUs7Z0JBQzVDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNqQixDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQUMsS0FBSztnQkFDNUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2pCLENBQUMsQ0FBQyxDQUFDO1lBQ0gsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO1NBQzNCO1FBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcscUNBQXFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ25KLENBQUM7SUFLRCxnQ0FBZSxHQUFmO1FBQ0ksT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUM7SUFDcEMsQ0FBQztJQUtELDRCQUFXLEdBQVg7UUFDSSxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0I7WUFDN0IsSUFBSSxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLFdBQVcsS0FBSyxJQUFJO1lBQ2hFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEtBQUssS0FBSyxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUtELDRCQUFXLEdBQVg7UUFDSSxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0I7WUFDN0IsSUFBSSxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLFdBQVcsS0FBSyxJQUFJO1lBQ2hFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEtBQUssS0FBSyxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUtELDZCQUFZLEdBQVo7UUFDSSxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0I7WUFDN0IsSUFBSSxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBS0QsMENBQXlCLEdBQXpCO1FBQ0ksSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDbkIsSUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMscUJBQXFCLENBQUMsOEJBQThCLElBQUksRUFBRSxDQUFDO1lBQ3JHLFdBQVcsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxPQUFPLFdBQVcsQ0FBQyxRQUFRLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUM5RixXQUFXLENBQUMsU0FBUyxHQUFHLENBQUMsT0FBTyxXQUFXLENBQUMsU0FBUyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUVsRyxJQUFJLENBQUMsV0FBVyxHQUFHLFlBQVksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDbEY7SUFDTCxDQUFDO0lBS0QscUNBQW9CLEdBQXBCO1FBQUEsaUJBUUM7UUFQRyxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztRQUNqQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUU7WUFDNUIsS0FBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxJQUFJLCtDQUFzQixDQUFDLEtBQUksQ0FBQyxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsS0FBSSxDQUFDLFVBQVUsRUFBRSxLQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNKLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsa0JBQWtCLEVBQUU7WUFDcEMsS0FBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsdUJBQXVCLEVBQUUsQ0FBQyxJQUFJLCtDQUFzQixDQUFDLEtBQUksQ0FBQyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsS0FBSSxDQUFDLFVBQVUsRUFBRSxLQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3pKLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUtELHlDQUF3QixHQUF4QjtRQUFBLGlCQVVDO1FBVEcsSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFO1lBQzVCLEtBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLHdCQUF3QixFQUFFLENBQUMsSUFBSSwrQ0FBc0IsQ0FBQyxLQUFJLENBQUMsT0FBTyxFQUFFLHdCQUF3QixFQUFFLEtBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN2SixLQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLGtCQUFrQixFQUFFO1lBQ3BDLEtBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLHVCQUF1QixFQUFFLENBQUMsSUFBSSwrQ0FBc0IsQ0FBQyxLQUFJLENBQUMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLEtBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNySixLQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFLRCxzQ0FBcUIsR0FBckI7UUFDSSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDO0lBQ2pDLENBQUM7SUFLTyxtQ0FBa0IsR0FBMUI7UUFBQSxpQkFxRUM7UUFwRUcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBRS9CLElBQU0sb0JBQW9CLEdBQUc7Z0JBQ3pCLEtBQUssRUFBRSxLQUFJLENBQUMsV0FBVyxFQUFFO2dCQUN6QixLQUFLLEVBQUUsS0FBSSxDQUFDLFdBQVcsRUFBRTthQUM1QixDQUFDO1lBRUYsSUFBTSxPQUFPLEdBQVE7Z0JBQ2pCLFdBQVcsRUFBRSxLQUFJLENBQUMsV0FBVztnQkFDN0IsZ0JBQWdCLEVBQUUsb0JBQW9CO2dCQUN0QyxjQUFjLEVBQUUsS0FBSSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSSxDQUFDLFVBQVUsQ0FBQztnQkFDdEUsVUFBVSxFQUFFLEtBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLHFCQUFxQixDQUFDLFVBQVU7YUFDckUsQ0FBQztZQUVGLElBQU0sZUFBZSxHQUFHLFVBQUMsS0FBSyxFQUFFLGFBQWEsRUFBRSxFQUFFO2dCQUM3QyxJQUFJLEtBQUssRUFBRTtvQkFDUCxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsNkJBQTZCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQzVFO2dCQUVELE9BQU8sQ0FBQyxLQUFLLENBQUMsa0NBQWtDO3NCQUMxQyxLQUFJLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxDQUFDO2dCQUVwQyxLQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFO29CQUM5QyxRQUFRLEVBQUUsYUFBYTtvQkFDdkIsVUFBVSxFQUFFLEtBQUksQ0FBQyxlQUFlLEVBQUUsSUFBSSxLQUFLO29CQUMzQyxXQUFXLEVBQUUsS0FBSSxDQUFDLFdBQVcsRUFBRTtvQkFDL0IsV0FBVyxFQUFFLEtBQUksQ0FBQyxXQUFXLEVBQUU7b0JBQy9CLFdBQVcsRUFBRSxDQUFDLENBQUMsS0FBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQ3RGLFNBQVMsRUFBRSxDQUFDLENBQUMsS0FBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUNwRCxFQUFFLFVBQUMsS0FBSyxFQUFFLFFBQVE7b0JBQ2YsSUFBSSxLQUFLLEVBQUU7d0JBQ1AsTUFBTSxDQUFDLHlCQUF5QixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztxQkFDN0Q7eUJBQU07d0JBQ0gsS0FBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7NkJBQ3BDLElBQUksQ0FBQzs0QkFDRixLQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDOzRCQUNuQyxJQUFJLEtBQUksQ0FBQyxlQUFlLEVBQUUsRUFBRTtnQ0FHeEIsS0FBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7NkJBQ3BDOzRCQUNELEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLDZCQUE2QixDQUFDLENBQUM7NEJBQ2pELE9BQU8sRUFBRSxDQUFDO3dCQUNkLENBQUMsQ0FBQzs2QkFDRCxLQUFLLENBQUMsVUFBQSxLQUFLOzRCQUNSLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQzt3QkFDbEIsQ0FBQyxDQUFDLENBQUM7d0JBQ1AsT0FBTyxDQUFDLElBQUksQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO3FCQUNqRTtnQkFDTCxDQUFDLENBQUMsQ0FBQztZQUNQLENBQUMsQ0FBQztZQUVGLElBQUksS0FBSSxDQUFDLGVBQWUsRUFBRSxFQUFFO2dCQUN4QixLQUFJLENBQUMsVUFBVSxHQUFHLFlBQVksQ0FBQyxVQUFVLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLFVBQUEsR0FBRztvQkFDckUsSUFBSSxHQUFHLEVBQUU7d0JBQ0wsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO3FCQUNmO29CQUNELEtBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUNuRCxDQUFDLENBQUMsQ0FBQzthQUNOO2lCQUFNO2dCQUNILEtBQUksQ0FBQyxVQUFVLEdBQUcsWUFBWSxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsVUFBQSxLQUFLO29CQUN2RSxJQUFJLEtBQUssRUFBRTt3QkFDUCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7cUJBQ2pCO29CQUNELEtBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUNuRCxDQUFDLENBQUMsQ0FBQzthQUNOO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sc0NBQXFCLEdBQTdCO1FBQUEsaUJBNENDO1FBM0NHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUUvQixJQUFNLGdCQUFnQixHQUFHO2dCQUNyQixLQUFLLEVBQUUsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVM7Z0JBQ3ZDLEtBQUssRUFBRSxLQUFJLENBQUMsaUJBQWlCLENBQUMsU0FBUzthQUMxQyxDQUFDO1lBQ0YsT0FBTyxDQUFDLEtBQUssQ0FBQyx1RUFBdUUsRUFDakYsZ0JBQWdCLENBQUMsQ0FBQztZQUN0QixJQUFNLE9BQU8sR0FBRztnQkFDWixjQUFjLEVBQUUsS0FBSSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSSxDQUFDLFVBQVUsQ0FBQztnQkFDdEUsZ0JBQWdCLEVBQUUsZ0JBQWdCO2FBQ3JDLENBQUM7WUFFRixJQUFNLGVBQWUsR0FBRyxVQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsRUFBRTtnQkFFN0MsSUFBSSxLQUFLLEVBQUU7b0JBQ1AsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLCtCQUErQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUM5RTtnQkFDRCxPQUFPLENBQUMsS0FBSyxDQUFDLG9DQUFvQztzQkFDNUMsS0FBSSxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQztnQkFDcEMsS0FBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLGtCQUFrQixFQUFFO29CQUNsRCxNQUFNLEVBQUUsS0FBSSxDQUFDLFFBQVE7b0JBQ3JCLFFBQVEsRUFBRSxhQUFhO2lCQUMxQixFQUFFLFVBQUMsS0FBSyxFQUFFLFFBQVE7b0JBQ2YsSUFBSSxLQUFLLEVBQUU7d0JBQ1AsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLDBCQUEwQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO3FCQUN6RTt5QkFBTTt3QkFDSCxLQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksQ0FBQzs0QkFDM0MsT0FBTyxFQUFFLENBQUM7d0JBQ2QsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUEsS0FBSzs0QkFDVixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7d0JBQ2xCLENBQUMsQ0FBQyxDQUFDO3FCQUNOO2dCQUNMLENBQUMsQ0FBQyxDQUFDO1lBQ1AsQ0FBQyxDQUFDO1lBRUYsS0FBSSxDQUFDLFVBQVUsR0FBRyxZQUFZLENBQUMsVUFBVSxDQUFDLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxVQUFBLEtBQUs7Z0JBQ3ZFLElBQUksS0FBSyxFQUFFO29CQUNQLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDakI7Z0JBQ0QsS0FBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDbkQsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTyxpQ0FBZ0IsR0FBeEIsVUFBeUIsU0FBUztRQUFsQyxpQkFpQ0M7UUFoQ0csT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQy9CLElBQU0sTUFBTSxHQUFHLElBQUkscUJBQXFCLENBQUM7Z0JBQ3JDLElBQUksRUFBRSxRQUFRO2dCQUNkLEdBQUcsRUFBRSxTQUFTO2FBQ2pCLENBQUMsQ0FBQztZQUVILE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSSxDQUFDLFFBQVEsR0FBRyw2Q0FBNkMsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUV4RixJQUFNLFFBQVEsR0FBRyxLQUFJLENBQUMsUUFBUSxDQUFDO1lBQy9CLElBQU0sY0FBYyxHQUFHLEtBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO1lBQ3RELGNBQWMsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLEVBQUU7Z0JBR3hDLElBQUksQ0FBQyxLQUFJLENBQUMsT0FBTyxFQUFFLElBQUksS0FBSSxDQUFDLGVBQWUsRUFBRSxFQUFFO29CQUMzQyxLQUFJLENBQUMsV0FBVyxHQUFHLGNBQWMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUN4RCxPQUFPLENBQUMsS0FBSyxDQUFDLG9CQUFvQixFQUFFLEtBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztvQkFFdEQsSUFBSSxDQUFDLENBQUMsS0FBSSxDQUFDLFdBQVcsRUFBRTt3QkFDcEIsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMscUJBQXFCLENBQUMsQ0FBQzt3QkFDekMsSUFBSSxDQUFDLENBQUMsS0FBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFJLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFOzRCQUM5RSxLQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQzt5QkFDL0I7cUJBQ0o7aUJBQ0o7Z0JBRUQsS0FBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUN2QixPQUFPLEVBQUUsQ0FBQztZQUVkLENBQUMsRUFBRSxVQUFBLEtBQUs7Z0JBQ0osTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLEtBQUksQ0FBQyxRQUFRLEdBQUcsOENBQThDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDOUcsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTyxnQ0FBZSxHQUF2QjtRQUNJLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSx5QkFBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDdkMsQ0FBQztJQUVPLGdDQUFlLEdBQXZCO1FBQ0ksSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFBRSxFQUFFO1lBQ3BELElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxFQUFFLENBQUM7U0FDdEM7SUFDTCxDQUFDO0lBS0Qsd0JBQU8sR0FBUDtRQUVJLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVMLGFBQUM7QUFBRCxDQW5mQSxBQW1mQyxJQUFBO0FBbmZZLHdCQUFNOzs7OztBQ2ZuQixvRkFBbUY7QUFDbkYsa0ZBQWlGO0FBQ2pGLDZFQUE0RTtBQUU1RSxtREFBc0Q7QUFZdEQ7SUEwREksdUJBQVksTUFBYyxFQUFFLGFBQW9DO1FBQWhFLGlCQXNDQztRQXRGRCxXQUFNLEdBQXlCLEVBQUUsQ0FBQztRQThCbEMsdUNBQWtDLEdBQUcsS0FBSyxDQUFDO1FBUWpDLE9BQUUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBVzlCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUNqQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUVyQyxJQUFJLENBQUMsQ0FBQyxhQUFhLEVBQUU7WUFDakIsSUFBSSxNQUFNLFNBQUEsQ0FBQztZQUNYLElBQUksT0FBTyxhQUFhLEtBQUssUUFBUSxFQUFFO2dCQUNuQyxNQUFNLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxhQUFhLENBQUMsQ0FBQzthQUNuRDtpQkFBTSxJQUFJLGFBQWEsWUFBWSxXQUFXLEVBQUU7Z0JBQzdDLE1BQU0sR0FBRyxhQUFhLENBQUM7YUFDMUI7WUFFRCxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUU7Z0JBQ1YsSUFBSSxDQUFDLGlCQUFpQixHQUFHO29CQUNyQixhQUFhLEVBQUUsTUFBTTtvQkFDckIsS0FBSyxFQUFFLFFBQVEsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDO29CQUN0QyxFQUFFLEVBQUUsRUFBRTtpQkFDVCxDQUFDO2dCQUNGLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDO2dCQUM1QixJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQzthQUN6QjtTQUNKO1FBQ0QsSUFBSSxDQUFDLGVBQWUsR0FBRztZQUNuQixJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEVBQUU7Z0JBQ3ZCLElBQUksQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxFQUFFO29CQUNoQyxPQUFPLENBQUMsSUFBSSxDQUFDLCtCQUErQixHQUFHLEtBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxHQUFHLHdCQUF3QixDQUFDLENBQUM7b0JBQ2hHLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDMUc7cUJBQU07b0JBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxvQ0FBb0MsR0FBRyxLQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsR0FBRyx3QkFBd0IsQ0FBQyxDQUFDO29CQUNyRyxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUN0SDthQUNKO2lCQUFNO2dCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLEdBQUcsS0FBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsd0JBQXdCLENBQUMsQ0FBQztnQkFDNUYsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxxQ0FBaUIsQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFJLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQzFHO1lBQ0QsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFLENBQUMsSUFBSSx1Q0FBa0IsQ0FBQyxLQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkUsQ0FBQyxDQUFDO0lBQ04sQ0FBQztJQUtELDBCQUFFLEdBQUYsVUFBRyxJQUFZLEVBQUUsT0FBK0I7UUFDNUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQUEsS0FBSztZQUNsQixJQUFJLEtBQUssRUFBRTtnQkFDUCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLEdBQUcsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQ3pEO2lCQUFNO2dCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksR0FBRyxhQUFhLENBQUMsQ0FBQzthQUNsRDtZQUNELE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksSUFBSSxLQUFLLHFCQUFxQixFQUFFO1lBQ2hDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLGtDQUFrQyxFQUFFO2dCQUMxRCxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNySCxJQUFJLENBQUMsa0NBQWtDLEdBQUcsS0FBSyxDQUFDO2FBQ25EO1NBQ0o7UUFDRCxJQUFJLElBQUksS0FBSyxlQUFlLElBQUksSUFBSSxLQUFLLGNBQWMsRUFBRTtZQUNyRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUN0QyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxXQUFXLEdBQUcsQ0FBQztnQkFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLEtBQUs7Z0JBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxLQUFLO2dCQUNwQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssQ0FBQyxFQUFFO2dCQUN2QyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxJQUFJLHVDQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDbkUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxxQ0FBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQzFHO1NBQ0o7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBS0QsNEJBQUksR0FBSixVQUFLLElBQVksRUFBRSxPQUErQjtRQUM5QyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsVUFBQSxLQUFLO1lBQ3BCLElBQUksS0FBSyxFQUFFO2dCQUNQLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksR0FBRyxrQkFBa0IsRUFBRSxLQUFLLENBQUMsQ0FBQzthQUM5RDtpQkFBTTtnQkFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLEdBQUcsa0JBQWtCLENBQUMsQ0FBQzthQUN2RDtZQUNELE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksSUFBSSxLQUFLLHFCQUFxQixFQUFFO1lBQ2hDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLGtDQUFrQyxFQUFFO2dCQUMxRCxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3hIO1NBQ0o7UUFDRCxJQUFJLElBQUksS0FBSyxlQUFlLElBQUksSUFBSSxLQUFLLGNBQWMsRUFBRTtZQUNyRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUN0QyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxXQUFXLEdBQUcsQ0FBQztnQkFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLEtBQUs7Z0JBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxLQUFLO2dCQUNwQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssQ0FBQyxFQUFFO2dCQUN2QyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxJQUFJLHVDQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDbkUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxxQ0FBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQzFHO1NBQ0o7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBS0QsMkJBQUcsR0FBSCxVQUFJLElBQVksRUFBRSxPQUFnQztRQUM5QyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ1YsSUFBSSxDQUFDLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUNwQzthQUFNO1lBQ0gsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1NBQzlCO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQWFELHVDQUFlLEdBQWYsVUFBZ0IsS0FBdUI7UUFFbkMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBR3RDLEtBQWdCLFVBQVcsRUFBWCxLQUFBLElBQUksQ0FBQyxNQUFNLEVBQVgsY0FBVyxFQUFYLElBQVc7WUFBdEIsSUFBTSxDQUFDLFNBQUE7WUFDUixJQUFJLENBQUMsQ0FBQyxLQUFLLEtBQUssS0FBSyxFQUFFO2dCQUNuQixPQUFPLENBQUMsQ0FBQzthQUNaO1NBQ0o7UUFFRCxJQUFJLFlBQVksR0FBRyxDQUFDLENBQUM7UUFFckIsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXRDLEtBQTRCLFVBQWtDLEVBQWxDLEtBQUEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFsQyxjQUFrQyxFQUFsQyxJQUFrQztZQUF6RCxJQUFNLGFBQWEsU0FBQTtZQUNwQixJQUFJLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDeEMsWUFBWSxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNsQixNQUFNO2FBQ1Q7U0FDSjtRQUVELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsVUFBQSxhQUFhO1lBQ3BELGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMzQyxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyx5QkFBeUIsQ0FBQztZQUMzQixLQUFLLE9BQUE7WUFDTCxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUU7U0FDZixDQUFDLENBQUM7UUFFSCxPQUFPLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRXZELE9BQU8sWUFBWSxDQUFDO0lBQ3hCLENBQUM7SUFZRCwwQ0FBa0IsR0FBbEIsVUFBbUIsYUFBb0MsRUFBRSxVQUE0QjtRQUNqRixJQUFJLE1BQU0sQ0FBQztRQUNYLElBQUksT0FBTyxhQUFhLEtBQUssUUFBUSxFQUFFO1lBQ25DLE1BQU0sR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxNQUFNLEVBQUU7Z0JBQ1QsTUFBTSxJQUFJLEtBQUssQ0FBQyx5RUFBeUUsR0FBRyxhQUFhLENBQUMsQ0FBQzthQUM5RztTQUNKO2FBQU0sSUFBSSxhQUFhLFlBQVksV0FBVyxFQUFFO1lBQzdDLE1BQU0sR0FBRyxhQUFhLENBQUM7U0FDMUI7YUFBTTtZQUNILE1BQU0sSUFBSSxLQUFLLENBQUMseUVBQXlFLEdBQUcsYUFBYSxDQUFDLENBQUM7U0FDOUc7UUFFRCxJQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV0QyxJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLGlDQUFlLENBQUMsTUFBTSxDQUFDO1FBQ2pFLFFBQVEsT0FBTyxFQUFFO1lBQ2IsS0FBSyxpQ0FBZSxDQUFDLEtBQUs7Z0JBQ3RCLE1BQU0sQ0FBQyxVQUFZLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQzVELE1BQU07WUFDVixLQUFLLGlDQUFlLENBQUMsTUFBTTtnQkFDdkIsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDMUIsTUFBTTtZQUNWLEtBQUssaUNBQWUsQ0FBQyxNQUFNO2dCQUN2QixNQUFNLENBQUMsVUFBWSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQ2hELE1BQU07WUFDVixLQUFLLGlDQUFlLENBQUMsT0FBTztnQkFDeEIsTUFBTSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNqRCxNQUFNO1lBQ1YsS0FBSyxpQ0FBZSxDQUFDLE9BQU87Z0JBQ3hCLE1BQU0sQ0FBQyxVQUFZLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDaEQsTUFBTTtZQUNWO2dCQUNJLE9BQU8sR0FBRyxpQ0FBZSxDQUFDLE1BQU0sQ0FBQztnQkFDakMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDMUIsTUFBTTtTQUNiO1FBRUQsSUFBTSxDQUFDLEdBQXVCO1lBQzFCLGFBQWEsRUFBRSxNQUFNO1lBQ3JCLEtBQUssT0FBQTtZQUNMLFVBQVUsRUFBRSxPQUFPO1lBQ25CLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRTtTQUNmLENBQUM7UUFDRixJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFbEMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxJQUFJLHFDQUFpQixDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRXhHLElBQUksQ0FBQyxrQ0FBa0MsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDO1FBRW5FLE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7SUFLRCxpREFBeUIsR0FBekIsVUFBMEIsS0FBdUI7UUFDN0MsS0FBSyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQy9DLEtBQUssQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLEtBQUssQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFO1lBQ1gsS0FBSyxDQUFDLEVBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsUUFBUSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO1lBRWxGLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUNsQyxJQUFJLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7YUFDdEI7U0FDSjtRQUNELElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsRUFBRTtZQUNoRCxLQUFLLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQztZQUNuQixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFO2dCQUMzRCxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQzNCO1NBQ0o7SUFDTCxDQUFDO0lBS0QsdUNBQWUsR0FBZjtRQUFBLGlCQXFCQztRQXBCRyxLQUFLLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUU7WUFDckUsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFO2dCQUNoRCxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQzthQUNuRDtTQUNKO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBQyxrQkFBa0IsRUFBRSxLQUFLLEVBQUUsTUFBTTtZQUVwRSxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsU0FBUyxFQUFFLEtBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUM5RSxJQUFJLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLEVBQUU7Z0JBR3BDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxVQUFXLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMzRSxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsa0JBQWtCLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSx1QkFBdUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDN0gsS0FBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO2FBQ3BEO2lCQUFNO2dCQUVILGtCQUFrQixDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO2FBQzdDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBS0QseUNBQWlCLEdBQWpCLFVBQWtCLEtBQXVCO1FBQ3JDLElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMxQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDekMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxLQUFLLEVBQUU7Z0JBQ2hDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDekIsYUFBYSxHQUFHLElBQUksQ0FBQztnQkFDckIsT0FBTyxDQUFDLElBQUksQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDeEQsTUFBTTthQUNUO1NBQ0o7UUFDRCxPQUFPLGFBQWEsQ0FBQztJQUN6QixDQUFDO0lBS0QsZ0RBQXdCLEdBQXhCO1FBQ0ksSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsS0FBSyxJQUFJLENBQUMsRUFBRTtZQUM3RixJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1NBQzFFO0lBQ0wsQ0FBQztJQUtELHlDQUFpQixHQUFqQixVQUFrQixXQUF3QjtRQUN0QyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFBLGtCQUFrQjtZQUNsQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLFdBQVcsQ0FBQztRQUNyRCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTyxpREFBeUIsR0FBakMsVUFBa0Msa0JBQXNDO1FBQ3BFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDckMsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7UUFDaEMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO1lBQ3pELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDakQ7SUFDTCxDQUFDO0lBRU8sbUNBQVcsR0FBbkIsVUFBb0IsS0FBSztRQUNyQixLQUFLLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxpQkFBaUIsQ0FBQztRQUMxQyxLQUFLLENBQUMsS0FBSyxDQUFDLGVBQWUsR0FBRyxpQkFBaUIsQ0FBQztJQUNwRCxDQUFDO0lBRUwsb0JBQUM7QUFBRCxDQXpYQSxBQXlYQyxJQUFBO0FBelhZLHNDQUFhOzs7Ozs7Ozs7Ozs7Ozs7QUNuQjFCLGlEQUFnRDtBQU9oRDtJQUFnQyw4QkFBYTtJQU96QyxvQkFBWSxNQUFjLEVBQUUsTUFBNEIsRUFBRSxVQUFnQztRQUExRixZQUNJLGtCQUFNLE1BQU0sRUFBRSxNQUFNLENBQUMsU0FJeEI7UUFIRyxLQUFJLENBQUMsT0FBTyxHQUFHLEtBQUksQ0FBQyxhQUFhLENBQUM7UUFDbEMsS0FBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsS0FBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7O0lBQ2pDLENBQUM7SUFNRCxxQ0FBZ0IsR0FBaEIsVUFBaUIsS0FBYztRQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDLGNBQWMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFDLEtBQUs7WUFDeEQsS0FBSyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDMUIsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLG1CQUFtQixHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLG1CQUFtQixDQUFDLEdBQUcsbUJBQW1CLENBQUMsQ0FBQztRQUMxRyxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBTUQscUNBQWdCLEdBQWhCLFVBQWlCLEtBQWM7UUFDM0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBQyxLQUFLO1lBQ3hELEtBQUssQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBQzFCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLG1CQUFtQixDQUFDLENBQUM7UUFDMUcsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVMLGlCQUFDO0FBQUQsQ0F0Q0EsQUFzQ0MsQ0F0QytCLDZCQUFhLEdBc0M1QztBQXRDWSxnQ0FBVTs7Ozs7QUNSdkIsSUFBWSxrQkFLWDtBQUxELFdBQVksa0JBQWtCO0lBQzFCLHFDQUFlLENBQUE7SUFDZiw2Q0FBdUIsQ0FBQTtJQUN2Qix1Q0FBaUIsQ0FBQTtJQUNqQiwyQ0FBcUIsQ0FBQTtBQUN6QixDQUFDLEVBTFcsa0JBQWtCLEdBQWxCLDBCQUFrQixLQUFsQiwwQkFBa0IsUUFLN0I7Ozs7O0FDRkQsSUFBWSxpQkE2RVg7QUE3RUQsV0FBWSxpQkFBaUI7SUFNekIsb0VBQStDLENBQUE7SUFNL0Msa0VBQTZDLENBQUE7SUFNN0Msb0VBQStDLENBQUE7SUFNL0Msa0ZBQTZELENBQUE7SUFNN0Qsc0ZBQWlFLENBQUE7SUFNakUsNEVBQXVELENBQUE7SUFNdkQsa0ZBQTZELENBQUE7SUFNN0Qsa0ZBQTZELENBQUE7SUFNN0QsZ0VBQTJDLENBQUE7SUFPM0MsOEVBQXlELENBQUE7SUFLekQsOEVBQXlELENBQUE7SUFLekQsc0VBQWlELENBQUE7SUFLakQsb0RBQStCLENBQUE7QUFDbkMsQ0FBQyxFQTdFVyxpQkFBaUIsR0FBakIseUJBQWlCLEtBQWpCLHlCQUFpQixRQTZFNUI7QUFLRDtJQVFJLHVCQUFZLElBQXVCLEVBQUUsT0FBZTtRQUNoRCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztJQUMzQixDQUFDO0lBRUwsb0JBQUM7QUFBRCxDQWJBLEFBYUMsSUFBQTtBQWJZLHNDQUFhOzs7OztBQ2xGMUIsSUFBWSxlQXVCWDtBQXZCRCxXQUFZLGVBQWU7SUFLdkIsa0NBQWUsQ0FBQTtJQUlmLG9DQUFpQixDQUFBO0lBSWpCLG9DQUFpQixDQUFBO0lBSWpCLHNDQUFtQixDQUFBO0lBSW5CLHNDQUFtQixDQUFBO0FBRXZCLENBQUMsRUF2QlcsZUFBZSxHQUFmLHVCQUFlLEtBQWYsdUJBQWUsUUF1QjFCOzs7Ozs7Ozs7Ozs7Ozs7QUMxQkQsaUNBQWdDO0FBVWhDO0lBQXFDLG1DQUFLO0lBbUJ0Qyx5QkFBWSxVQUFtQixFQUFFLE1BQWUsRUFBRSxJQUFZLEVBQUUsVUFBc0IsRUFBRSxNQUFjO1FBQXRHLFlBQ0ksa0JBQU0sVUFBVSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FHbEM7UUFGRyxLQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixLQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQzs7SUFDekIsQ0FBQztJQU1ELDhDQUFvQixHQUFwQixjQUF5QixDQUFDO0lBRTlCLHNCQUFDO0FBQUQsQ0EvQkEsQUErQkMsQ0EvQm9DLGFBQUssR0ErQnpDO0FBL0JZLDBDQUFlOzs7OztBQ1A1QjtJQXNCSSxlQUFZLFVBQW1CLEVBQUUsTUFBK0IsRUFBRSxJQUFZO1FBTHRFLHFCQUFnQixHQUFHLEtBQUssQ0FBQztRQU03QixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztJQUNyQixDQUFDO0lBS0Qsa0NBQWtCLEdBQWxCO1FBQ0ksT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7SUFDakMsQ0FBQztJQWdCRCw4QkFBYyxHQUFkO1FBRUksSUFBSSxDQUFDLG9CQUFvQixHQUFHLGNBQVEsQ0FBQyxDQUFDO1FBQ3RDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7SUFDakMsQ0FBQztJQUlMLFlBQUM7QUFBRCxDQXpEQSxBQXlEQyxJQUFBO0FBekRxQixzQkFBSzs7Ozs7Ozs7Ozs7Ozs7O0FDSDNCLGlDQUFnQztBQWdCaEM7SUFBNEMsMENBQUs7SUFlN0MsZ0NBQVksTUFBZSxFQUFFLElBQVksRUFBRSxVQUFzQixFQUFFLFFBQWdCO1FBQW5GLFlBQ0ksa0JBQU0sS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FJN0I7UUFIRyxLQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixLQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixLQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQzs7SUFDN0IsQ0FBQztJQU1ELHFEQUFvQixHQUFwQixjQUF5QixDQUFDO0lBRTlCLDZCQUFDO0FBQUQsQ0E1QkEsQUE0QkMsQ0E1QjJDLGFBQUssR0E0QmhEO0FBNUJZLHdEQUFzQjs7Ozs7Ozs7Ozs7Ozs7O0FDaEJuQyxpQ0FBZ0M7QUFTaEM7SUFBb0Msa0NBQUs7SUFvQnJDLHdCQUFZLE1BQWUsRUFBRSxJQUFZLEVBQUUsRUFBVSxFQUFFLElBQVk7UUFBbkUsWUFDSSxrQkFBTSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxTQUs3QjtRQUpHLEtBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBQ2IsSUFBSSxJQUFJLEtBQUssRUFBRSxFQUFFO1lBQ2IsS0FBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7U0FDcEI7O0lBQ0wsQ0FBQztJQU1ELDZDQUFvQixHQUFwQixjQUF5QixDQUFDO0lBRTlCLHFCQUFDO0FBQUQsQ0FsQ0EsQUFrQ0MsQ0FsQ21DLGFBQUssR0FrQ3hDO0FBbENZLHdDQUFjOzs7Ozs7Ozs7Ozs7Ozs7QUNUM0IsaUNBQWdDO0FBT2hDO0lBQThDLDRDQUFLO0lBVy9DLGtDQUFZLE1BQWUsRUFBRSxNQUFjO1FBQTNDLFlBQ0ksa0JBQU0sSUFBSSxFQUFFLE1BQU0sRUFBRSxxQkFBcUIsQ0FBQyxTQUU3QztRQURHLEtBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDOztJQUN6QixDQUFDO0lBS0QsdURBQW9CLEdBQXBCO1FBRUksT0FBTyxDQUFDLElBQUksQ0FBQyxrQ0FBa0MsR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLGlDQUFpQyxDQUFDLENBQUM7UUFFakcsSUFBTSxPQUFPLEdBQVksSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUdyQyxLQUFLLElBQU0sWUFBWSxJQUFJLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRTtZQUNsRCxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLENBQUMsTUFBTSxFQUFFO2dCQUNsRCxPQUFPLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7Z0JBQ25FLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztnQkFDcEUsSUFBSSxPQUFPLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRTtvQkFDOUQsT0FBTyxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsZUFBZSxFQUFFLENBQUM7aUJBQ2xGO2dCQUNELE9BQU8sT0FBTyxDQUFDLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQzdGLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQzthQUNyRDtZQUNELE9BQU8sT0FBTyxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQ2xEO0lBQ0wsQ0FBQztJQUVMLCtCQUFDO0FBQUQsQ0F4Q0EsQUF3Q0MsQ0F4QzZDLGFBQUssR0F3Q2xEO0FBeENZLDREQUF3Qjs7Ozs7Ozs7Ozs7Ozs7O0FDUHJDLGlDQUFnQztBQVVoQztJQUFpQywrQkFBSztJQXdCbEMscUJBQVksTUFBZSxFQUFFLElBQVksRUFBRSxJQUFZLEVBQUUsSUFBZ0I7UUFBekUsWUFDSSxrQkFBTSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxTQUk3QjtRQUhHLEtBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLEtBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLEtBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDOztJQUNyQixDQUFDO0lBTUQsMENBQW9CLEdBQXBCLGNBQXlCLENBQUM7SUFFOUIsa0JBQUM7QUFBRCxDQXJDQSxBQXFDQyxDQXJDZ0MsYUFBSyxHQXFDckM7QUFyQ1ksa0NBQVc7Ozs7Ozs7Ozs7Ozs7OztBQ1Z4QixpQ0FBZ0M7QUFDaEMsc0RBQXFEO0FBQ3JELGtEQUFpRDtBQVNqRDtJQUFpQywrQkFBSztJQW9CbEMscUJBQVksVUFBbUIsRUFBRSxNQUEyQixFQUFFLElBQVksRUFBRSxNQUFjLEVBQUUsTUFBYztRQUExRyxZQUNJLGtCQUFNLFVBQVUsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLFNBR2xDO1FBRkcsS0FBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsS0FBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7O0lBQ3pCLENBQUM7SUFLRCwwQ0FBb0IsR0FBcEI7UUFDSSxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssaUJBQWlCLEVBQUU7WUFFakMsSUFBSSxJQUFJLENBQUMsTUFBTSxZQUFZLGlCQUFPLEVBQUU7Z0JBRWhDLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0NBQWtDLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxpQ0FBaUMsQ0FBQyxDQUFDO2dCQUNqRyxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7YUFDbkM7aUJBQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxZQUFZLHFCQUFTLEVBQUU7Z0JBRXpDLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0NBQWtDLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxtQ0FBbUMsQ0FBQyxDQUFDO2dCQUNuRyxJQUFJLENBQUMsTUFBTSxDQUFDLDJCQUEyQixHQUFHLEtBQUssQ0FBQzthQUNuRDtZQUdELElBQUksQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUlqQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYTtnQkFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUczRSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7WUFHdEUsSUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNwRyxJQUFJLENBQUMsQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFO2dCQUNsRCxJQUFNLG1CQUFtQixHQUFHLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7Z0JBQzdELEtBQUssSUFBSSxDQUFDLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFO29CQUN0RCxJQUFJLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTt3QkFDcEQsbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztxQkFDcEM7aUJBQ0o7YUFDSjtTQUVKO0lBQ0wsQ0FBQztJQUVMLGtCQUFDO0FBQUQsQ0FsRUEsQUFrRUMsQ0FsRWdDLGFBQUssR0FrRXJDO0FBbEVZLGtDQUFXOzs7Ozs7Ozs7Ozs7Ozs7QUNYeEIsaUNBQWdDO0FBT2hDO0lBQXdDLHNDQUFLO0lBS3pDLDRCQUFZLE1BQXFCO2VBQzdCLGtCQUFNLEtBQUssRUFBRSxNQUFNLEVBQUUsZUFBZSxDQUFDO0lBQ3pDLENBQUM7SUFNRCxpREFBb0IsR0FBcEIsY0FBeUIsQ0FBQztJQUU5Qix5QkFBQztBQUFELENBZkEsQUFlQyxDQWZ1QyxhQUFLLEdBZTVDO0FBZlksZ0RBQWtCOzs7Ozs7Ozs7Ozs7Ozs7QUNQL0IsaUNBQWdDO0FBVWhDO0lBQXVDLHFDQUFLO0lBVXhDLDJCQUFZLE9BQXlCLEVBQUUsTUFBcUIsRUFBRSxJQUFZO1FBQTFFLFlBQ0ksa0JBQU0sS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FFN0I7UUFERyxLQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQzs7SUFDM0IsQ0FBQztJQU1ELGdEQUFvQixHQUFwQixjQUF5QixDQUFDO0lBRTlCLHdCQUFDO0FBQUQsQ0FyQkEsQUFxQkMsQ0FyQnNDLGFBQUssR0FxQjNDO0FBckJZLDhDQUFpQjs7O0FDM0I5QjtJQUVFLElBQUksT0FBTyxHQUFHLEVBQUUsQ0FBQztJQUdqQixJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVMsUUFBUTtRQUU5QixLQUFJLElBQUksR0FBRyxJQUFJLE9BQU8sRUFDdEI7WUFDRSxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFMUIsS0FBSSxJQUFJLElBQUksSUFBSSxNQUFNO2dCQUNwQixRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7U0FDMUI7UUFBQSxDQUFDO0lBQ0osQ0FBQyxDQUFDO0lBRUYsSUFBSSxDQUFDLEdBQUcsR0FBRyxVQUFTLEVBQUUsRUFBRSxNQUFNO1FBRTVCLElBQUksR0FBRyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMxQixJQUFHLEdBQUcsSUFBSSxTQUFTO1lBQ2pCLE9BQU8sU0FBUyxDQUFDO1FBRW5CLE9BQU8sR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2pCLENBQUMsQ0FBQztJQUVGLElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBUyxFQUFFLEVBQUUsTUFBTTtRQUUvQixJQUFJLEdBQUcsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDMUIsSUFBRyxHQUFHLElBQUksU0FBUztZQUNqQixPQUFPO1FBRVQsT0FBTyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFHZixLQUFJLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBQztZQUFDLE9BQU8sS0FBSyxDQUFBO1NBQUM7UUFFL0IsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDekIsQ0FBQyxDQUFDO0lBRUYsSUFBSSxDQUFDLEdBQUcsR0FBRyxVQUFTLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTTtRQUVuQyxJQUFHLEtBQUssSUFBSSxTQUFTO1lBQ25CLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFakMsSUFBSSxHQUFHLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFCLElBQUcsR0FBRyxJQUFJLFNBQVM7WUFDakIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUM7UUFFN0IsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUNsQixDQUFDLENBQUM7QUFDSixDQUFDO0FBQUEsQ0FBQztBQUdGLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxHQUFHLFVBQVMsRUFBRSxFQUFFLE1BQU07SUFFeEMsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDakMsSUFBRyxLQUFLLElBQUksU0FBUztRQUNuQixPQUFPLFNBQVMsQ0FBQztJQUVuQixJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUV4QixPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMsQ0FBQztBQUdGLE1BQU0sQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDOzs7QUNoRHhCLElBQUksYUFBYSxHQUFJLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBR2hELE9BQU8sQ0FBQyxhQUFhLEdBQUksYUFBYSxDQUFDOzs7QUNIdkMsSUFBSSxVQUFVLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hDLElBQUkseUJBQXlCLEdBQUcsT0FBTyxDQUFDLHdDQUF3QyxDQUFDLENBQUM7QUFFbEYsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJO0lBQ25CLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQztBQUNyQixDQUFDLENBQUM7QUFFRixJQUFJLGFBQWEsR0FBRyxJQUFJLENBQUM7QUFFekIsSUFBSSxZQUFZLEdBQUcsY0FBYyxDQUFDO0FBQ2xDLElBQUksU0FBUyxHQUFHLFdBQVcsQ0FBQztBQUM1QixJQUFJLFlBQVksR0FBRyxjQUFjLENBQUM7QUFFbEMsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDO0FBdUJyQix1QkFBdUIsYUFBYTtJQUVoQyxJQUFJLElBQUksR0FBRyxJQUFJLENBQUM7SUFFaEIsSUFBSSxRQUFRLEdBQUcsYUFBYSxDQUFDLEVBQUUsQ0FBQztJQUVoQyxJQUFJLHlCQUF5QixHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRW5DLElBQUksV0FBVyxHQUFHLENBQUMsQ0FBQztJQUNwQixJQUFJLFlBQVksR0FBRyxJQUFJLENBQUM7SUFDeEIsSUFBSSxlQUFlLEdBQUcsS0FBSyxDQUFDO0lBQzVCLElBQUksWUFBWSxDQUFDO0lBRWpCLElBQUksTUFBTSxHQUFHLFlBQVksQ0FBQztJQUUxQixJQUFJLGNBQWMsR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDO0lBQzdDLElBQUksYUFBYSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUM7SUFDM0MsSUFBSSxXQUFXLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQztJQUN2QyxJQUFJLE9BQU8sR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDO0lBRS9CLGFBQWEsQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLFVBQVMsTUFBTSxFQUFFLE9BQU87UUFDN0MsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDaEMsQ0FBQyxDQUFBO0lBRUQsUUFBUSxDQUFDLGNBQWMsR0FBRztRQUN0QixNQUFNLENBQUMsS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7UUFDckQsSUFBSSxNQUFNLEtBQUssWUFBWSxFQUFFO1lBQ3pCLE1BQU0sQ0FBQyxLQUFLLENBQUMsa0dBQWtHLENBQUMsQ0FBQztZQUNqSCxPQUFPO1NBQ1Y7UUFFRCxNQUFNLEdBQUcsWUFBWSxDQUFDO1FBQ3RCLElBQUksY0FBYyxFQUFFO1lBQ2hCLGNBQWMsRUFBRSxDQUFDO1NBQ3BCO0lBQ0wsQ0FBQyxDQUFBO0lBRUQsUUFBUSxDQUFDLGFBQWEsR0FBRztRQUNyQixNQUFNLENBQUMsS0FBSyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7UUFDcEQsSUFBSSxNQUFNLEtBQUssU0FBUyxFQUFFO1lBQ3RCLE1BQU0sQ0FBQyxLQUFLLENBQUMsOEZBQThGLENBQUMsQ0FBQztZQUM3RyxPQUFPO1NBQ1Y7UUFDRCxNQUFNLEdBQUcsU0FBUyxDQUFDO1FBRW5CLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDcEIsNEJBQTRCLEVBQUUsQ0FBQztRQUMvQixPQUFPLEVBQUUsQ0FBQztRQUVWLElBQUksYUFBYSxFQUFFO1lBQ2YsYUFBYSxFQUFFLENBQUM7U0FDbkI7SUFDTCxDQUFDLENBQUE7SUFFRCxRQUFRLENBQUMsV0FBVyxHQUFHO1FBQ25CLE1BQU0sQ0FBQyxLQUFLLENBQUMsbUNBQW1DLENBQUMsQ0FBQztRQUNsRCxJQUFJLE1BQU0sS0FBSyxTQUFTLEVBQUU7WUFDdEIsTUFBTSxDQUFDLEtBQUssQ0FBQyw0RkFBNEYsQ0FBQyxDQUFDO1lBQzNHLE9BQU87U0FDVjtRQUNELE1BQU0sR0FBRyxTQUFTLENBQUM7UUFFbkIsWUFBWSxHQUFHLElBQUksQ0FBQztRQUNwQixPQUFPLEVBQUUsQ0FBQztRQUVWLElBQUksV0FBVyxFQUFFO1lBQ2IsV0FBVyxFQUFFLENBQUM7U0FDakI7SUFDTCxDQUFDLENBQUE7SUFFRCxRQUFRLENBQUMsT0FBTyxHQUFHLFVBQVMsS0FBSztRQUM3QixNQUFNLENBQUMsS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7UUFFOUMsTUFBTSxHQUFHLFlBQVksQ0FBQztRQUV0QixJQUFJLE9BQU8sRUFBRTtZQUNULE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUNsQjtJQUNMLENBQUMsQ0FBQTtJQUVELElBQUksRUFBRSxHQUFHLElBQUkseUJBQXlCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFakQsTUFBTSxDQUFDLEtBQUssQ0FBQywrQkFBK0IsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFN0QsSUFBSSxpQkFBaUIsR0FBRztRQUNwQixlQUFlLEVBQUUsYUFBYSxDQUFDLEdBQUcsQ0FBQyxjQUFjO1FBQ2pELG9CQUFvQixFQUFFLGFBQWEsQ0FBQyxHQUFHLENBQUMsdUJBQXVCO0tBQ2xFLENBQUM7SUFFRixJQUFJLEdBQUcsR0FBRyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxFQUFFLEVBQ3RFLFVBQVMsT0FBTztRQUVaLE1BQU0sQ0FBQyxLQUFLLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBRTdELElBQUk7WUFDQSxJQUFJLElBQUksR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUU3QyxJQUFJLElBQUksS0FBSyxTQUFTLEVBQUU7Z0JBQ3BCLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsMkJBQTJCLENBQUMsQ0FBQzthQUMxRTtpQkFBTTtnQkFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQzthQUNqQztTQUNKO1FBQUMsT0FBTyxHQUFHLEVBQUU7WUFDVixNQUFNLENBQUMsS0FBSyxDQUFDLGdDQUFnQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUN6RSxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3JCO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFUCxJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVMsTUFBTSxFQUFFLE1BQU0sRUFBRSxRQUFRO1FBQ3pDLElBQUksTUFBTSxLQUFLLE1BQU0sRUFBRTtZQUNuQixNQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixHQUFHLE1BQU0sR0FBRyxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1NBQ25GO1FBRUQsSUFBSSxXQUFXLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRTdCLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxVQUFTLEtBQUssRUFBRSxNQUFNO1lBQzdDLElBQUksS0FBSyxFQUFFO2dCQUNQLElBQUk7b0JBQ0EsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLE9BQU8sR0FBRyxzQkFBc0I7d0JBQzFELE1BQU0sR0FBRyxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxXQUFXO3dCQUMxRCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7b0JBQ25CLElBQUksS0FBSyxDQUFDLElBQUksRUFBRTt3QkFDWixNQUFNLENBQUMsS0FBSyxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO3FCQUM1RDtpQkFDSjtnQkFBQyxPQUFPLENBQUMsRUFBRSxHQUFFO2dCQUNkLEtBQUssQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO2FBQ25DO1lBQ0QsSUFBSSxRQUFRLEVBQUU7Z0JBQ1YsSUFBSSxNQUFNLElBQUksU0FBUyxJQUFJLE1BQU0sQ0FBQyxLQUFLLEtBQUssTUFBTSxFQUFFO29CQUNoRCxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7aUJBQ3ZEO2dCQUNELFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7YUFDM0I7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUMsQ0FBQTtJQUVEO1FBQ0ksTUFBTSxDQUFDLEtBQUssQ0FBQyw4QkFBOEIsR0FBRyxXQUFXLEdBQUcsUUFBUTtZQUNoRSx5QkFBeUIsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUNyQyx5QkFBeUIsR0FBRyxXQUFXLENBQUM7SUFDNUMsQ0FBQztJQUVEO1FBQ0ksSUFBSSxZQUFZLEVBQUU7WUFDZCxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUM7WUFDbEIsSUFBSSxXQUFXLElBQUksQ0FBQyxJQUFJLFdBQVcsSUFBSSx5QkFBeUIsRUFBRTtnQkFDOUQsTUFBTSxHQUFHO29CQUNMLFFBQVEsRUFBRSxhQUFhLENBQUMsU0FBUyxJQUFJLGFBQWE7aUJBQ3JELENBQUM7YUFDTDtZQUNELFdBQVcsRUFBRSxDQUFDO1lBRWQsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUMsVUFBUyxPQUFPO2dCQUN2QyxPQUFPLFVBQVMsS0FBSyxFQUFFLE1BQU07b0JBQ3pCLElBQUksS0FBSyxFQUFFO3dCQUNQLE1BQU0sQ0FBQyxLQUFLLENBQUMseUJBQXlCLEdBQUcsT0FBTyxHQUFHLElBQUk7NEJBQ25ELEtBQUssQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDLENBQUM7d0JBQ3pCLElBQUksT0FBTyxHQUFHLHlCQUF5QixFQUFFOzRCQUNyQyxZQUFZLEdBQUcsS0FBSyxDQUFDOzRCQUNyQiw0QkFBNEIsRUFBRSxDQUFDOzRCQUMvQixNQUFNLENBQUMsS0FBSyxDQUFDLDBDQUEwQztnQ0FDbkQsT0FBTyxHQUFHLG9CQUFvQixDQUFDLENBQUM7NEJBQ3BDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQzt5QkFDcEI7cUJBQ0o7Z0JBQ0wsQ0FBQyxDQUFBO1lBQ0wsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztTQUNwQjthQUFNO1lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1NBQ2hFO0lBQ0wsQ0FBQztJQU1EO1FBQ0ksSUFBSSxDQUFDLGVBQWUsRUFBRTtZQUNsQixNQUFNLENBQUMsS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUE7WUFDN0MsZUFBZSxHQUFHLElBQUksQ0FBQztZQUV2QixJQUFJLGFBQWEsQ0FBQyxTQUFTLElBQUksU0FBUyxFQUFFO2dCQUN0QyxZQUFZLEdBQUcsV0FBVyxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQzlELFFBQVEsRUFBRSxDQUFDO2FBQ2Q7U0FDSjtJQUNMLENBQUM7SUFFRCxJQUFJLENBQUMsS0FBSyxHQUFHO1FBQ1QsTUFBTSxDQUFDLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO1FBRTNELElBQUksWUFBWSxJQUFJLFNBQVMsRUFBRTtZQUMzQixNQUFNLENBQUMsS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUM7WUFDdkMsYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQy9CO1FBQ0QsZUFBZSxHQUFHLEtBQUssQ0FBQztRQUN4QixZQUFZLEdBQUcsS0FBSyxDQUFDO1FBRXJCLElBQUksYUFBYSxDQUFDLGdCQUFnQixFQUFFO1lBQ2hDLE1BQU0sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQTtZQUNyQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxJQUFJLEVBQUUsVUFBUyxLQUFLLEVBQUUsTUFBTTtnQkFDbEQsSUFBSSxLQUFLLEVBQUU7b0JBQ1AsTUFBTSxDQUFDLEtBQUssQ0FBQywrQkFBK0IsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQ3pFO2dCQUNELEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNmLENBQUMsQ0FBQyxDQUFDO1NBQ047YUFBTTtZQUNaLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztTQUNMO0lBQ0wsQ0FBQyxDQUFBO0lBR0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFTLE1BQU07UUFDN0IsRUFBRSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxQixDQUFDLENBQUE7SUFFRCxJQUFJLENBQUMsU0FBUyxHQUFHO1FBQ2IsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3JCLENBQUMsQ0FBQTtBQUNMLENBQUM7QUFHRCxNQUFNLENBQUMsT0FBTyxHQUFHLGFBQWEsQ0FBQzs7O0FDbFEvQixJQUFJLHlCQUF5QixHQUFJLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0FBR3hFLE9BQU8sQ0FBQyx5QkFBeUIsR0FBSSx5QkFBeUIsQ0FBQzs7OztBQ0ovRCxZQUFZLENBQUM7QUFFYixJQUFJLGdCQUFnQixHQUFHLE1BQU0sQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDLFlBQVksQ0FBQztBQUUvRCxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUM7QUFpQnJCLElBQUksV0FBVyxHQUFHLElBQUksQ0FBQztBQUN2QixJQUFJLGFBQWEsR0FBRyxJQUFJLENBQUM7QUFFekIsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0FBQ25CLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQztBQUNiLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQztBQUNoQixJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7QUFZZixtQ0FBbUMsTUFBTTtJQUVyQyxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDcEIsSUFBSSxzQkFBc0IsQ0FBQztJQUMzQixJQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDO0lBQ3ZCLElBQUksU0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUM7SUFDakMsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFDO0lBRXpCLElBQUksb0JBQW9CLEdBQUcsS0FBSyxDQUFDO0lBRWpDLElBQUksRUFBRSxDQUFDO0lBRVAsSUFBSSxTQUFTLEVBQUU7UUFDWCxFQUFFLEdBQUcsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDMUI7U0FBTTtRQUNILEVBQUUsR0FBRyxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztLQUM3QjtJQUVELEVBQUUsQ0FBQyxNQUFNLEdBQUc7UUFDUixZQUFZLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3hCLElBQUksTUFBTSxDQUFDLFdBQVcsRUFBRTtZQUNwQixNQUFNLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDeEI7SUFDTCxDQUFDLENBQUM7SUFFRixFQUFFLENBQUMsT0FBTyxHQUFHLFVBQVMsS0FBSztRQUN2QixNQUFNLENBQUMsS0FBSyxDQUFDLHVCQUF1QixHQUFHLEtBQUssR0FBRyxnQ0FBZ0MsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN4RixJQUFJLE1BQU0sQ0FBQyxPQUFPLEVBQUU7WUFDaEIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUN6QjtJQUNMLENBQUMsQ0FBQztJQUVGLHNCQUFzQixFQUFFLEVBQUUsS0FBSztRQUMzQixJQUFJO1lBQ0EsTUFBTSxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxLQUFLLENBQUMsQ0FBQztTQUNuRDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1IsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNuQjtJQUNMLENBQUM7SUFFRCxJQUFJLG1CQUFtQixHQUFHO1FBQ3RCLElBQUksRUFBRSxDQUFDLFVBQVUsS0FBSyxNQUFNLEVBQUU7WUFDMUIsSUFBSSxPQUFPLEVBQUU7Z0JBQ1QsTUFBTSxDQUFDLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO2FBQzdDO2lCQUFNO2dCQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsaURBQWlELENBQUMsQ0FBQztnQkFDaEUsa0JBQWtCLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO2FBQ3RDO1NBQ0o7YUFBTTtZQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQztTQUN2RTtJQUNMLENBQUMsQ0FBQztJQUVGLEVBQUUsQ0FBQyxPQUFPLEdBQUcsbUJBQW1CLENBQUM7SUFFakMsNEJBQTRCLFVBQVUsRUFBRSxVQUFVO1FBQzlDLE1BQU0sQ0FBQyxLQUFLLENBQUMsK0JBQStCLEdBQUcsVUFBVSxHQUFHLFFBQVEsR0FBRyxVQUFVLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFFekYsSUFBSSxVQUFVLEtBQUssQ0FBQyxFQUFFO1lBQ2xCLElBQUksWUFBWSxFQUFFO2dCQUNkLE1BQU0sQ0FBQyxJQUFJLENBQUMsOEVBQThFLENBQUMsQ0FBQTtnQkFDM0YsT0FBTzthQUNWO2lCQUFNO2dCQUNILFlBQVksR0FBRyxJQUFJLENBQUM7YUFDdkI7WUFFRCxJQUFJLE1BQU0sQ0FBQyxjQUFjLEVBQUU7Z0JBQ3ZCLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQzthQUMzQjtTQUNKO1FBRUQsSUFBSSxvQkFBb0IsRUFBRTtZQUN0QixpQkFBaUIsQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBRXBEO2FBQU07WUFDSCxJQUFJLE1BQU0sQ0FBQyxzQkFBc0IsRUFBRTtnQkFDL0IsTUFBTSxDQUFDLHNCQUFzQixDQUFDLFVBQVMsS0FBSyxFQUFFLFFBQVE7b0JBRWxELElBQUksS0FBSyxFQUFFO3dCQUNQLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7d0JBQ3BCLFVBQVUsQ0FBQzs0QkFDUCxrQkFBa0IsQ0FBQyxVQUFVLEVBQUUsVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDO3dCQUNuRCxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7cUJBQ3JCO3lCQUFNO3dCQUNILGlCQUFpQixDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7cUJBQ3ZEO2dCQUNMLENBQUMsQ0FBQyxDQUFBO2FBQ0w7aUJBQU07Z0JBQ0gsaUJBQWlCLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQzthQUNwRDtTQUNKO0lBQ0wsQ0FBQztJQUdELDJCQUEyQixVQUFVLEVBQUUsVUFBVSxFQUFFLGNBQWM7UUFDN0QsTUFBTSxDQUFDLEtBQUssQ0FBQyx3QkFBd0IsR0FBRyxVQUFVLENBQUMsQ0FBQztRQUVwRCxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFWCxLQUFLLEdBQUcsY0FBYyxJQUFJLEtBQUssQ0FBQztRQUVoQyxJQUFJLEtBQUssQ0FBQztRQUNWLElBQUksU0FBUyxFQUFFO1lBQ1gsS0FBSyxHQUFHLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQzdCO2FBQU07WUFDSCxLQUFLLEdBQUcsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDaEM7UUFFRCxLQUFLLENBQUMsTUFBTSxHQUFHO1lBQ1gsTUFBTSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsR0FBRyxVQUFVLEdBQUcsY0FBYyxDQUFDLENBQUM7WUFDakUsWUFBWSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztZQUMzQixZQUFZLEdBQUcsS0FBSyxDQUFDO1lBQ3JCLHNCQUFzQixFQUFFLENBQUM7WUFDekIsSUFBSSxNQUFNLENBQUMsYUFBYSxFQUFFLEVBQUU7Z0JBQ3hCLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQzthQUMxQjtZQUVELEtBQUssQ0FBQyxPQUFPLEdBQUcsbUJBQW1CLENBQUM7UUFDeEMsQ0FBQyxDQUFDO1FBRUYsSUFBSSxjQUFjLEdBQUcsVUFBUyxLQUFLO1lBQy9CLE1BQU0sQ0FBQyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFM0MsSUFBSSxVQUFVLEtBQUssVUFBVSxFQUFFO2dCQUMzQixJQUFJLE1BQU0sQ0FBQyxZQUFZLEVBQUU7b0JBQ3JCLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztpQkFDekI7YUFDSjtpQkFBTTtnQkFDSCxVQUFVLENBQUM7b0JBQ1Asa0JBQWtCLENBQUMsVUFBVSxFQUFFLFVBQVUsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDbkQsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO2FBQ3JCO1FBQ0wsQ0FBQyxDQUFDO1FBRUYsS0FBSyxDQUFDLE9BQU8sR0FBRyxjQUFjLENBQUM7UUFFL0IsRUFBRSxHQUFHLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxJQUFJLENBQUMsS0FBSyxHQUFHO1FBQ1QsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNmLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNmLENBQUMsQ0FBQztJQUlGLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBUyxNQUFNO1FBQzdCLE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztRQUUvQyxJQUFJLE1BQU0sRUFBRTtZQUNSLE1BQU0sQ0FBQyxLQUFLLENBQUMsNEJBQTRCLEdBQUcsTUFBTSxHQUFHLGlDQUFpQyxDQUFDLENBQUM7WUFDeEYsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDO1lBQ3RCLEtBQUssR0FBRywyQkFBMkIsQ0FBQztZQUVwQyxvQkFBb0IsR0FBRyxJQUFJLENBQUM7WUFFNUIsVUFBVSxDQUFDO2dCQUNQLE1BQU0sQ0FBQyxLQUFLLENBQUMsOEJBQThCLEdBQUcsU0FBUyxDQUFDLENBQUM7Z0JBQ3pELEtBQUssR0FBRyxTQUFTLENBQUM7Z0JBRWxCLG9CQUFvQixHQUFHLEtBQUssQ0FBQztZQUVqQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7U0FDZDtRQUVELEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNmLENBQUMsQ0FBQztJQUVGLElBQUksQ0FBQyxXQUFXLEdBQUc7UUFDZixNQUFNLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzVCLGtCQUFrQixDQUFDLFdBQVcsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDOUMsQ0FBQyxDQUFDO0lBRUYsSUFBSSxDQUFDLElBQUksR0FBRyxVQUFTLE9BQU87UUFDeEIsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyQixDQUFDLENBQUM7SUFFRixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsVUFBUyxJQUFJLEVBQUUsUUFBUTtRQUMzQyxzQkFBc0IsR0FBRztZQUNyQixFQUFFLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ3hDLENBQUMsQ0FBQztRQUVGLHNCQUFzQixFQUFFLENBQUM7SUFDN0IsQ0FBQyxDQUFDO0FBQ04sQ0FBQztBQUVELE1BQU0sQ0FBQyxPQUFPLEdBQUcseUJBQXlCLENBQUM7Ozs7O0FDL04zQyxJQUFJLGtCQUFrQixHQUFHLEtBQUssQ0FBQTtBQUM5QixJQUFHLE1BQU0sQ0FBQyxjQUFjLEVBQ3hCO0lBQ0UsSUFDQTtRQUNFLE1BQU0sQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztLQUNwQztJQUNELE9BQU0sQ0FBQyxFQUNQO1FBQ0Usa0JBQWtCLEdBQUcsSUFBSSxDQUFBO0tBQzFCO0NBQ0Y7QUFHRCxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUU7SUFDNUIsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEdBQUcsVUFBUyxLQUFLO1FBQ3RDLElBQUksT0FBTyxJQUFJLEtBQUssVUFBVSxFQUFFO1lBRzlCLE1BQU0sSUFBSSxTQUFTLENBQUMsc0VBQXNFLENBQUMsQ0FBQztTQUM3RjtRQUVELElBQUksS0FBSyxHQUFLLEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQ2xELE9BQU8sR0FBRyxJQUFJLEVBQ2QsSUFBSSxHQUFNLGNBQVksQ0FBQyxFQUN2QixNQUFNLEdBQUk7WUFDUixPQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxZQUFZLElBQUksSUFBSSxLQUFLO2dCQUMzQyxDQUFDLENBQUMsSUFBSTtnQkFDTixDQUFDLENBQUMsS0FBSyxFQUNQLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5RCxDQUFDLENBQUM7UUFFTixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDaEMsTUFBTSxDQUFDLFNBQVMsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBRTlCLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUMsQ0FBQztDQUNIO0FBR0QsSUFBSSxZQUFZLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLFlBQVksQ0FBQztBQUVsRCxJQUFJLFFBQVEsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7QUFFbkMsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQ25DLElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUdqQyxJQUFJLFlBQVksR0FBRyxJQUFJLENBQUM7QUFHeEIsOEJBQThCLGVBQWU7SUFFM0MsSUFBRyxDQUFDLGVBQWU7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUUvQixLQUFJLElBQUksR0FBRyxJQUFJLGVBQWUsRUFDOUI7UUFDRSxJQUFJLEtBQUssR0FBRyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFakMsSUFBRyxPQUFPLEtBQUssSUFBSSxRQUFRO1lBQ3pCLGVBQWUsQ0FBQyxHQUFHLENBQUM7Z0JBQ3BCO29CQUNFLFFBQVEsRUFBRSxLQUFLO2lCQUNoQixDQUFBO0tBQ0o7SUFBQSxDQUFDO0lBRUYsT0FBTyxlQUFlLENBQUM7QUFDekIsQ0FBQztBQUFBLENBQUM7QUFFRix3QkFBd0IsU0FBUztJQUUvQixJQUFHLENBQUMsU0FBUztRQUFFLE9BQU87SUFHdEIsSUFBRyxTQUFTLFlBQVksUUFBUTtRQUM5QixPQUFPLEVBQUMsSUFBSSxFQUFFLFNBQVMsRUFBQyxDQUFDO0lBRzNCLElBQUcsU0FBUyxDQUFDLElBQUksWUFBWSxRQUFRO1FBQ25DLE9BQU8sU0FBUyxDQUFDO0lBR25CLElBQUcsU0FBUyxDQUFDLFdBQVcsWUFBWSxRQUFRLEVBQzVDO1FBQ0UsU0FBUyxDQUFDLElBQUksR0FBRyxTQUFTLENBQUMsV0FBVyxDQUFDO1FBQ3ZDLE9BQU8sU0FBUyxDQUFDO0tBQ2xCO0lBR0QsSUFBRyxTQUFTLENBQUMsS0FBSyxZQUFZLFFBQVEsRUFDdEM7UUFDRSxTQUFTLENBQUMsSUFBSSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUM7UUFDakMsT0FBTyxTQUFTLENBQUM7S0FDbEI7SUFHRCxJQUFHLFNBQVMsQ0FBQyxTQUFTLEtBQUssU0FBUztRQUFFLE9BQU87SUFDN0MsSUFBRyxTQUFTLENBQUMsS0FBSyxZQUFZLFFBQVE7UUFBRSxPQUFPO0lBRS9DLE1BQU0sSUFBSSxXQUFXLENBQUMsZ0RBQWdELENBQUMsQ0FBQztBQUMxRSxDQUFDO0FBQUEsQ0FBQztBQWFGLHlCQUF5QixNQUFNLEVBQUUsTUFBTTtJQUVyQyxJQUFHLGtCQUFrQixFQUNyQjtRQUNFLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO1FBQ3BCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO0tBQ3JCO1NBRUQ7UUFDRSxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO1FBQ3pFLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBQyxDQUFDLENBQUM7S0FDMUU7QUFDSCxDQUFDO0FBQUEsQ0FBQztBQWdCRixvQkFBb0IsTUFBTSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUztJQUV2RCxJQUFJLElBQUksR0FBRyxJQUFJLENBQUM7SUFFaEIsSUFBRyxDQUFDLE1BQU07UUFDUixNQUFNLElBQUksV0FBVyxDQUFDLHVCQUF1QixDQUFDLENBQUM7SUFFakQsSUFBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTtRQUMvQixNQUFNLElBQUksV0FBVyxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFFN0MsSUFBSSxlQUFlLEdBQUcsb0JBQW9CLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBR25FLElBQUcsT0FBTyxZQUFZLFFBQVEsRUFDOUI7UUFDRSxJQUFHLFNBQVMsSUFBSSxTQUFTO1lBQ3ZCLE1BQU0sSUFBSSxXQUFXLENBQUMsMkNBQTJDLENBQUMsQ0FBQztRQUVyRSxTQUFTLEdBQUcsT0FBTyxDQUFDO1FBQ3BCLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDdEIsT0FBTyxHQUFLLFNBQVMsQ0FBQztLQUN2QjtJQUFBLENBQUM7SUFFRixJQUFHLE9BQU8sSUFBSSxPQUFPLENBQUMsSUFBSSxZQUFZLFFBQVEsRUFDOUM7UUFDRSxJQUFHLFNBQVMsSUFBSSxDQUFDLENBQUMsU0FBUyxZQUFZLFFBQVEsQ0FBQztZQUM5QyxNQUFNLElBQUksV0FBVyxDQUFDLHdDQUF3QyxDQUFDLENBQUM7UUFFbEUsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUN0QixTQUFTLEdBQUcsT0FBTyxDQUFDO1FBQ3BCLE9BQU8sR0FBSyxTQUFTLENBQUM7S0FDdkI7SUFBQSxDQUFDO0lBRUYsSUFBRyxTQUFTLFlBQVksUUFBUSxFQUNoQztRQUNFLElBQUcsU0FBUyxJQUFJLFNBQVM7WUFDdkIsTUFBTSxJQUFJLFdBQVcsQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1FBRXJFLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDdEIsU0FBUyxHQUFHLFNBQVMsQ0FBQztLQUN2QjtJQUFBLENBQUM7SUFFRixJQUFHLFNBQVMsSUFBSSxTQUFTLENBQUMsSUFBSSxZQUFZLFFBQVE7UUFDaEQsSUFBRyxTQUFTLElBQUksQ0FBQyxDQUFDLFNBQVMsWUFBWSxRQUFRLENBQUM7WUFDOUMsTUFBTSxJQUFJLFdBQVcsQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDO0lBRXBFLE9BQU8sR0FBRyxPQUFPLElBQUksRUFBRSxDQUFDO0lBR3hCLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFeEIsSUFBRyxTQUFTO1FBQ1YsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFHaEMsSUFBRyxrQkFBa0I7UUFDbkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFBOztRQUU1QixNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLE1BQU0sRUFBQyxDQUFDLENBQUM7SUFFakUsSUFBSSxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUM7SUFHM0MsMEJBQTBCLEtBQUs7UUFFN0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFBQSxDQUFDO0lBRUYsSUFBSSxDQUFDLFlBQVksR0FBRztRQUVsQixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDLENBQUE7SUFDRCxJQUFJLENBQUMsWUFBWSxHQUFHLFVBQVMsS0FBSztRQUdoQyxJQUFHLFNBQVMsRUFDWjtZQUVFLElBQUcsU0FBUyxDQUFDLG1CQUFtQjtnQkFDOUIsU0FBUyxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO2lCQUd4RCxJQUFHLFNBQVMsQ0FBQyxjQUFjO2dCQUM5QixTQUFTLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1NBQ3REO1FBQUEsQ0FBQztRQUdGLElBQUcsS0FBSyxFQUNSO1lBRUUsSUFBRyxLQUFLLENBQUMsZ0JBQWdCO2dCQUN2QixLQUFLLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7aUJBR2pELElBQUcsS0FBSyxDQUFDLFdBQVc7Z0JBQ3ZCLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLGdCQUFnQixDQUFDLENBQUM7U0FDL0M7UUFBQSxDQUFDO1FBRUYsU0FBUyxHQUFHLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNwQyxDQUFDLENBQUE7SUFFRCxJQUFHLENBQUMsa0JBQWtCO1FBQ3BCLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFDdkM7WUFDRSxHQUFHLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ2pDLEdBQUcsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7U0FDbEMsQ0FBQyxDQUFBO0lBRUosSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUc3QixJQUFJLGVBQWUsR0FBUSxPQUFPLENBQUMsZUFBZSxJQUFTLFlBQVksQ0FBQztJQUN4RSxJQUFJLG9CQUFvQixHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsSUFBSSxlQUFlLENBQUM7SUFDM0UsSUFBSSxnQkFBZ0IsR0FBTyxPQUFPLENBQUMsZ0JBQWdCLElBQVEsWUFBWSxDQUFDO0lBQ3hFLElBQUksa0JBQWtCLEdBQUssT0FBTyxDQUFDLGtCQUFrQixJQUFNLFlBQVksQ0FBQztJQUd4RSxJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7SUFFbEIsSUFBSSxRQUFRLEdBQUksSUFBSSxNQUFNLEVBQUUsQ0FBQztJQUM3QixJQUFJLFNBQVMsR0FBRyxJQUFJLE1BQU0sRUFBRSxDQUFDO0lBQzdCLElBQUksa0JBQWtCLEdBQUcsSUFBSSxNQUFNLEVBQUUsQ0FBQztJQUV0QyxJQUFJLFdBQVcsR0FBRyxFQUFFLENBQUM7SUFNckIsdUJBQXVCLE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSTtRQUV0QyxJQUFJLFFBQVEsR0FDWjtZQUNFLE9BQU8sRUFBRSxPQUFPO1lBRWhCLE9BQU8sRUFBRSxVQUFVLENBQUM7Z0JBRWxCLFNBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzdCLENBQUMsRUFDRCxnQkFBZ0IsQ0FBQztTQUNsQixDQUFDO1FBRUYsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFBQSxDQUFDO0lBS0YsZ0NBQWdDLEdBQUcsRUFBRSxJQUFJO1FBRXZDLElBQUksT0FBTyxHQUFHLFVBQVUsQ0FBQztZQUV2QixrQkFBa0IsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3ZDLENBQUMsRUFDRCxrQkFBa0IsQ0FBQyxDQUFDO1FBRXBCLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFBQSxDQUFDO0lBZ0JGLG9CQUFvQixNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUztRQUVyRCxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFM0MsSUFBSSxDQUFDLFlBQVksR0FBRztZQUVsQixPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDLENBQUE7UUFDRCxJQUFJLENBQUMsWUFBWSxHQUFHLFVBQVMsS0FBSztZQUVoQyxTQUFTLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BDLENBQUMsQ0FBQTtRQUVELElBQUcsQ0FBQyxrQkFBa0I7WUFDcEIsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUN2QztnQkFDRSxHQUFHLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2dCQUNqQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2FBQ2xDLENBQUMsQ0FBQTtRQUVKLElBQUksUUFBUSxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBS3ZDLElBQUcsQ0FBQyxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsRUFDdEM7WUFDRSxJQUFHLGtCQUFrQjtnQkFDbkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7O2dCQUVuQyxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxZQUFZLEVBQ3hDO29CQUNFLEtBQUssRUFBRSxPQUFPLENBQUMsUUFBUSxDQUFDO2lCQUN6QixDQUFDLENBQUM7U0FDTjtRQUVELElBQUksY0FBYyxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUU3QyxJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFVOUMsSUFBSSxDQUFDLEtBQUssR0FBRyxVQUFTLEtBQUssRUFBRSxNQUFNLEVBQUUsU0FBUztZQUc1QyxJQUFHLEtBQUssWUFBWSxRQUFRLElBQUksS0FBSyxJQUFJLEtBQUssQ0FBQyxJQUFJLFlBQVksUUFBUSxFQUN2RTtnQkFDRSxJQUFHLE1BQU0sSUFBSSxTQUFTO29CQUNwQixNQUFNLElBQUksV0FBVyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7Z0JBRXBFLFNBQVMsR0FBRyxLQUFLLENBQUM7Z0JBQ2xCLE1BQU0sR0FBRyxJQUFJLENBQUM7Z0JBQ2QsS0FBSyxHQUFHLFNBQVMsQ0FBQzthQUNuQjtpQkFFSSxJQUFHLE1BQU0sWUFBWSxRQUFRO21CQUMvQixNQUFNLElBQUksTUFBTSxDQUFDLElBQUksWUFBWSxRQUFRLEVBQzVDO2dCQUNFLElBQUcsU0FBUyxJQUFJLFNBQVM7b0JBQ3ZCLE1BQU0sSUFBSSxXQUFXLENBQUMsMENBQTBDLENBQUMsQ0FBQztnQkFFcEUsU0FBUyxHQUFHLE1BQU0sQ0FBQztnQkFDbkIsTUFBTSxHQUFHLElBQUksQ0FBQzthQUNmO1lBQUEsQ0FBQztZQUVGLFNBQVMsR0FBRyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUM7WUFHdEMsSUFBRyxRQUFRO2dCQUNULFlBQVksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFakMsSUFBRyxJQUFJLElBQUksU0FBUyxFQUNwQjtnQkFDRSxJQUFHLEtBQUs7b0JBQ04sS0FBSyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7Z0JBRXBCLElBQUcsTUFBTTtvQkFDUCxNQUFNLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQzthQUN0QjtZQUFBLENBQUM7WUFFRixJQUFJLE9BQU8sQ0FBQztZQUdaLElBQUcsS0FBSyxJQUFJLE1BQU0sSUFBSSxTQUFTLEVBQy9CO2dCQUNFLElBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxTQUFTLEVBQzNCO29CQUNFLElBQUcsS0FBSzt3QkFDTixLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7O3dCQUV6QixNQUFNLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7aUJBQzdCO2dCQUdELElBQUcsY0FBYyxFQUNqQjtvQkFDRSxJQUFHLGNBQWMsQ0FBQyxLQUFLLElBQUksU0FBUyxJQUFJLEtBQUs7d0JBQzNDLE9BQU87NEJBQ1A7Z0NBQ0UsS0FBSyxFQUFFLEtBQUs7NkJBQ2IsQ0FBQzt5QkFHSjt3QkFDRSxJQUFJLE1BQU0sR0FBRyxLQUFLOzRCQUNQLENBQUMsQ0FBQyxjQUFjLENBQUMsS0FBSzs0QkFDdEIsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUM7d0JBRXJDLE9BQU87NEJBQ1A7Z0NBQ0UsTUFBTSxFQUFFLE1BQU07Z0NBQ2QsTUFBTSxFQUFFLEtBQUssSUFBSSxNQUFNOzZCQUN4QixDQUFDO3FCQUNIO2lCQUNGOztvQkFFQyxPQUFPO3dCQUNQOzRCQUNFLEtBQUssRUFBRyxLQUFLOzRCQUNiLE1BQU0sRUFBRSxNQUFNO3lCQUNmLENBQUM7Z0JBRUosT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2FBQ3BDO2lCQUdJLElBQUcsUUFBUTtnQkFDZCxPQUFPLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQzs7Z0JBSTNCLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBRzVDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBR2pDLFNBQVMsR0FBRyxTQUFTLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUVwRSxJQUFHLFNBQVM7Z0JBQ1YsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRWpDLE9BQU8sT0FBTyxDQUFDO1FBQ2pCLENBQUMsQ0FBQTtJQUNILENBQUM7SUFBQSxDQUFDO0lBQ0YsUUFBUSxDQUFDLFVBQVUsRUFBRSxlQUFlLENBQUMsQ0FBQztJQUd0QyxnQkFBZ0IsT0FBTztRQUVyQixJQUFJLEdBQUcsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDL0IsSUFBRyxDQUFDLEdBQUc7WUFBRSxPQUFPO1FBRWhCLE9BQU8sV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTVCLElBQUksT0FBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDN0MsSUFBRyxDQUFDLE9BQU87WUFBRSxPQUFPO1FBRXBCLFlBQVksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFHOUIsc0JBQXNCLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUFBLENBQUM7SUFPRixJQUFJLENBQUMsTUFBTSxHQUFHLFVBQVMsT0FBTztRQUU1QixJQUFHLE9BQU87WUFBRSxPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVuQyxLQUFJLElBQUksT0FBTyxJQUFJLFdBQVc7WUFDNUIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3BCLENBQUMsQ0FBQztJQUdGLElBQUksQ0FBQyxLQUFLLEdBQUc7UUFHWCxJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDcEMsSUFBRyxTQUFTLElBQUksU0FBUyxDQUFDLEtBQUs7WUFDNUIsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBR3JCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUVkLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUd6QyxTQUFTLENBQUMsT0FBTyxDQUFDLFVBQVMsUUFBUTtZQUVqQyxZQUFZLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDO0lBZUYsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFTLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxRQUFRO1FBRzlELElBQUcsTUFBTSxZQUFZLFFBQVEsRUFDN0I7WUFDRSxJQUFHLElBQUksSUFBSSxTQUFTO2dCQUNsQixNQUFNLElBQUksV0FBVyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7WUFFcEUsUUFBUSxHQUFJLE1BQU0sQ0FBQztZQUNuQixTQUFTLEdBQUcsU0FBUyxDQUFDO1lBQ3RCLElBQUksR0FBUSxTQUFTLENBQUM7WUFDdEIsTUFBTSxHQUFNLFNBQVMsQ0FBQztTQUN2QjthQUVJLElBQUcsSUFBSSxZQUFZLFFBQVEsRUFDaEM7WUFDRSxJQUFHLFNBQVMsSUFBSSxTQUFTO2dCQUN2QixNQUFNLElBQUksV0FBVyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7WUFFcEUsUUFBUSxHQUFJLElBQUksQ0FBQztZQUNqQixTQUFTLEdBQUcsU0FBUyxDQUFDO1lBQ3RCLElBQUksR0FBUSxTQUFTLENBQUM7U0FDdkI7YUFFSSxJQUFHLFNBQVMsWUFBWSxRQUFRLEVBQ3JDO1lBQ0UsSUFBRyxRQUFRLElBQUksU0FBUztnQkFDdEIsTUFBTSxJQUFJLFdBQVcsQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1lBRXBFLFFBQVEsR0FBSSxTQUFTLENBQUM7WUFDdEIsU0FBUyxHQUFHLFNBQVMsQ0FBQztTQUN2QjtRQUFBLENBQUM7UUFFRixJQUFHLElBQUksQ0FBQyxNQUFNLElBQUksU0FBUyxFQUMzQjtZQUNFLE1BQU0sR0FBRyxNQUFNLElBQUksRUFBRSxDQUFDO1lBRXRCLE1BQU0sQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztTQUMzQjtRQUFBLENBQUM7UUFFRixJQUFHLElBQUksSUFBSSxTQUFTLEVBQ3BCO1lBQ0UsTUFBTSxHQUFHLE1BQU0sSUFBSSxFQUFFLENBQUM7WUFFdEIsTUFBTSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7U0FDcEI7UUFBQSxDQUFDO1FBR0YsSUFBSSxPQUFPLEdBQ1g7WUFDRSxNQUFNLEVBQUUsTUFBTTtZQUNkLE1BQU0sRUFBRSxNQUFNO1NBQ2YsQ0FBQztRQUVGLElBQUcsUUFBUSxFQUNYO1lBQ0UsSUFBSSxFQUFFLEdBQUcsU0FBUyxFQUFFLENBQUM7WUFDckIsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO1lBRWhCLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztZQUVuQywwQkFBMEIsS0FBSyxFQUFFLE1BQU07Z0JBRXJDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBRXJCLFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDMUIsQ0FBQztZQUFBLENBQUM7WUFFRixJQUFJLE9BQU8sR0FDWDtnQkFDRSxPQUFPLEVBQVUsT0FBTztnQkFDeEIsUUFBUSxFQUFTLGdCQUFnQjtnQkFDakMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFO2FBQy9DLENBQUM7WUFFRixJQUFJLGdCQUFnQixHQUFHLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUVqRCxxQkFBcUIsU0FBUztnQkFFNUIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUM7Z0JBQ3RFLE9BQU8sQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLEdBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUNqRSxXQUFXLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUMsQ0FBQztnQkFDNUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUVoQyxTQUFTLEdBQUcsU0FBUyxJQUFJLGdCQUFnQixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDakUsSUFBRyxTQUFTO29CQUNWLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFFakMsT0FBTyxPQUFPLENBQUM7WUFDakIsQ0FBQztZQUFBLENBQUM7WUFFRixlQUFlLFNBQVM7Z0JBRXRCLFNBQVMsR0FBRyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBRXRDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxHQUFDLDZCQUE2QixFQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUU1RCxJQUFJLE9BQU8sR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUMvQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBRXRCLE9BQU8sV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ2hDLENBQUM7WUFBQSxDQUFDO1lBRUY7Z0JBRUUsSUFBRyxPQUFPLEdBQUcsV0FBVztvQkFDdEIsT0FBTyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBRTFCLElBQUksS0FBSyxHQUFHLElBQUksS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7Z0JBQzNDLEtBQUssQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO2dCQUU1QixLQUFLLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztnQkFFcEIsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDekIsQ0FBQztZQUFBLENBQUM7WUFFRixPQUFPLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUMvQjtRQUFBLENBQUM7UUFHRixPQUFPLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUUvQixTQUFTLEdBQUcsU0FBUyxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUM3QyxJQUFHLFNBQVM7WUFDVixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFakMsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQyxDQUFDO0lBYUYsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFTLE9BQU8sRUFBRSxTQUFTO1FBRXZDLElBQUcsQ0FBQyxPQUFPO1lBQ1QsTUFBTSxJQUFJLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBRWhELElBQ0E7WUFDRSxPQUFPLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNsQztRQUNELE9BQU0sQ0FBQyxFQUNQO1lBRUUsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUNsQztRQUFBLENBQUM7UUFFRixJQUFJLEVBQUUsR0FBTyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3hCLElBQUksR0FBRyxHQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7UUFDekIsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztRQUM1QixJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUVsQyxJQUFJLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQ3ZCLElBQUksSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFHdkIsSUFBRyxJQUFJLENBQUMsTUFBTSxJQUFJLFNBQVMsSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBRzNELElBQUcsRUFBRSxJQUFJLFNBQVMsSUFBSSxHQUFHLElBQUksU0FBUyxFQUN0QztZQUNFLElBQUksWUFBWSxHQUFHLElBQUksZUFBZSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUV2RCxJQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQztnQkFBRSxPQUFPO1lBQzlDLE9BQU8sWUFBWSxDQUFDO1NBQ3JCO1FBQUEsQ0FBQztRQUdGO1lBR0UsU0FBUyxHQUFHLGNBQWMsQ0FBQyxTQUFTLENBQUMsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDN0QsSUFBRyxTQUFTLEVBQ1o7Z0JBQ0UsSUFBSSxRQUFRLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ3ZDLElBQUcsUUFBUTtvQkFDVCxPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2FBQzNDO1lBQUEsQ0FBQztZQUVGLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUN6QyxJQUFJLE9BQU8sR0FBRyxJQUFJLFVBQVUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFFckUsSUFBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUM7Z0JBQUUsT0FBTztZQUN6QyxPQUFPLE9BQU8sQ0FBQztRQUNqQixDQUFDO1FBQUEsQ0FBQztRQUVGLHlCQUF5QixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU07WUFFN0MsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDbEMsQ0FBQztRQUFBLENBQUM7UUFFRiw0QkFBNEIsT0FBTztZQUVqQyxPQUFPLENBQUMsSUFBSSxDQUFDLDRCQUE0QixFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBR3BELFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN0QixzQkFBc0IsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDcEMsQ0FBQztRQUFBLENBQUM7UUFJRixJQUFHLE1BQU0sRUFDVDtZQUVFLElBQUcsSUFBSSxJQUFJLFNBQVMsSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU0sRUFDM0M7Z0JBQ0UsSUFBSSxPQUFPLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ3RDLElBQUcsT0FBTyxFQUNWO29CQUNFLElBQUksZUFBZSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUM7b0JBRTlDLElBQUcsTUFBTSxJQUFJLGVBQWUsQ0FBQyxLQUFLO3dCQUNoQyxPQUFPLGVBQWUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7b0JBRTFDLElBQUcsTUFBTSxJQUFJLGVBQWUsQ0FBQyxRQUFRO3dCQUNuQyxPQUFPLGVBQWUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO29CQUVoRCxPQUFPLGNBQWMsRUFBRSxDQUFDO2lCQUN6QjtnQkFFRCxJQUFJLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUNsRCxJQUFHLFNBQVM7b0JBQ1YsT0FBTyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQzthQUN4QztZQUdELE9BQU8sY0FBYyxFQUFFLENBQUM7U0FDekI7UUFBQSxDQUFDO1FBRUYsSUFBSSxLQUFLLEdBQUksT0FBTyxDQUFDLEtBQUssQ0FBQztRQUMzQixJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBRzVCLElBQUcsS0FBSyxJQUFLLEtBQUssQ0FBQyxJQUFJLElBQUssS0FBSyxDQUFDLElBQUksSUFBSyxJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU87UUFDL0QsSUFBRyxNQUFNLElBQUksTUFBTSxDQUFDLElBQUksSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTztRQUcvRCxJQUFJLE9BQU8sR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN0QyxJQUFHLENBQUMsT0FBTyxFQUNYO1lBQ0UsSUFBSSxTQUFTLEdBQUcsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNsRCxJQUFHLFNBQVM7Z0JBQ1YsT0FBTyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUV2QyxPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsMENBQTBDLEVBQUUsT0FBTyxDQUFDLENBQUM7U0FDMUU7UUFBQSxDQUFDO1FBR0YsZUFBZSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDMUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUFBLENBQUM7QUFDRixRQUFRLENBQUMsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDO0FBR25DLFVBQVUsQ0FBQyxlQUFlLEdBQUcsZUFBZSxDQUFDO0FBRzdDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDO0FBRTVCLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNuQyxJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUMsc0JBQXNCLENBQUMsQ0FBQztBQUVqRCxVQUFVLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztBQUM3QixVQUFVLENBQUMsT0FBTyxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7QUFDM0MsVUFBVSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7OztBQ3p5QjdCLGNBQWMsT0FBTyxFQUFFLEVBQUU7SUFFdkIsSUFBSSxNQUFNLEdBQ1Y7UUFDRSxPQUFPLEVBQUUsS0FBSztLQUNmLENBQUM7SUFHRixJQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQ2pCO1FBQ0UsTUFBTSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBRS9CLElBQUcsT0FBTyxDQUFDLE1BQU07WUFDZixNQUFNLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFHakMsSUFBRyxFQUFFLElBQUksU0FBUztZQUNoQixNQUFNLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztLQUNsQjtTQUdJLElBQUcsRUFBRSxJQUFJLFNBQVMsRUFDdkI7UUFDRSxJQUFHLE9BQU8sQ0FBQyxLQUFLLEVBQ2hCO1lBQ0UsSUFBRyxPQUFPLENBQUMsTUFBTSxLQUFLLFNBQVM7Z0JBQzdCLE1BQU0sSUFBSSxTQUFTLENBQUMsbUNBQW1DLENBQUMsQ0FBQztZQUUzRCxNQUFNLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7U0FDOUI7YUFDSSxJQUFHLE9BQU8sQ0FBQyxNQUFNLEtBQUssU0FBUztZQUNsQyxNQUFNLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7O1lBRS9CLE1BQU0sSUFBSSxTQUFTLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUV2RCxNQUFNLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztLQUNoQjtJQUFBLENBQUM7SUFFRixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDaEMsQ0FBQztBQUFBLENBQUM7QUFXRixnQkFBZ0IsT0FBTztJQUVyQixJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUM7SUFFckIsSUFBRyxPQUFPLE9BQU8sS0FBSyxRQUFRLElBQUksT0FBTyxZQUFZLE1BQU0sRUFBRTtRQUMzRCxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztLQUM5QjtJQUlELElBQUksT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUM7SUFDN0IsSUFBRyxPQUFPLEtBQUssS0FBSztRQUNsQixNQUFNLElBQUksU0FBUyxDQUFDLDJCQUEyQixHQUFHLE9BQU8sR0FBRyxLQUFLLEdBQUcsT0FBTyxDQUFDLENBQUM7SUFHL0UsSUFBRyxNQUFNLENBQUMsTUFBTSxJQUFJLFNBQVMsRUFDN0I7UUFDRSxJQUFHLE1BQU0sQ0FBQyxFQUFFLElBQUksU0FBUztZQUN2QixNQUFNLElBQUksU0FBUyxDQUFDLG1CQUFtQixHQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRW5ELElBQUksY0FBYyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDO1FBQ2pELElBQUksYUFBYSxHQUFJLE1BQU0sQ0FBQyxLQUFLLEtBQU0sU0FBUyxDQUFDO1FBR2pELElBQUcsY0FBYyxJQUFJLGFBQWE7WUFDaEMsTUFBTSxJQUFJLFNBQVMsQ0FBQyxxQ0FBcUMsR0FBQyxPQUFPLENBQUMsQ0FBQztRQUVyRSxJQUFHLENBQUMsY0FBYyxJQUFJLENBQUMsYUFBYTtZQUNsQyxNQUFNLElBQUksU0FBUyxDQUFDLGlDQUFpQyxHQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRWpFLE1BQU0sQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUN2QixPQUFPLE1BQU0sQ0FBQyxFQUFFLENBQUM7S0FDbEI7SUFHRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBQUEsQ0FBQztBQUdGLE9BQU8sQ0FBQyxJQUFJLEdBQUssSUFBSSxDQUFDO0FBQ3RCLE9BQU8sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDOzs7QUN0R3hCLGNBQWMsT0FBTztJQUVuQixNQUFNLElBQUksU0FBUyxDQUFDLHFCQUFxQixDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUFBLENBQUM7QUFFRixnQkFBZ0IsT0FBTztJQUVyQixNQUFNLElBQUksU0FBUyxDQUFDLHFCQUFxQixDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUFBLENBQUM7QUFHRixPQUFPLENBQUMsSUFBSSxHQUFLLElBQUksQ0FBQztBQUN0QixPQUFPLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQzs7O0FDWnhCLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNuQyxJQUFJLE1BQU0sR0FBSSxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7QUFHbEMsT0FBTyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7QUFDMUIsT0FBTyxDQUFDLE1BQU0sR0FBSSxNQUFNLENBQUM7OztBQ1d6QixJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUE7QUFDaEMsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFBO0FBQ2xDLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQTtBQUN0QyxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7QUFDMUIsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBRTFCLElBQUksWUFBWSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxZQUFZLENBQUE7QUFDakQsSUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFBO0FBQ2hFLElBQUksYUFBYSxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFBO0FBQzdDLElBQUksTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFBO0FBcUJyQyxJQUFJLGlCQUFpQixHQUFHO0lBQ3RCLEtBQUssRUFBRSxJQUFJO0lBQ1gsS0FBSyxFQUFFO1FBQ0wsS0FBSyxFQUFFLEdBQUc7UUFDVixTQUFTLEVBQUUsRUFBRTtLQUNkO0NBQ0YsQ0FBQTtBQUlELElBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtBQUN2RSxJQUFJLE1BQU0sR0FBRyxJQUFJLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUM3QixJQUFJLE9BQU8sR0FBRyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUE7QUFFakMsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFBO0FBQ3BCLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxVQUFVLEVBQUU7SUFDNUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLG1CQUFtQixDQUFDLENBQUE7SUFDaEQsUUFBUSxHQUFHLElBQUksQ0FBQTtDQUNoQjtBQUVELGNBQWMsS0FBSztJQUNqQixJQUFJLEtBQUs7UUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBQ2hDLENBQUM7QUFFRCxtQkFBbUIsS0FBSztJQUN0QixLQUFLLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQTtBQUM1QixDQUFDO0FBRUQsb0JBQW9CLE1BQU07SUFDeEIsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQUN2QyxDQUFDO0FBS0QsSUFBSSxPQUFPLEdBQUcsVUFBVSxXQUFXO0lBQ2pDLElBQUksT0FBTyxXQUFXLEtBQUssV0FBVyxJQUFJLFdBQVcsS0FBSyxJQUFJLEVBQUU7UUFDOUQsT0FBTyxFQUFFLENBQUE7S0FDVjtJQUVELE9BQU8sUUFBUSxHQUFHLFdBQVcsQ0FBQyxJQUFJLEdBQUcsTUFBTSxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUE7QUFDL0QsQ0FBQyxDQUFBO0FBRUQsNkJBQTZCLEVBQUUsRUFBRSxPQUFPO0lBQ3RDLElBQUksZUFBZSxHQUFHLEVBQUUsQ0FBQTtJQUV4QixFQUFFLENBQUMsZ0JBQWdCLENBQUMsc0JBQXNCLEVBQUU7UUFDMUMsSUFBSSxJQUFJLENBQUMsY0FBYyxLQUFLLFFBQVEsRUFBRTtZQUNwQyxPQUFPLGVBQWUsQ0FBQyxNQUFNLEVBQUU7Z0JBQzdCLElBQUksS0FBSyxHQUFHLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtnQkFDbkMsRUFBRSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFBO2FBQ3BFO1NBQ0Y7SUFDSCxDQUFDLENBQUMsQ0FBQTtJQUVGLE9BQU8sVUFBVSxTQUFTLEVBQUUsUUFBUTtRQUNsQyxRQUFRLEdBQUcsUUFBUSxJQUFJLE9BQU8sQ0FBQTtRQUU5QixRQUFRLEVBQUUsQ0FBQyxjQUFjLEVBQUU7WUFDM0IsS0FBSyxRQUFRO2dCQUNYLFFBQVEsQ0FBQyxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZELE1BQU07WUFDUixLQUFLLFFBQVE7Z0JBQ1gsSUFBSSxFQUFFLENBQUMsaUJBQWlCLEVBQUU7b0JBQ3hCLEVBQUUsQ0FBQyxlQUFlLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztpQkFDbkQ7Z0JBQ0QsTUFBTTtZQUNSO2dCQUNFLGVBQWUsQ0FBQyxJQUFJLENBQUM7b0JBQ25CLFNBQVMsRUFBRSxTQUFTO29CQUNwQixRQUFRLEVBQUUsUUFBUTtpQkFDbkIsQ0FBQyxDQUFBO1NBQ0g7SUFDSCxDQUFDLENBQUE7QUFDSCxDQUFDO0FBSUQsNEJBQTRCLEdBQUc7SUFDN0IsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBRXhDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRTtRQUNULE9BQU8sR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7S0FDeEI7U0FBTTtRQUNMLE9BQU8sR0FBRyxDQUFDO0tBQ1o7QUFDSCxDQUFDO0FBRUQsMEJBQTBCLFdBQVc7SUFDbkMsSUFBSSxXQUFXLEdBQUcsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQy9DLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFO1FBQ3ZCLE1BQU0sQ0FBQyxJQUFJLENBQUMsK0NBQStDLENBQUMsQ0FBQTtRQUM1RCxPQUFPLEVBQUUsQ0FBQTtLQUNWO0lBQ0QsSUFBSSxLQUFLLEdBQUc7UUFDViw0QkFBNEI7UUFDNUIsd0JBQXdCO1FBQ3hCLDJCQUEyQjtRQUMzQixnQkFBZ0IsR0FBRyxXQUFXLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUMzRCxtQkFBbUIsR0FBRyxXQUFXLENBQUMsRUFBRTtRQUNwQyxpQkFBaUIsR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUNyQywyQkFBMkI7UUFDM0IsZ0JBQWdCLEdBQUcsV0FBVyxDQUFDLEVBQUUsR0FBRyxHQUFHLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDM0QsbUJBQW1CLEdBQUcsV0FBVyxDQUFDLEVBQUU7UUFDcEMsaUJBQWlCLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDckMsMkJBQTJCO1FBQzNCLGdCQUFnQixHQUFHLFdBQVcsQ0FBQyxFQUFFLEdBQUcsR0FBRyxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQzNELG1CQUFtQixHQUFHLFdBQVcsQ0FBQyxFQUFFO1FBQ3BDLGlCQUFpQixHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO0tBQ3RDLENBQUM7SUFFRixLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBRWYsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzFCLENBQUM7QUFtQkQsb0JBQW9CLElBQUksRUFBRSxPQUFPLEVBQUUsUUFBUTtJQUN6QyxJQUFJLENBQUMsQ0FBQyxJQUFJLFlBQVksVUFBVSxDQUFDLEVBQUU7UUFDakMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFBO0tBQy9DO0lBRUQsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7SUFFNUIsSUFBSSxPQUFPLFlBQVksUUFBUSxFQUFFO1FBQy9CLFFBQVEsR0FBRyxPQUFPLENBQUE7UUFDbEIsT0FBTyxHQUFHLFNBQVMsQ0FBQTtLQUNwQjtJQUVELE9BQU8sR0FBRyxPQUFPLElBQUksRUFBRSxDQUFBO0lBQ3ZCLFFBQVEsR0FBRyxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7SUFFeEMsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFBO0lBQ2YsSUFBSSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQTtJQUNuQyxJQUFJLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFBO0lBQ3JDLElBQUksV0FBVyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUE7SUFDckMsSUFBSSxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQTtJQUNyQyxJQUFJLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQTtJQUUvQyxJQUFJLHFCQUFxQixHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQTtJQUN6RCxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFBO0lBQy9CLElBQUksVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLElBQUksUUFBUSxDQUFBO0lBTS9DLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQTtJQUNwQixJQUFJLGFBQWEsR0FBRyxTQUFTLENBQUM7UUFDMUIsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFVLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRTtLQUNyRyxFQUNELE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQTtJQUV4QixJQUFJLGNBQWMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFBO0lBQzNDLElBQUksY0FBYztRQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsY0FBYyxFQUFFLGNBQWMsQ0FBQyxDQUFBO0lBRTNELElBQUksd0JBQXdCLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixDQUFBO0lBQy9ELElBQUksd0JBQXdCLEVBQUU7UUFDNUIsSUFBSSxDQUFDLEVBQUUsQ0FBQyx3QkFBd0IsRUFBRSx3QkFBd0IsQ0FBQyxDQUFBO0tBQzVEO0lBRUQsSUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQTtJQUNqQyxJQUFJLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFBO0lBQ3JDLElBQUksT0FBTyxHQUFHLElBQUksYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBQ3pDLElBQUksa0JBQWtCLEdBQUcsRUFBRSxDQUFBO0lBQzNCLElBQUksc0JBQXNCLEdBQUcsS0FBSyxDQUFBO0lBRWxDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUU7UUFDNUIsZ0JBQWdCLEVBQUU7WUFDaEIsR0FBRyxFQUFFO2dCQUNILE9BQU8sRUFBRSxDQUFBO1lBQ1gsQ0FBQztTQUNGO1FBRUQsSUFBSSxFQUFFO1lBQ0osS0FBSyxFQUFFLE9BQU8sQ0FBQyxFQUFFLElBQUksSUFBSTtZQUN6QixRQUFRLEVBQUUsS0FBSztTQUNoQjtRQUVELGFBQWEsRUFBRTtZQUNiLEdBQUcsRUFBRTtnQkFDSCxPQUFPLFdBQVcsQ0FBQTtZQUNwQixDQUFDO1NBQ0Y7UUFFRCxZQUFZLEVBQUU7WUFDWixHQUFHLEVBQUU7Z0JBQ0gsT0FBTyxVQUFVLENBQUE7WUFDbkIsQ0FBQztTQUNGO1FBV0QsY0FBYyxFQUFFO1lBQ2QsR0FBRyxFQUFFO2dCQUdILElBQUksQ0FBQyxXQUFXO29CQUFFLE9BQU87Z0JBRXpCLElBQUksV0FBVyxDQUFDLFVBQVUsR0FBRyxXQUFXLENBQUMsaUJBQWlCO29CQUN4RCxNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUE7Z0JBRW5ELElBQUksTUFBTSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUE7Z0JBQzdDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsV0FBVyxDQUFDLFVBQVUsQ0FBQTtnQkFDckMsTUFBTSxDQUFDLE1BQU0sR0FBRyxXQUFXLENBQUMsV0FBVyxDQUFBO2dCQUV2QyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO2dCQUVwRCxPQUFPLE1BQU0sQ0FBQTtZQUNmLENBQUM7U0FDRjtLQUNGLENBQUMsQ0FBQTtJQUdGLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDUCxFQUFFLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsQ0FBQztLQWlCM0M7SUFFRCxFQUFFLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxFQUFFLFVBQVUsS0FBSztRQUNqRCxJQUFJLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFBO1FBRS9CLElBQUksWUFBWSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDO1lBQ2xELFlBQVksQ0FBQyxhQUFhLENBQ3hCLElBQUksRUFBRSx3QkFBd0IsQ0FBQyxFQUFFO1lBQ25DLElBQUksU0FBUyxFQUFFO2dCQUNiLElBQUksSUFBSSxDQUFBO2dCQUVSLElBQUksV0FBVyxJQUFJLFFBQVEsRUFBRTtvQkFDM0IsSUFBSSxHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsQ0FBQTtpQkFDakQ7cUJBQU07b0JBQ0wsSUFBSSxHQUFHLFNBQVMsQ0FBQTtpQkFDakI7Z0JBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUE7Z0JBQy9CLHNCQUFzQixHQUFHLEtBQUssQ0FBQTthQUMvQjtpQkFBTSxJQUFJLENBQUMsc0JBQXNCLEVBQUU7Z0JBQ2xDLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQTtnQkFDbkMsc0JBQXNCLEdBQUcsSUFBSSxDQUFBO2FBQzlCO1NBQ0Y7YUFBTSxJQUFJLENBQUMsc0JBQXNCLEVBQUU7WUFHbEMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFBO1lBRWxDLElBQUksQ0FBQyxTQUFTO2dCQUFFLHNCQUFzQixHQUFHLElBQUksQ0FBQTtTQUM5QztJQUNILENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFBO0lBQ3BDLEVBQUUsQ0FBQyxtQkFBbUIsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUE7SUFDcEQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUUsVUFBVSxLQUFLLEVBQUUsUUFBUTtRQUM5QyxJQUFJLEtBQUssS0FBSyxjQUFjLElBQUksS0FBSyxLQUFLLHdCQUF3QixFQUFFO1lBQ2xFLE9BQU8sa0JBQWtCLENBQUMsTUFBTSxFQUFFO2dCQUNoQyxJQUFJLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtnQkFFMUMsSUFBSSxDQUFDLFNBQVMsS0FBSyxDQUFDLEtBQUssS0FBSyx3QkFBd0IsQ0FBQyxFQUFFO29CQUN2RCxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUE7aUJBQ3BCO2FBQ0Y7U0FDRjtJQUNILENBQUMsQ0FBQyxDQUFBO0lBRUYsSUFBSSxlQUFlLEdBQUcsbUJBQW1CLENBQUMsRUFBRSxDQUFDLENBQUE7SUFXN0MsSUFBSSxDQUFDLGVBQWUsR0FBRyxVQUFVLFlBQVksRUFBRSxRQUFRO1FBQ3JELElBQUksU0FBUyxDQUFBO1FBRWIsSUFBSSxXQUFXLElBQUksUUFBUSxFQUFFO1lBQzNCLFNBQVMsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLENBQUE7U0FDbkQ7YUFBTTtZQUNMLFNBQVMsR0FBRyxJQUFJLGVBQWUsQ0FBQyxZQUFZLENBQUMsQ0FBQTtTQUM5QztRQUVELE1BQU0sQ0FBQyxLQUFLLENBQUMsK0JBQStCLEVBQUUsWUFBWSxDQUFDLENBQUE7UUFDM0QsUUFBUSxHQUFHLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUN4QyxlQUFlLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFBO0lBQ3RDLENBQUMsQ0FBQTtJQUVELElBQUksQ0FBQyxhQUFhLEdBQUcsVUFBVSxRQUFRO1FBQ3JDLFFBQVEsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRTlCLElBQUksVUFBVSxHQUFHLElBQUksQ0FBQTtRQUNyQixJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUE7UUFFckIsSUFBSSxnQkFBZ0IsRUFBRTtZQUNwQixVQUFVLEdBQUcsQ0FBQyxPQUFPLGdCQUFnQixDQUFDLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDO2dCQUMxRCxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtZQUMvQixVQUFVLEdBQUcsQ0FBQyxPQUFPLGdCQUFnQixDQUFDLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDO2dCQUMxRCxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtTQUNoQztRQUVELElBQUksMkJBQTJCLEdBQUc7WUFDaEMsbUJBQW1CLEVBQUUsQ0FBQyxJQUFJLEtBQUssVUFBVSxJQUFJLFVBQVUsQ0FBQztZQUN4RCxtQkFBbUIsRUFBRSxDQUFDLElBQUksS0FBSyxVQUFVLElBQUksVUFBVSxDQUFDO1NBQ3pELENBQUE7UUFNRCxJQUFJLFdBQVcsR0FBRywyQkFBMkIsQ0FBQztRQUU5QyxNQUFNLENBQUMsS0FBSyxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUE7UUFFM0QsRUFBRSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxLQUFLO1lBQzlDLE1BQU0sQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsQ0FBQTtZQUNqQyxLQUFLLEdBQUcsdUJBQXVCLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDdEMsT0FBTyxFQUFFLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDdEMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ04sSUFBSSxnQkFBZ0IsR0FBRyxFQUFFLENBQUMsZ0JBQWdCLENBQUE7WUFDMUMsTUFBTSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsRUFBRSxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUMzRCxJQUFJLFdBQVcsSUFBSSxRQUFRLEVBQUU7Z0JBQzNCLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLENBQUMsQ0FBQTtnQkFDMUQsTUFBTSxDQUFDLEtBQUssQ0FBQywrQkFBK0IsRUFBRSxPQUFPLENBQ25ELGdCQUFnQixDQUFDLENBQUMsQ0FBQTthQUNyQjtZQUNELFFBQVEsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUMxRCxJQUFJLENBQUMsQ0FBQyxDQUFBO1FBQ1YsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQ3BCLENBQUMsQ0FBQTtJQUVELElBQUksQ0FBQyx5QkFBeUIsR0FBRztRQUMvQixPQUFPLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQTtJQUM1QixDQUFDLENBQUE7SUFFRCxJQUFJLENBQUMsMEJBQTBCLEdBQUc7UUFDaEMsT0FBTyxFQUFFLENBQUMsaUJBQWlCLENBQUE7SUFDN0IsQ0FBQyxDQUFBO0lBRUQ7UUFDRSxJQUFJLFdBQVcsRUFBRTtZQUNmLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtZQUVuQixJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtZQUNyQyxXQUFXLENBQUMsU0FBUyxHQUFHLE1BQU0sQ0FBQTtZQUM5QixNQUFNLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxDQUFBO1lBRXRDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtTQUNuQjtJQUNILENBQUM7SUFFRCxJQUFJLENBQUMsY0FBYyxHQUFHO1FBQ3BCLFVBQVUsQ0FBQyxTQUFTLEdBQUcsV0FBVyxDQUFBO1FBQ2xDLFVBQVUsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFBO0lBQ3pCLENBQUMsQ0FBQTtJQXFCRCxJQUFJLENBQUMsYUFBYSxHQUFHLFVBQVUsU0FBUyxFQUFFLFFBQVE7UUFDaEQsUUFBUSxHQUFHLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUV4QyxJQUFJLE1BQU0sR0FBRyxJQUFJLHFCQUFxQixDQUFDO1lBQ3JDLElBQUksRUFBRSxRQUFRO1lBQ2QsR0FBRyxFQUFFLFNBQVM7U0FDZixDQUFDLENBQUE7UUFFRixJQUFJLFdBQVcsSUFBSSxRQUFRLEVBQUU7WUFDM0IsSUFBSSxXQUFXLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUN6QyxNQUFNLENBQUMsS0FBSyxDQUFDLGVBQWUsRUFBRSxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQTtZQUNuRCxNQUFNLEdBQUcsV0FBVyxDQUFBO1NBQ3JCO1FBRUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxpREFBaUQsQ0FBQyxDQUFBO1FBRS9ELElBQUksRUFBRSxDQUFDLGNBQWMsS0FBSyxRQUFRLEVBQUU7WUFDbEMsT0FBTyxRQUFRLENBQUMsMEJBQTBCLENBQUMsQ0FBQTtTQUM1QztRQUVELEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLEVBQUU7WUFDNUIsY0FBYyxFQUFFLENBQUE7WUFFaEIsUUFBUSxFQUFFLENBQUE7UUFDWixDQUFDLEVBQ0QsUUFBUSxDQUFDLENBQUE7SUFDYixDQUFDLENBQUE7SUFZRCxJQUFJLENBQUMsWUFBWSxHQUFHLFVBQVUsUUFBUSxFQUFFLFFBQVE7UUFDOUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7UUFFOUIsSUFBSSxLQUFLLEdBQUcsSUFBSSxxQkFBcUIsQ0FBQztZQUNwQyxJQUFJLEVBQUUsT0FBTztZQUNiLEdBQUcsRUFBRSxRQUFRO1NBQ2QsQ0FBQyxDQUFBO1FBRUYsSUFBSSxXQUFXLElBQUksUUFBUSxFQUFFO1lBQzNCLElBQUksVUFBVSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDdkMsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUE7WUFDakQsS0FBSyxHQUFHLFVBQVUsQ0FBQTtTQUNuQjtRQUVELE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQTtRQUU5RCxJQUFJLEVBQUUsQ0FBQyxjQUFjLEtBQUssUUFBUSxFQUFFO1lBQ2xDLE9BQU8sUUFBUSxDQUFDLDBCQUEwQixDQUFDLENBQUE7U0FDNUM7UUFFRCxFQUFFLENBQUMsb0JBQW9CLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ2xDLE9BQU8sY0FBYyxFQUFFLENBQUE7UUFDekIsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ04sT0FBTyxFQUFFLENBQUMsWUFBWSxFQUFFLENBQUE7UUFDMUIsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsTUFBTTtZQUN0QixNQUFNLEdBQUcsdUJBQXVCLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDeEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFBO1lBQ2xDLE9BQU8sRUFBRSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ3ZDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUNOLElBQUksZ0JBQWdCLEdBQUcsRUFBRSxDQUFDLGdCQUFnQixDQUFBO1lBQzFDLElBQUksV0FBVyxJQUFJLFFBQVEsRUFBRTtnQkFDM0IsZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFBO2dCQUMxRCxNQUFNLENBQUMsS0FBSyxDQUFDLGdDQUFnQyxFQUFFLE9BQU8sQ0FDcEQsZ0JBQWdCLENBQUMsQ0FBQyxDQUFBO2FBQ3JCO1lBQ0QsTUFBTSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsRUFBRSxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUMzRCxRQUFRLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQ3RDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUNwQixDQUFDLENBQUE7SUFFRCxpQ0FBaUMsTUFBTTtRQUNyQyxJQUFJLFNBQVMsRUFBRTtZQUNiLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxVQUFVLEVBQUU7Z0JBQzVELE1BQU0sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQTtnQkFDckMsTUFBTSxHQUFHLElBQUkscUJBQXFCLENBQUM7b0JBQ2pDLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSTtvQkFDbkIsS0FBSyxFQUFFLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxnQkFBZ0IsQ0FDdEQsV0FBVyxDQUFDO2lCQUNmLENBQUMsQ0FBQTthQUNIO2lCQUFNO2dCQUNMLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0RBQWdELENBQUMsQ0FBQTthQUM5RDtTQUNGO1FBRUQsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0lBU0Q7UUFDRSxJQUFJLEVBQUUsQ0FBQyxjQUFjLEtBQUssUUFBUSxFQUFFO1lBQ2xDLFFBQVEsQ0FDTixrSkFBa0osQ0FDbkosQ0FBQTtTQUNGO1FBRUQsSUFBSSxXQUFXLElBQUksVUFBVSxFQUFFO1lBQzdCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQTtTQUN0QjtRQUVELElBQUksV0FBVyxFQUFFO1lBQ2YsRUFBRSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQTtTQUMxQjtRQUVELElBQUksV0FBVyxFQUFFO1lBQ2YsRUFBRSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQTtTQUMxQjtRQUdELElBQUksT0FBTyxHQUFHLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQTtRQUNqQyxJQUFJLElBQUksS0FBSyxVQUFVO1lBQ3JCLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxVQUFVLENBQUM7WUFDMUQsT0FBTyxDQUFDLEtBQUssS0FBSyxFQUFFLEVBQUU7WUFDdEIsSUFBSSxHQUFHLFVBQVUsQ0FBQTtTQUNsQjtRQUVELFFBQVEsRUFBRSxDQUFBO0lBQ1osQ0FBQztJQUVELElBQUksSUFBSSxLQUFLLFVBQVUsSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLFdBQVcsRUFBRTtRQUN2RCxrQkFBa0IsV0FBVztZQUMzQixJQUFJLFdBQVcsS0FBSyxTQUFTLEVBQUU7Z0JBQzdCLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQTthQUNoQztZQUVELFNBQVMsQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLE1BQU07Z0JBQ3BFLFdBQVcsR0FBRyxNQUFNLENBQUE7Z0JBQ3BCLEtBQUssRUFBRSxDQUFBO1lBQ1QsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JCLENBQUM7UUFDRCxJQUFJLFVBQVUsS0FBSyxRQUFRLEVBQUU7WUFDM0IsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUE7U0FDM0I7YUFBTTtZQUNMLG9CQUFvQixDQUFDLFVBQVUsRUFBRSxVQUFVLEtBQUssRUFBRSxZQUFZO2dCQUM1RCxJQUFJLEtBQUs7b0JBQ1AsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUE7Z0JBRXhCLFdBQVcsR0FBRyxDQUFDLGdCQUFnQixDQUFDLENBQUE7Z0JBQ2hDLFdBQVcsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUE7Z0JBQ2pDLFFBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFBO1lBQ25ELENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQTtTQUNUO0tBQ0Y7U0FBTTtRQUNMLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUE7S0FDckI7SUFFRCxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRTtRQUNsQixJQUFJLFVBQVUsRUFBRTtZQUNkLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtZQUNsQixVQUFVLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQTtZQUMzQixVQUFVLENBQUMsSUFBSSxFQUFFLENBQUE7WUFFakIsVUFBVSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUE7U0FDekI7UUFDRCxJQUFJLFdBQVcsRUFBRTtZQUNmLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtZQUNuQixXQUFXLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQTtZQUM1QixXQUFXLENBQUMsSUFBSSxFQUFFLENBQUE7U0FDbkI7UUFDRCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQTtRQUV6QixJQUFJLE1BQU0sQ0FBQyx3QkFBd0IsS0FBSyxTQUFTLEVBQUU7WUFDakQsTUFBTSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxDQUFBO1NBQ3RDO0lBQ0gsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDO0FBQ0QsUUFBUSxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQTtBQUVsQyxnQ0FBZ0MsSUFBSTtJQUNsQyxJQUFJLE1BQU0sR0FBRyxLQUFLLEdBQUcsSUFBSSxHQUFHLFFBQVEsQ0FBQTtJQUVwQyxPQUFPO1FBQ0wsVUFBVSxFQUFFLElBQUk7UUFDaEIsR0FBRyxFQUFFO1lBR0gsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjO2dCQUFFLE9BQU07WUFFaEMsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlLEVBQUUsQ0FBQTtZQUNuRCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU07Z0JBQUUsT0FBTTtZQUUzQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDaEQsSUFBSSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUE7Z0JBQzdCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtvQkFDM0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPO3dCQUFFLE9BQU8sS0FBSyxDQUFBO2FBQ25DO1lBRUQsT0FBTyxJQUFJLENBQUE7UUFDYixDQUFDO1FBQ0QsR0FBRyxFQUFFLFVBQVUsS0FBSztZQUNsQix3QkFBd0IsS0FBSztnQkFDM0IsS0FBSyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUE7WUFDdkIsQ0FBQztZQUVELElBQUksQ0FBQyxjQUFjLENBQUMsZUFBZSxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsTUFBTTtnQkFDNUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFBO1lBQzFDLENBQUMsQ0FBQyxDQUFBO1FBQ0osQ0FBQztLQUNGLENBQUE7QUFDSCxDQUFDO0FBRUQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUU7SUFDNUMsU0FBUyxFQUFFO1FBQ1QsVUFBVSxFQUFFLElBQUk7UUFDaEIsR0FBRyxFQUFFO1lBQ0gsT0FBTyxJQUFJLENBQUMsWUFBWSxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUE7UUFDL0MsQ0FBQztRQUNELEdBQUcsRUFBRSxVQUFVLEtBQUs7WUFDbEIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQTtRQUMvQyxDQUFDO0tBQ0Y7SUFDRCxjQUFjLEVBQUUsc0JBQXNCLENBQUMsT0FBTyxDQUFDO0lBQy9DLGNBQWMsRUFBRSxzQkFBc0IsQ0FBQyxPQUFPLENBQUM7Q0FDaEQsQ0FBQyxDQUFBO0FBRUYsVUFBVSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEdBQUcsVUFBVSxLQUFLO0lBQ25ELElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtRQUN2QixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsZUFBZSxFQUFFLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFBO0tBQ3pEO0FBQ0gsQ0FBQyxDQUFBO0FBRUQsVUFBVSxDQUFDLFNBQVMsQ0FBQyxlQUFlLEdBQUcsVUFBVSxLQUFLO0lBQ3BELElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtRQUN2QixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUE7S0FDMUQ7QUFDSCxDQUFDLENBQUE7QUFPRCxVQUFVLENBQUMsU0FBUyxDQUFDLE9BQU8sR0FBRztJQUM3QixNQUFNLENBQUMsS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUE7SUFFcEMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQTtJQUU1QixJQUFJO1FBT0YsSUFBSSxFQUFFLEVBQUU7WUFDTixJQUFJLEVBQUUsQ0FBQyxjQUFjLEtBQUssUUFBUTtnQkFBRSxPQUFNO1lBRTFDLEVBQUUsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUE7WUFNeEMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFBO1NBQ1g7S0FDRjtJQUFDLE9BQU8sR0FBRyxFQUFFO1FBQ1osTUFBTSxDQUFDLElBQUksQ0FBQyxrQ0FBa0MsR0FBRyxHQUFHLENBQUMsQ0FBQTtLQUN0RDtJQUVELElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUE7QUFDdkIsQ0FBQyxDQUFBO0FBTUQsNEJBQTRCLE9BQU8sRUFBRSxRQUFRO0lBQzNDLElBQUksQ0FBQyxDQUFDLElBQUksWUFBWSxrQkFBa0IsQ0FBQyxFQUFFO1FBQ3pDLE9BQU8sSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7S0FDakQ7SUFFRCxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFBO0FBQ3JFLENBQUM7QUFDRCxRQUFRLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDLENBQUE7QUFFeEMsNEJBQTRCLE9BQU8sRUFBRSxRQUFRO0lBQzNDLElBQUksQ0FBQyxDQUFDLElBQUksWUFBWSxrQkFBa0IsQ0FBQyxFQUFFO1FBQ3pDLE9BQU8sSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7S0FDakQ7SUFFRCxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFBO0FBQ3JFLENBQUM7QUFDRCxRQUFRLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDLENBQUE7QUFFeEMsNEJBQTRCLE9BQU8sRUFBRSxRQUFRO0lBQzNDLElBQUksQ0FBQyxDQUFDLElBQUksWUFBWSxrQkFBa0IsQ0FBQyxFQUFFO1FBQ3pDLE9BQU8sSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7S0FDakQ7SUFFRCxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFBO0FBQ3JFLENBQUM7QUFDRCxRQUFRLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDLENBQUE7QUFFeEMsbUJBQW1CLE1BQU0sRUFBRSxPQUFPO0lBQ2hDLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztBQUMvQixDQUFDO0FBRUQsT0FBTyxDQUFDLG1CQUFtQixHQUFHLG1CQUFtQixDQUFBO0FBRWpELE9BQU8sQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQTtBQUMvQyxPQUFPLENBQUMsa0JBQWtCLEdBQUcsa0JBQWtCLENBQUE7QUFDL0MsT0FBTyxDQUFDLGtCQUFrQixHQUFHLGtCQUFrQixDQUFBO0FBQy9DLE9BQU8sQ0FBQyxJQUFJLEdBQUcsU0FBUyxDQUFBOzs7QUMzdUJ4QixJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7QUFFekMsT0FBTyxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7OztBQ05oQyxNQUFNLENBQUMsV0FBVyxHQUFHLFVBQVUsUUFBUTtJQUluQyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFO1FBQzdCLFFBQVEsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFO1lBQ3RCLEtBQUssRUFBRTtnQkFDSCxjQUFjLEVBQUUsUUFBUTtnQkFDeEIsV0FBVyxFQUFFLFFBQVE7YUFDeEI7U0FDSixDQUFDLENBQUM7UUFDSCxPQUFPO0tBQ1Y7SUFFRCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFFckQsMEJBQTBCLEtBQUs7UUFDM0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJO1lBQUUsT0FBTztRQUV4QixJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUU7WUFDaEMsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLG1CQUFtQixLQUFLLHVCQUF1QixFQUFFO2dCQUM1RCxRQUFRLENBQUMsbUJBQW1CLENBQUMsQ0FBQzthQUNqQztpQkFBTTtnQkFDSCxRQUFRLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsb0JBQW9CLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO2FBQzlHO1lBR0QsTUFBTSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1NBQzNEO1FBRUQsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFO1lBQ2xDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLElBQUksRUFBRSxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztZQUd6RyxNQUFNLENBQUMsbUJBQW1CLENBQUMsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7U0FDM0Q7SUFDTCxDQUFDO0lBRUQsVUFBVSxDQUFDLHNCQUFzQixFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzVDLENBQUMsQ0FBQztBQUVGLDhCQUE4QixLQUFLLEVBQUUsUUFBUTtJQUN6QyxJQUFJLGtCQUFrQixHQUFHO1FBQ3JCLEtBQUssRUFBRSxLQUFLO1FBQ1osS0FBSyxFQUFFO1lBQ0gsU0FBUyxFQUFFO2dCQUNQLGlCQUFpQixFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTO2dCQUMvQyxRQUFRLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDakUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUk7YUFDdkU7WUFDRCxRQUFRLEVBQUUsRUFBRTtTQUNmO0tBQ0osQ0FBQztJQUVGLElBQUksUUFBUSxFQUFFO1FBQ1Ysa0JBQWtCLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsR0FBRyxRQUFRLENBQUM7S0FDckU7SUFFRCxPQUFPLGtCQUFrQixDQUFDO0FBQzlCLENBQUM7QUFFRCxJQUFJLE1BQU0sQ0FBQztBQUVYO0lBQ0ksSUFBSSxDQUFDLE1BQU0sRUFBRTtRQUNULFVBQVUsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ25DLE9BQU87S0FDVjtJQUVELElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO1FBQ2xCLFVBQVUsQ0FBQyxzQkFBc0IsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUN4QyxPQUFPO0tBQ1Y7SUFFRCxNQUFNLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQztRQUM3QixlQUFlLEVBQUUsSUFBSTtLQUN4QixFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ1osQ0FBQztBQUVELG9CQUFvQixZQUFZO0lBQzVCLElBQUksTUFBTSxFQUFFO1FBQ1IsWUFBWSxFQUFFLENBQUM7UUFDZixPQUFPO0tBQ1Y7SUFFRCxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMxQyxNQUFNLENBQUMsTUFBTSxHQUFHO1FBQ1osTUFBTSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDdkIsWUFBWSxFQUFFLENBQUM7SUFDbkIsQ0FBQyxDQUFDO0lBQ0YsTUFBTSxDQUFDLEdBQUcsR0FBRyxnREFBZ0QsQ0FBQztJQUM5RCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7SUFDOUIsQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDcEUsQ0FBQztBQUVELE1BQU0sQ0FBQyx3QkFBd0IsR0FBRyxVQUFVLFFBQVE7SUFFaEQsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRTtRQUM3QixRQUFRLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUM5QixPQUFPO0tBQ1Y7SUFFRCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFFckQsMEJBQTBCLEtBQUs7UUFDM0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJO1lBQUUsT0FBTztRQUV4QixJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMscUJBQXFCLEVBQUU7WUFDbEMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQztTQUM5QztRQUdELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQsVUFBVSxDQUFDLG1DQUFtQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ3pELENBQUMsQ0FBQztBQUVGO0lBQ0ksSUFBSSxDQUFDLE1BQU0sRUFBRTtRQUNULFVBQVUsQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1FBQ2hELE9BQU87S0FDVjtJQUVELElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO1FBQ2xCLFVBQVUsQ0FBQyxtQ0FBbUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNyRCxPQUFPO0tBQ1Y7SUFFRCxNQUFNLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQztRQUM3Qix3QkFBd0IsRUFBRSxJQUFJO0tBQ2pDLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDWixDQUFDO0FBRUQsT0FBTyxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7OztBQzVKbEMsSUFBSSxpQkFBaUIsR0FBRyxRQUFRLENBQUM7QUFDakMsSUFBSSxjQUFjLENBQUM7QUFDbkIsSUFBSSxTQUFTLEdBQUcsT0FBTyxNQUFNLENBQUMsY0FBYyxLQUFLLFdBQVcsQ0FBQztBQUM3RCxJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssSUFBSSxTQUFTLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDMUUsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUM7QUFFM0MsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxVQUFVLEtBQUs7SUFDOUMsSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFO1FBQ3hDLE9BQU87S0FDVjtJQUNELGlCQUFpQixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUNsQyxDQUFDLENBQUMsQ0FBQztBQUdILDJCQUEyQixJQUFJO0lBRTNCLElBQUksSUFBSSxJQUFJLHVCQUF1QixFQUFFO1FBQ2pDLGlCQUFpQixHQUFHLHVCQUF1QixDQUFDO1FBQzVDLElBQUksY0FBYztZQUNkLE9BQU8sY0FBYyxDQUFDLHVCQUF1QixDQUFDLENBQUM7O1lBRS9DLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztLQUNoRDtJQUVELElBQUksSUFBSSxJQUFJLHFDQUFxQyxFQUFFO1FBQy9DLGlCQUFpQixHQUFHLFNBQVMsQ0FBQztLQUNqQztJQUVELElBQUksSUFBSSxDQUFDLFFBQVEsSUFBSSxjQUFjLEVBQUU7UUFDakMsY0FBYyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7S0FDNUM7QUFDTCxDQUFDO0FBR0Qsb0NBQW9DLFFBQVE7SUFDeEMsSUFBSSxTQUFTO1FBQ1QsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0IsSUFBSSxpQkFBaUIsSUFBSSxTQUFTO1FBQzlCLE9BQU8sUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBRWpDLE1BQU0sQ0FBQyxXQUFXLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLFVBQVUsQ0FBQztRQUNQLElBQUksaUJBQWlCLElBQUksUUFBUSxFQUFFO1lBQy9CLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQztTQUMzQjs7WUFFRyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDOUIsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ2IsQ0FBQztBQUdELHFCQUFxQixRQUFRO0lBQ3pCLElBQUksQ0FBQyxRQUFRO1FBQ1QsTUFBTSxvQ0FBb0MsQ0FBQztJQUMvQyxJQUFJLFFBQVE7UUFDUixPQUFPLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5QixjQUFjLEdBQUcsUUFBUSxDQUFDO0lBQzFCLE1BQU0sQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzVDLENBQUM7QUFFRCxrQ0FBa0MsV0FBVyxFQUFFLFFBQVE7SUFDbkQsSUFBSSxTQUFTO1FBQ1QsT0FBTyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDbEMsSUFBSSxTQUFTLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRTtRQUN2QixRQUFRLEdBQUcsV0FBVyxDQUFDO1FBQ3ZCLFdBQVcsR0FBRyxrQ0FBa0MsQ0FBQztLQUNwRDtJQUNELElBQUksS0FBSyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDMUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxxQkFBcUIsR0FBRyxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQzlELEtBQUssQ0FBQyxNQUFNLEdBQUc7UUFDWCxpQkFBaUIsR0FBRyxRQUFRLENBQUM7UUFDN0IsTUFBTSxDQUFDLFdBQVcsQ0FBQyxlQUFlLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDekMsVUFBVSxDQUFDO1lBQ1AsSUFBSSxpQkFBaUIsSUFBSSxRQUFRLEVBQUU7Z0JBQy9CLFFBQVEsQ0FBQyxXQUFXLElBQUksV0FBVyxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsb0JBQW9CLENBQUMsQ0FBQzthQUNyRjs7Z0JBRUcsUUFBUSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDdEMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2IsQ0FBQyxDQUFDO0lBQ0YsS0FBSyxDQUFDLE9BQU8sR0FBRztRQUNaLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUM5QixDQUFDLENBQUM7QUFDTixDQUFDO0FBR0QsOEJBQThCLFFBQVE7SUFDbEMsUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUNkLElBQUksd0JBQXdCLEdBQUc7UUFDM0IsY0FBYyxFQUFFLFFBQVE7UUFDeEIsV0FBVyxFQUFFLFFBQVE7S0FDeEIsQ0FBQztJQUNGLElBQUksU0FBUztRQUNULE9BQU8sUUFBUSxDQUFDLElBQUksRUFBRSx3QkFBd0IsQ0FBQyxDQUFDO0lBR3BELElBQUksa0JBQWtCLEdBQUc7UUFDckIsU0FBUyxFQUFFO1lBQ1AsaUJBQWlCLEVBQUUsaUJBQWlCO1lBQ3BDLFFBQVEsRUFBRSxNQUFNLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSTtZQUNuRCxTQUFTLEVBQUUsTUFBTSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUk7U0FDekQ7UUFDRCxRQUFRLEVBQUUsRUFBRTtLQUNmLENBQUM7SUFJRixJQUFJLGlCQUFpQixJQUFJLFNBQVMsSUFBSSxDQUFDLFFBQVEsRUFBRTtRQUM3QyxXQUFXLENBQUM7WUFDUixrQkFBa0IsQ0FBQyxTQUFTLENBQUMsbUJBQW1CLEdBQUcsUUFBUSxDQUFDO1lBQzVELFFBQVEsQ0FBQyxRQUFRLElBQUksdUJBQXVCLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLGtCQUFrQixDQUFDLENBQUM7UUFDeEYsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPO0tBQ1Y7SUFFRCxJQUFJLGlCQUFpQixJQUFJLFNBQVMsRUFBRTtRQUNoQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsbUJBQW1CLEdBQUcsUUFBUSxDQUFDO0tBQy9EO0lBRUQsUUFBUSxDQUFDLElBQUksRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO0FBQ3ZDLENBQUM7QUFFRCxPQUFPLENBQUMsb0JBQW9CLEdBQUcsb0JBQW9CLENBQUM7QUFDcEQsT0FBTyxDQUFDLDBCQUEwQixHQUFHLDBCQUEwQixDQUFDO0FBQ2hFLE9BQU8sQ0FBQyx3QkFBd0IsR0FBRyx3QkFBd0IsQ0FBQztBQUM1RCxPQUFPLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQzs7Ozs7QUN6R2xDLG1DQUFzQztBQUV0QztJQWtDSSxxQkFBb0IsTUFBYztRQUFkLFdBQU0sR0FBTixNQUFNLENBQVE7UUFoQzFCLHVCQUFrQixHQUFHLEtBQUssQ0FBQztRQUUzQixrQkFBYSxHQUFHLENBQUMsQ0FBQztRQUNsQixVQUFLLEdBQVE7WUFDakIsT0FBTyxFQUFFO2dCQUNMLEtBQUssRUFBRTtvQkFDSCxhQUFhLEVBQUUsQ0FBQztvQkFDaEIsZUFBZSxFQUFFLENBQUM7b0JBQ2xCLFdBQVcsRUFBRSxDQUFDO2lCQUNqQjtnQkFDRCxLQUFLLEVBQUU7b0JBQ0gsYUFBYSxFQUFFLENBQUM7b0JBQ2hCLGVBQWUsRUFBRSxDQUFDO29CQUNsQixXQUFXLEVBQUUsQ0FBQztvQkFDZCxhQUFhLEVBQUUsQ0FBQztvQkFDaEIsU0FBUyxFQUFFLENBQUM7aUJBQ2Y7YUFDSjtZQUNELFFBQVEsRUFBRTtnQkFDTixLQUFLLEVBQUU7b0JBQ0gsU0FBUyxFQUFFLENBQUM7b0JBQ1osV0FBVyxFQUFFLENBQUM7aUJBQ2pCO2dCQUNELEtBQUssRUFBRTtvQkFDSCxTQUFTLEVBQUUsQ0FBQztvQkFDWixXQUFXLEVBQUUsQ0FBQztvQkFDZCxhQUFhLEVBQUUsQ0FBQztvQkFDaEIsU0FBUyxFQUFFLENBQUM7aUJBQ2Y7YUFDSjtTQUNKLENBQUM7SUFFb0MsQ0FBQztJQUVoQywrQkFBUyxHQUFoQjtRQUNJLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0lBQ25DLENBQUM7SUFFTSxxQ0FBZSxHQUF0QjtRQUFBLGlCQXdCQztRQXRCRyxJQUFNLHVCQUF1QixHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsMEJBQTBCLENBQUMsQ0FBQztRQUVqRixJQUFJLHVCQUF1QixFQUFFO1lBR3pCLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0NBQWtDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7WUFFbEksSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQztZQUUvQixJQUFNLGlCQUFlLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1lBQzVELElBQUksQ0FBQyxhQUFhLEdBQUcsaUJBQWUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO1lBRXJELE9BQU8sQ0FBQyxJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxpQkFBZSxDQUFDLENBQUMsQ0FBQztZQUV0RSxJQUFJLENBQUMscUJBQXFCLEdBQUcsV0FBVyxDQUFDO2dCQUNyQyxLQUFJLENBQUMsdUJBQXVCLENBQUMsaUJBQWUsQ0FBQyxDQUFDO1lBQ2xELENBQUMsRUFBRSxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxDQUFDO1lBRTlCLE9BQU87U0FDVjtRQUVELE9BQU8sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRU0scUNBQWUsR0FBdEI7UUFDSSxJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUN6QixhQUFhLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDMUMsT0FBTyxDQUFDLElBQUksQ0FBQywyQ0FBMkMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsR0FBRyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQztTQUM5STtJQUNMLENBQUM7SUFFTyw2Q0FBdUIsR0FBL0IsVUFBZ0MsZUFBZTtRQUEvQyxpQkFpTkM7UUEvTUcsSUFBTSxRQUFRLEdBQUcsVUFBQyxJQUFJO1lBQ2xCLElBQU0sSUFBSSxHQUFtQixJQUFJLGNBQWMsRUFBRSxDQUFDO1lBQ2xELElBQU0sR0FBRyxHQUFXLGVBQWUsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDO1lBQ3hELElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUU3QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxFQUFFLGtCQUFrQixDQUFDLENBQUM7WUFFMUQsSUFBSSxDQUFDLGtCQUFrQixHQUFHO2dCQUN0QixJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFO29CQUM5QyxPQUFPLENBQUMsR0FBRyxDQUFDLG9DQUFvQyxHQUFHLEdBQUcsR0FBRyxjQUFjLEdBQUcsS0FBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsaUJBQWlCLEdBQUcsS0FBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7aUJBQzdKO1lBQ0wsQ0FBQyxDQUFDO1lBQ0YsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQixDQUFDLENBQUM7UUFFRixJQUFNLENBQUMsR0FBRyxVQUFDLEtBQUs7WUFFWixJQUFJLFFBQVEsQ0FBQyxJQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO2dCQUMxQyxLQUFLLENBQUMsT0FBTyxDQUFDLFVBQUMsSUFBSTtvQkFFZixJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7b0JBRWQsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssYUFBYSxDQUFDO3dCQUM3QixDQUVJLElBQUksQ0FBQyxTQUFTLEtBQUssSUFBSTs0QkFDdkIsSUFBSSxDQUFDLFFBQVEsS0FBSyxLQUFLOzRCQUN2QixJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7NEJBQzdCLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUN0QyxFQUFFO3dCQUVILElBQU0sUUFBUSxHQUFHLGlCQUFpQixHQUFHLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7d0JBQ3RFLElBQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO3dCQUUvQixJQUFNLE9BQU8sR0FBRzs0QkFDWixhQUFhLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxhQUFhLENBQUMsR0FBRyxLQUFJLENBQUMsYUFBYTs0QkFDM0csTUFBTSxFQUFFLEdBQUc7NEJBQ1gsZUFBZSxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsZUFBZSxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWE7NEJBQ2pILFdBQVcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhO3lCQUN4RyxDQUFDO3dCQUNGLElBQU0sS0FBSyxHQUFHOzRCQUNWLGFBQWEsRUFBRSxPQUFPOzRCQUN0QixNQUFNLEVBQUUsSUFBSTs0QkFDWixlQUFlLEVBQUUsU0FBUzs0QkFDMUIsV0FBVyxFQUFFLFNBQVM7eUJBQ3pCLENBQUM7d0JBQ0YsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLE9BQU8sRUFBRTs0QkFDNUIsT0FBTyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQzs0QkFDOUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQzs0QkFDbEcsS0FBSyxDQUFDLGVBQWUsQ0FBQyxHQUFHLFFBQVEsQ0FBQzs0QkFDbEMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFHLFNBQVMsQ0FBQzs0QkFFL0IsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDOzRCQUM1RCxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7eUJBQ3ZEO3dCQUVELEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQzt3QkFDdEUsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO3dCQUMxRSxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7d0JBRWxFLElBQUksR0FBRzs0QkFDSCxZQUFZLEVBQUUsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsRUFBRTs0QkFDcEQsTUFBTSxFQUFFLGVBQWUsQ0FBQyxJQUFJOzRCQUM1QixXQUFXLEVBQUUsZUFBZSxDQUFDLFNBQVM7NEJBQ3RDLFFBQVEsRUFBRSxRQUFROzRCQUNsQixNQUFNLEVBQUUsUUFBUTs0QkFDaEIsYUFBYSxFQUFFLGtCQUFrQjs0QkFDakMsT0FBTyxFQUFFLEtBQUs7eUJBQ2pCLENBQUM7d0JBQ0YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLE9BQU8sQ0FBQzt3QkFFekIsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztxQkFFbEM7eUJBQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssY0FBYyxDQUFDO3dCQUNyQyxDQUVJLElBQUksQ0FBQyxRQUFRLEtBQUssS0FBSzs0QkFDdkIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQzdDLEVBQUU7d0JBRUgsSUFBTSxRQUFRLEdBQUcsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLFNBQVMsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQzt3QkFFdkUsSUFBTSxPQUFPLEdBQUc7NEJBQ1osU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWE7NEJBQ2hHLFdBQVcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhO3lCQUN6RyxDQUFDO3dCQUNGLElBQU0sS0FBSyxHQUFHOzRCQUNWLFNBQVMsRUFBRSxPQUFPOzRCQUNsQixXQUFXLEVBQUUsU0FBUzt5QkFDekIsQ0FBQzt3QkFDRixJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssT0FBTyxFQUFFOzRCQUM1QixPQUFPLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsR0FBRyxLQUFJLENBQUMsYUFBYSxDQUFDOzRCQUMvRyxLQUFLLENBQUMsZUFBZSxDQUFDLEdBQUcsUUFBUSxDQUFDOzRCQUVsQyxLQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7eUJBQ2hFO3dCQUVELEtBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQzt3QkFDL0QsS0FBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO3dCQUVuRSxJQUFJLEdBQUc7NEJBQ0gsWUFBWSxFQUFFLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLEVBQUU7NEJBQ3BELE1BQU0sRUFBRSxlQUFlLENBQUMsSUFBSTs0QkFDNUIsV0FBVyxFQUFFLGVBQWUsQ0FBQyxTQUFTOzRCQUN0QyxRQUFRLEVBQUUsUUFBUTs0QkFDbEIsTUFBTSxFQUFFLFFBQVE7NEJBQ2hCLGFBQWEsRUFBRSxrQkFBa0I7NEJBQ2pDLE9BQU8sRUFBRSxLQUFLO3lCQUNqQixDQUFDO3dCQUNGLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxPQUFPLENBQUM7d0JBRXpCLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7cUJBQ2xDO2dCQUNMLENBQUMsQ0FBQyxDQUFDO2FBQ047aUJBQU0sSUFBSSxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTtnQkFDaEQsS0FBa0IsVUFBa0IsRUFBbEIsS0FBQSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFsQixjQUFrQixFQUFsQixJQUFrQjtvQkFBL0IsSUFBTSxHQUFHLFNBQUE7b0JBQ1YsSUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUN4QixJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssTUFBTSxFQUFFO3dCQUV0QixJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7d0JBRWQsSUFBSSxlQUFlLElBQUksSUFBSSxJQUFJLENBQzNCLENBQUMsSUFBSSxDQUFDLFNBQVMsS0FBSyxPQUFPLElBQUksa0JBQWtCLElBQUksSUFBSSxDQUFDOzRCQUMxRCxDQUFDLElBQUksQ0FBQyxTQUFTLEtBQUssT0FBTyxJQUFJLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FDbEQsRUFBRTs0QkFFQyxJQUFNLFFBQVEsR0FBRyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsU0FBUyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDOzRCQUV0RSxJQUFNLE9BQU8sR0FBRztnQ0FDWixhQUFhLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxhQUFhLENBQUMsR0FBRyxLQUFJLENBQUMsYUFBYTtnQ0FDM0csTUFBTSxFQUFFLElBQUksQ0FBQyxrQkFBa0I7Z0NBQy9CLGVBQWUsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhO2dDQUNqSCxXQUFXLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLENBQUMsR0FBRyxLQUFJLENBQUMsYUFBYTs2QkFDeEcsQ0FBQzs0QkFDRixJQUFNLEtBQUssR0FBRztnQ0FDVixhQUFhLEVBQUUsT0FBTztnQ0FDdEIsTUFBTSxFQUFFLElBQUk7Z0NBQ1osZUFBZSxFQUFFLFNBQVM7Z0NBQzFCLFdBQVcsRUFBRSxTQUFTOzZCQUN6QixDQUFDOzRCQUNGLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxPQUFPLEVBQUU7Z0NBQzVCLE9BQU8sQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhLENBQUM7Z0NBQzlHLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhLENBQUM7Z0NBQ3RHLEtBQUssQ0FBQyxlQUFlLENBQUMsR0FBRyxRQUFRLENBQUM7Z0NBQ2xDLEtBQUssQ0FBQyxXQUFXLENBQUMsR0FBRyxTQUFTLENBQUM7Z0NBRS9CLEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztnQ0FDNUQsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDOzZCQUMzRDs0QkFFRCxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7NEJBQ3RFLEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQzs0QkFDMUUsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDOzRCQUVsRSxJQUFJLEdBQUc7Z0NBQ0gsWUFBWSxFQUFFLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLEVBQUU7Z0NBQ3BELE1BQU0sRUFBRSxlQUFlLENBQUMsSUFBSTtnQ0FDNUIsV0FBVyxFQUFFLGVBQWUsQ0FBQyxTQUFTO2dDQUN0QyxRQUFRLEVBQUUsUUFBUTtnQ0FDbEIsTUFBTSxFQUFFLFFBQVE7Z0NBQ2hCLGFBQWEsRUFBRSxrQkFBa0I7Z0NBQ2pDLE9BQU8sRUFBRSxLQUFLOzZCQUNqQixDQUFDOzRCQUNGLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxPQUFPLENBQUM7NEJBRXpCLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7eUJBQ2xDOzZCQUFNLElBQUksV0FBVyxJQUFJLElBQUksRUFBRTs0QkFFNUIsSUFBTSxRQUFRLEdBQUcsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLFNBQVMsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQzs0QkFFdkUsSUFBTSxPQUFPLEdBQUc7Z0NBQ1osU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWE7Z0NBQ2hHLFdBQVcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhOzZCQUN6RyxDQUFDOzRCQUNGLElBQU0sS0FBSyxHQUFHO2dDQUNWLFNBQVMsRUFBRSxPQUFPO2dDQUNsQixXQUFXLEVBQUUsU0FBUzs2QkFDekIsQ0FBQzs0QkFDRixJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssT0FBTyxFQUFFO2dDQUM1QixPQUFPLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsR0FBRyxLQUFJLENBQUMsYUFBYSxDQUFDO2dDQUMvRyxLQUFLLENBQUMsZUFBZSxDQUFDLEdBQUcsUUFBUSxDQUFDO2dDQUVsQyxLQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7NkJBQ2hFOzRCQUVELEtBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQzs0QkFDL0QsS0FBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDOzRCQUVuRSxJQUFJLEdBQUc7Z0NBQ0gsWUFBWSxFQUFFLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLEVBQUU7Z0NBQ3BELE1BQU0sRUFBRSxlQUFlLENBQUMsSUFBSTtnQ0FDNUIsV0FBVyxFQUFFLGVBQWUsQ0FBQyxTQUFTO2dDQUN0QyxRQUFRLEVBQUUsUUFBUTtnQ0FDbEIsTUFBTSxFQUFFLFFBQVE7Z0NBQ2hCLGFBQWEsRUFBRSxrQkFBa0I7Z0NBQ2pDLE9BQU8sRUFBRSxLQUFLOzZCQUNqQixDQUFDOzRCQUNGLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxPQUFPLENBQUM7NEJBRXpCLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7eUJBQ2xDO3FCQUNKO2lCQUNKO2FBQ0o7UUFDTCxDQUFDLENBQUM7UUFFRixJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsRUFBRSxFQUFFLENBQUMsRUFBRSxVQUFDLEtBQUssSUFBTyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckcsQ0FBQztJQUVPLHVDQUFpQixHQUF6QixVQUEwQixRQUFRO1FBQzlCLElBQUksUUFBUSxDQUFDLElBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7WUFDMUMsT0FBTyxRQUFRLENBQUM7U0FDbkI7UUFFRCxJQUFNLGNBQWMsR0FBRyxFQUFFLENBQUM7UUFDMUIsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFDLE1BQU07WUFDN0IsSUFBTSxhQUFhLEdBQUc7Z0JBQ2xCLEVBQUUsRUFBRSxNQUFNLENBQUMsRUFBRTtnQkFDYixTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7Z0JBQzNCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTthQUNwQixDQUFDO1lBQ0YsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFDLElBQUk7Z0JBQ3hCLGFBQWEsQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzVDLENBQUMsQ0FBQyxDQUFDO1lBQ0gsY0FBYyxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUMsR0FBRyxhQUFhLENBQUM7UUFDckQsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLGNBQWMsQ0FBQztJQUMxQixDQUFDO0lBRU8sc0NBQWdCLEdBQXhCLFVBQXlCLEVBQUUsRUFBRSxTQUFTLEVBQUUsU0FBUztRQUFqRCxpQkFjQztRQWJHLElBQUksUUFBUSxDQUFDLElBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7WUFFMUMsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxVQUFDLFFBQVE7Z0JBQzlCLElBQU0sTUFBTSxHQUFHLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDaEQsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RCLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztTQUNqQjthQUFNLElBQUksUUFBUSxDQUFDLElBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7WUFFaEQsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQUMsUUFBUTtnQkFDeEIsSUFBTSxNQUFNLEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztTQUN2QjtJQUNMLENBQUM7SUFFTCxrQkFBQztBQUFELENBalVBLEFBaVVDLElBQUE7QUFqVVksa0NBQVciLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qIVxyXG4gKiBAbmFtZSBKYXZhU2NyaXB0L05vZGVKUyBNZXJnZSB2MS4yLjBcclxuICogQGF1dGhvciB5ZWlrb3NcclxuICogQHJlcG9zaXRvcnkgaHR0cHM6Ly9naXRodWIuY29tL3llaWtvcy9qcy5tZXJnZVxyXG5cclxuICogQ29weXJpZ2h0IDIwMTQgeWVpa29zIC0gTUlUIGxpY2Vuc2VcclxuICogaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS95ZWlrb3MvanMubWVyZ2UvbWFzdGVyL0xJQ0VOU0VcclxuICovXHJcblxyXG47KGZ1bmN0aW9uKGlzTm9kZSkge1xyXG5cclxuXHQvKipcclxuXHQgKiBNZXJnZSBvbmUgb3IgbW9yZSBvYmplY3RzIFxyXG5cdCAqIEBwYXJhbSBib29sPyBjbG9uZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCwuLi4gYXJndW1lbnRzXHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0dmFyIFB1YmxpYyA9IGZ1bmN0aW9uKGNsb25lKSB7XHJcblxyXG5cdFx0cmV0dXJuIG1lcmdlKGNsb25lID09PSB0cnVlLCBmYWxzZSwgYXJndW1lbnRzKTtcclxuXHJcblx0fSwgcHVibGljTmFtZSA9ICdtZXJnZSc7XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvciBtb3JlIG9iamVjdHMgcmVjdXJzaXZlbHkgXHJcblx0ICogQHBhcmFtIGJvb2w/IGNsb25lXHJcblx0ICogQHBhcmFtIG1peGVkLC4uLiBhcmd1bWVudHNcclxuXHQgKiBAcmV0dXJuIG9iamVjdFxyXG5cdCAqL1xyXG5cclxuXHRQdWJsaWMucmVjdXJzaXZlID0gZnVuY3Rpb24oY2xvbmUpIHtcclxuXHJcblx0XHRyZXR1cm4gbWVyZ2UoY2xvbmUgPT09IHRydWUsIHRydWUsIGFyZ3VtZW50cyk7XHJcblxyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIENsb25lIHRoZSBpbnB1dCByZW1vdmluZyBhbnkgcmVmZXJlbmNlXHJcblx0ICogQHBhcmFtIG1peGVkIGlucHV0XHJcblx0ICogQHJldHVybiBtaXhlZFxyXG5cdCAqL1xyXG5cclxuXHRQdWJsaWMuY2xvbmUgPSBmdW5jdGlvbihpbnB1dCkge1xyXG5cclxuXHRcdHZhciBvdXRwdXQgPSBpbnB1dCxcclxuXHRcdFx0dHlwZSA9IHR5cGVPZihpbnB1dCksXHJcblx0XHRcdGluZGV4LCBzaXplO1xyXG5cclxuXHRcdGlmICh0eXBlID09PSAnYXJyYXknKSB7XHJcblxyXG5cdFx0XHRvdXRwdXQgPSBbXTtcclxuXHRcdFx0c2l6ZSA9IGlucHV0Lmxlbmd0aDtcclxuXHJcblx0XHRcdGZvciAoaW5kZXg9MDtpbmRleDxzaXplOysraW5kZXgpXHJcblxyXG5cdFx0XHRcdG91dHB1dFtpbmRleF0gPSBQdWJsaWMuY2xvbmUoaW5wdXRbaW5kZXhdKTtcclxuXHJcblx0XHR9IGVsc2UgaWYgKHR5cGUgPT09ICdvYmplY3QnKSB7XHJcblxyXG5cdFx0XHRvdXRwdXQgPSB7fTtcclxuXHJcblx0XHRcdGZvciAoaW5kZXggaW4gaW5wdXQpXHJcblxyXG5cdFx0XHRcdG91dHB1dFtpbmRleF0gPSBQdWJsaWMuY2xvbmUoaW5wdXRbaW5kZXhdKTtcclxuXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIG91dHB1dDtcclxuXHJcblx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogTWVyZ2UgdHdvIG9iamVjdHMgcmVjdXJzaXZlbHlcclxuXHQgKiBAcGFyYW0gbWl4ZWQgaW5wdXRcclxuXHQgKiBAcGFyYW0gbWl4ZWQgZXh0ZW5kXHJcblx0ICogQHJldHVybiBtaXhlZFxyXG5cdCAqL1xyXG5cclxuXHRmdW5jdGlvbiBtZXJnZV9yZWN1cnNpdmUoYmFzZSwgZXh0ZW5kKSB7XHJcblxyXG5cdFx0aWYgKHR5cGVPZihiYXNlKSAhPT0gJ29iamVjdCcpXHJcblxyXG5cdFx0XHRyZXR1cm4gZXh0ZW5kO1xyXG5cclxuXHRcdGZvciAodmFyIGtleSBpbiBleHRlbmQpIHtcclxuXHJcblx0XHRcdGlmICh0eXBlT2YoYmFzZVtrZXldKSA9PT0gJ29iamVjdCcgJiYgdHlwZU9mKGV4dGVuZFtrZXldKSA9PT0gJ29iamVjdCcpIHtcclxuXHJcblx0XHRcdFx0YmFzZVtrZXldID0gbWVyZ2VfcmVjdXJzaXZlKGJhc2Vba2V5XSwgZXh0ZW5kW2tleV0pO1xyXG5cclxuXHRcdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdFx0YmFzZVtrZXldID0gZXh0ZW5kW2tleV07XHJcblxyXG5cdFx0XHR9XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBiYXNlO1xyXG5cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvciBtb3JlIG9iamVjdHNcclxuXHQgKiBAcGFyYW0gYm9vbCBjbG9uZVxyXG5cdCAqIEBwYXJhbSBib29sIHJlY3Vyc2l2ZVxyXG5cdCAqIEBwYXJhbSBhcnJheSBhcmd2XHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0ZnVuY3Rpb24gbWVyZ2UoY2xvbmUsIHJlY3Vyc2l2ZSwgYXJndikge1xyXG5cclxuXHRcdHZhciByZXN1bHQgPSBhcmd2WzBdLFxyXG5cdFx0XHRzaXplID0gYXJndi5sZW5ndGg7XHJcblxyXG5cdFx0aWYgKGNsb25lIHx8IHR5cGVPZihyZXN1bHQpICE9PSAnb2JqZWN0JylcclxuXHJcblx0XHRcdHJlc3VsdCA9IHt9O1xyXG5cclxuXHRcdGZvciAodmFyIGluZGV4PTA7aW5kZXg8c2l6ZTsrK2luZGV4KSB7XHJcblxyXG5cdFx0XHR2YXIgaXRlbSA9IGFyZ3ZbaW5kZXhdLFxyXG5cclxuXHRcdFx0XHR0eXBlID0gdHlwZU9mKGl0ZW0pO1xyXG5cclxuXHRcdFx0aWYgKHR5cGUgIT09ICdvYmplY3QnKSBjb250aW51ZTtcclxuXHJcblx0XHRcdGZvciAodmFyIGtleSBpbiBpdGVtKSB7XHJcblxyXG5cdFx0XHRcdHZhciBzaXRlbSA9IGNsb25lID8gUHVibGljLmNsb25lKGl0ZW1ba2V5XSkgOiBpdGVtW2tleV07XHJcblxyXG5cdFx0XHRcdGlmIChyZWN1cnNpdmUpIHtcclxuXHJcblx0XHRcdFx0XHRyZXN1bHRba2V5XSA9IG1lcmdlX3JlY3Vyc2l2ZShyZXN1bHRba2V5XSwgc2l0ZW0pO1xyXG5cclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cclxuXHRcdFx0XHRcdHJlc3VsdFtrZXldID0gc2l0ZW07XHJcblxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdH1cclxuXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHJlc3VsdDtcclxuXHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgdHlwZSBvZiB2YXJpYWJsZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCBpbnB1dFxyXG5cdCAqIEByZXR1cm4gc3RyaW5nXHJcblx0ICpcclxuXHQgKiBAc2VlIGh0dHA6Ly9qc3BlcmYuY29tL3R5cGVvZnZhclxyXG5cdCAqL1xyXG5cclxuXHRmdW5jdGlvbiB0eXBlT2YoaW5wdXQpIHtcclxuXHJcblx0XHRyZXR1cm4gKHt9KS50b1N0cmluZy5jYWxsKGlucHV0KS5zbGljZSg4LCAtMSkudG9Mb3dlckNhc2UoKTtcclxuXHJcblx0fVxyXG5cclxuXHRpZiAoaXNOb2RlKSB7XHJcblxyXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBQdWJsaWM7XHJcblxyXG5cdH0gZWxzZSB7XHJcblxyXG5cdFx0d2luZG93W3B1YmxpY05hbWVdID0gUHVibGljO1xyXG5cclxuXHR9XHJcblxyXG59KSh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyk7IiwiLyoqXG4gICMgbm9ybWFsaWNlXG5cbiAgTm9ybWFsaXplIGFuIGljZSBzZXJ2ZXIgY29uZmlndXJhdGlvbiBvYmplY3QgKG9yIHBsYWluIG9sZCBzdHJpbmcpIGludG8gYSBmb3JtYXRcbiAgdGhhdCBpcyB1c2FibGUgaW4gYWxsIGJyb3dzZXJzIHN1cHBvcnRpbmcgV2ViUlRDLiAgUHJpbWFyaWx5IHRoaXMgbW9kdWxlIGlzIGRlc2lnbmVkXG4gIHRvIGhlbHAgd2l0aCB0aGUgdHJhbnNpdGlvbiBvZiB0aGUgYHVybGAgYXR0cmlidXRlIG9mIHRoZSBjb25maWd1cmF0aW9uIG9iamVjdCB0b1xuICB0aGUgYHVybHNgIGF0dHJpYnV0ZS5cblxuICAjIyBFeGFtcGxlIFVzYWdlXG5cbiAgPDw8IGV4YW1wbGVzL3NpbXBsZS5qc1xuXG4qKi9cblxudmFyIHByb3RvY29scyA9IFtcbiAgJ3N0dW46JyxcbiAgJ3R1cm46J1xuXTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpbnB1dCkge1xuICB2YXIgdXJsID0gKGlucHV0IHx8IHt9KS51cmwgfHwgaW5wdXQ7XG4gIHZhciBwcm90b2NvbDtcbiAgdmFyIHBhcnRzO1xuICB2YXIgb3V0cHV0ID0ge307XG5cbiAgLy8gaWYgd2UgZG9uJ3QgaGF2ZSBhIHN0cmluZyB1cmwsIHRoZW4gYWxsb3cgdGhlIGlucHV0IHRvIHBhc3N0aHJvdWdoXG4gIGlmICh0eXBlb2YgdXJsICE9ICdzdHJpbmcnICYmICghICh1cmwgaW5zdGFuY2VvZiBTdHJpbmcpKSkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIC8vIHRyaW0gdGhlIHVybCBzdHJpbmcsIGFuZCBjb252ZXJ0IHRvIGFuIGFycmF5XG4gIHVybCA9IHVybC50cmltKCk7XG5cbiAgLy8gaWYgdGhlIHByb3RvY29sIGlzIG5vdCBrbm93biwgdGhlbiBwYXNzdGhyb3VnaFxuICBwcm90b2NvbCA9IHByb3RvY29sc1twcm90b2NvbHMuaW5kZXhPZih1cmwuc2xpY2UoMCwgNSkpXTtcbiAgaWYgKCEgcHJvdG9jb2wpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyBub3cgbGV0J3MgYXR0YWNrIHRoZSByZW1haW5pbmcgdXJsIHBhcnRzXG4gIHVybCA9IHVybC5zbGljZSg1KTtcbiAgcGFydHMgPSB1cmwuc3BsaXQoJ0AnKTtcblxuICBvdXRwdXQudXNlcm5hbWUgPSBpbnB1dC51c2VybmFtZTtcbiAgb3V0cHV0LmNyZWRlbnRpYWwgPSBpbnB1dC5jcmVkZW50aWFsO1xuICAvLyBpZiB3ZSBoYXZlIGFuIGF1dGhlbnRpY2F0aW9uIHBhcnQsIHRoZW4gc2V0IHRoZSBjcmVkZW50aWFsc1xuICBpZiAocGFydHMubGVuZ3RoID4gMSkge1xuICAgIHVybCA9IHBhcnRzWzFdO1xuICAgIHBhcnRzID0gcGFydHNbMF0uc3BsaXQoJzonKTtcblxuICAgIC8vIGFkZCB0aGUgb3V0cHV0IGNyZWRlbnRpYWwgYW5kIHVzZXJuYW1lXG4gICAgb3V0cHV0LnVzZXJuYW1lID0gcGFydHNbMF07XG4gICAgb3V0cHV0LmNyZWRlbnRpYWwgPSAoaW5wdXQgfHwge30pLmNyZWRlbnRpYWwgfHwgcGFydHNbMV0gfHwgJyc7XG4gIH1cblxuICBvdXRwdXQudXJsID0gcHJvdG9jb2wgKyB1cmw7XG4gIG91dHB1dC51cmxzID0gWyBvdXRwdXQudXJsIF07XG5cbiAgcmV0dXJuIG91dHB1dDtcbn07XG4iLCIvKiFcbiAqIFBsYXRmb3JtLmpzIDxodHRwczovL210aHMuYmUvcGxhdGZvcm0+XG4gKiBDb3B5cmlnaHQgMjAxNC0yMDE4IEJlbmphbWluIFRhbiA8aHR0cHM6Ly9ibmptbnQ0bi5ub3cuc2gvPlxuICogQ29weXJpZ2h0IDIwMTEtMjAxMyBKb2huLURhdmlkIERhbHRvbiA8aHR0cDovL2FsbHlvdWNhbmxlZXQuY29tLz5cbiAqIEF2YWlsYWJsZSB1bmRlciBNSVQgbGljZW5zZSA8aHR0cHM6Ly9tdGhzLmJlL21pdD5cbiAqL1xuOyhmdW5jdGlvbigpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVybWluZSBpZiB2YWx1ZXMgYXJlIG9mIHRoZSBsYW5ndWFnZSB0eXBlIGBPYmplY3RgLiAqL1xuICB2YXIgb2JqZWN0VHlwZXMgPSB7XG4gICAgJ2Z1bmN0aW9uJzogdHJ1ZSxcbiAgICAnb2JqZWN0JzogdHJ1ZVxuICB9O1xuXG4gIC8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgcm9vdCA9IChvYmplY3RUeXBlc1t0eXBlb2Ygd2luZG93XSAmJiB3aW5kb3cpIHx8IHRoaXM7XG5cbiAgLyoqIEJhY2t1cCBwb3NzaWJsZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgb2xkUm9vdCA9IHJvb3Q7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBleHBvcnRzYC4gKi9cbiAgdmFyIGZyZWVFeHBvcnRzID0gb2JqZWN0VHlwZXNbdHlwZW9mIGV4cG9ydHNdICYmIGV4cG9ydHM7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBtb2R1bGVgLiAqL1xuICB2YXIgZnJlZU1vZHVsZSA9IG9iamVjdFR5cGVzW3R5cGVvZiBtb2R1bGVdICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzIG9yIEJyb3dzZXJpZmllZCBjb2RlIGFuZCB1c2UgaXQgYXMgYHJvb3RgLiAqL1xuICB2YXIgZnJlZUdsb2JhbCA9IGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUgJiYgdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWw7XG4gIGlmIChmcmVlR2xvYmFsICYmIChmcmVlR2xvYmFsLmdsb2JhbCA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLndpbmRvdyA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLnNlbGYgPT09IGZyZWVHbG9iYWwpKSB7XG4gICAgcm9vdCA9IGZyZWVHbG9iYWw7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBhcyB0aGUgbWF4aW11bSBsZW5ndGggb2YgYW4gYXJyYXktbGlrZSBvYmplY3QuXG4gICAqIFNlZSB0aGUgW0VTNiBzcGVjXShodHRwOi8vcGVvcGxlLm1vemlsbGEub3JnL35qb3JlbmRvcmZmL2VzNi1kcmFmdC5odG1sI3NlYy10b2xlbmd0aClcbiAgICogZm9yIG1vcmUgZGV0YWlscy5cbiAgICovXG4gIHZhciBtYXhTYWZlSW50ZWdlciA9IE1hdGgucG93KDIsIDUzKSAtIDE7XG5cbiAgLyoqIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBkZXRlY3QgT3BlcmEuICovXG4gIHZhciByZU9wZXJhID0gL1xcYk9wZXJhLztcblxuICAvKiogUG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHRoaXNCaW5kaW5nID0gdGhpcztcblxuICAvKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xuICB2YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4gIC8qKiBVc2VkIHRvIGNoZWNrIGZvciBvd24gcHJvcGVydGllcyBvZiBhbiBvYmplY3QuICovXG4gIHZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4gIC8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIHZhbHVlcy4gKi9cbiAgdmFyIHRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENhcGl0YWxpemVzIGEgc3RyaW5nIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGNhcGl0YWxpemVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gU3RyaW5nKHN0cmluZyk7XG4gICAgcmV0dXJuIHN0cmluZy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0cmluZy5zbGljZSgxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHV0aWxpdHkgZnVuY3Rpb24gdG8gY2xlYW4gdXAgdGhlIE9TIG5hbWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcyBUaGUgT1MgbmFtZSB0byBjbGVhbiB1cC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwYXR0ZXJuXSBBIGBSZWdFeHBgIHBhdHRlcm4gbWF0Y2hpbmcgdGhlIE9TIG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbGFiZWxdIEEgbGFiZWwgZm9yIHRoZSBPUy5cbiAgICovXG4gIGZ1bmN0aW9uIGNsZWFudXBPUyhvcywgcGF0dGVybiwgbGFiZWwpIHtcbiAgICAvLyBQbGF0Zm9ybSB0b2tlbnMgYXJlIGRlZmluZWQgYXQ6XG4gICAgLy8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgLy8gaHR0cDovL3dlYi5hcmNoaXZlLm9yZy93ZWIvMjAwODExMjIwNTM5NTAvaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgdmFyIGRhdGEgPSB7XG4gICAgICAnMTAuMCc6ICcxMCcsXG4gICAgICAnNi40JzogICcxMCBUZWNobmljYWwgUHJldmlldycsXG4gICAgICAnNi4zJzogICc4LjEnLFxuICAgICAgJzYuMic6ICAnOCcsXG4gICAgICAnNi4xJzogICdTZXJ2ZXIgMjAwOCBSMiAvIDcnLFxuICAgICAgJzYuMCc6ICAnU2VydmVyIDIwMDggLyBWaXN0YScsXG4gICAgICAnNS4yJzogICdTZXJ2ZXIgMjAwMyAvIFhQIDY0LWJpdCcsXG4gICAgICAnNS4xJzogICdYUCcsXG4gICAgICAnNS4wMSc6ICcyMDAwIFNQMScsXG4gICAgICAnNS4wJzogICcyMDAwJyxcbiAgICAgICc0LjAnOiAgJ05UJyxcbiAgICAgICc0LjkwJzogJ01FJ1xuICAgIH07XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgdmVyc2lvbiBmcm9tIHBsYXRmb3JtIHRva2Vucy5cbiAgICBpZiAocGF0dGVybiAmJiBsYWJlbCAmJiAvXldpbi9pLnRlc3Qob3MpICYmICEvXldpbmRvd3MgUGhvbmUgL2kudGVzdChvcykgJiZcbiAgICAgICAgKGRhdGEgPSBkYXRhWy9bXFxkLl0rJC8uZXhlYyhvcyldKSkge1xuICAgICAgb3MgPSAnV2luZG93cyAnICsgZGF0YTtcbiAgICB9XG4gICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgb3MgPSBTdHJpbmcob3MpO1xuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwpIHtcbiAgICAgIG9zID0gb3MucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgbGFiZWwpO1xuICAgIH1cblxuICAgIG9zID0gZm9ybWF0KFxuICAgICAgb3MucmVwbGFjZSgvIGNlJC9pLCAnIENFJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYmhwdy9pLCAnd2ViJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hY2ludG9zaFxcYi8sICdNYWMgT1MnKVxuICAgICAgICAucmVwbGFjZSgvX1Bvd2VyUENcXGIvaSwgJyBPUycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoT1MgWCkgW14gXFxkXSsvaSwgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hYyAoT1MgWClcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFwvKFxcZCkvLCAnICQxJylcbiAgICAgICAgLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICAucmVwbGFjZSgvKD86IEJlUEN8WyAuXSpmY1sgXFxkLl0rKSQvaSwgJycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJ4ODZcXC42NFxcYi9naSwgJ3g4Nl82NCcpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoV2luZG93cyBQaG9uZSkgT1NcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKENocm9tZSBPUyBcXHcrKSBbXFxkLl0rXFxiLywgJyQxJylcbiAgICAgICAgLnNwbGl0KCcgb24gJylbMF1cbiAgICApO1xuXG4gICAgcmV0dXJuIG9zO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGl0ZXJhdGlvbiB1dGlsaXR5IGZvciBhcnJheXMgYW5kIG9iamVjdHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIGVhY2gob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBvYmplY3QgPyBvYmplY3QubGVuZ3RoIDogMDtcblxuICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInICYmIGxlbmd0aCA+IC0xICYmIGxlbmd0aCA8PSBtYXhTYWZlSW50ZWdlcikge1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2luZGV4XSwgaW5kZXgsIG9iamVjdCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvck93bihvYmplY3QsIGNhbGxiYWNrKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJpbSBhbmQgY29uZGl0aW9uYWxseSBjYXBpdGFsaXplIHN0cmluZyB2YWx1ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBmb3JtYXQuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBmb3JtYXR0ZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gZm9ybWF0KHN0cmluZykge1xuICAgIHN0cmluZyA9IHRyaW0oc3RyaW5nKTtcbiAgICByZXR1cm4gL14oPzp3ZWJPU3xpKD86T1N8UCkpLy50ZXN0KHN0cmluZylcbiAgICAgID8gc3RyaW5nXG4gICAgICA6IGNhcGl0YWxpemUoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJdGVyYXRlcyBvdmVyIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzLCBleGVjdXRpbmcgdGhlIGBjYWxsYmFja2AgZm9yIGVhY2guXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBleGVjdXRlZCBwZXIgb3duIHByb3BlcnR5LlxuICAgKi9cbiAgZnVuY3Rpb24gZm9yT3duKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2tleV0sIGtleSwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgaW50ZXJuYWwgYFtbQ2xhc3NdXWAgb2YgYSB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBgW1tDbGFzc11dYC5cbiAgICovXG4gIGZ1bmN0aW9uIGdldENsYXNzT2YodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPT0gbnVsbFxuICAgICAgPyBjYXBpdGFsaXplKHZhbHVlKVxuICAgICAgOiB0b1N0cmluZy5jYWxsKHZhbHVlKS5zbGljZSg4LCAtMSk7XG4gIH1cblxuICAvKipcbiAgICogSG9zdCBvYmplY3RzIGNhbiByZXR1cm4gdHlwZSB2YWx1ZXMgdGhhdCBhcmUgZGlmZmVyZW50IGZyb20gdGhlaXIgYWN0dWFsXG4gICAqIGRhdGEgdHlwZS4gVGhlIG9iamVjdHMgd2UgYXJlIGNvbmNlcm5lZCB3aXRoIHVzdWFsbHkgcmV0dXJuIG5vbi1wcmltaXRpdmVcbiAgICogdHlwZXMgb2YgXCJvYmplY3RcIiwgXCJmdW5jdGlvblwiLCBvciBcInVua25vd25cIi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSBvYmplY3QgVGhlIG93bmVyIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3BlcnR5IFRoZSBwcm9wZXJ0eSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyBhIG5vbi1wcmltaXRpdmUsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGlzSG9zdFR5cGUob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgIHZhciB0eXBlID0gb2JqZWN0ICE9IG51bGwgPyB0eXBlb2Ygb2JqZWN0W3Byb3BlcnR5XSA6ICdudW1iZXInO1xuICAgIHJldHVybiAhL14oPzpib29sZWFufG51bWJlcnxzdHJpbmd8dW5kZWZpbmVkKSQvLnRlc3QodHlwZSkgJiZcbiAgICAgICh0eXBlID09ICdvYmplY3QnID8gISFvYmplY3RbcHJvcGVydHldIDogdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUHJlcGFyZXMgYSBzdHJpbmcgZm9yIHVzZSBpbiBhIGBSZWdFeHBgIGJ5IG1ha2luZyBoeXBoZW5zIGFuZCBzcGFjZXMgb3B0aW9uYWwuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBxdWFsaWZ5LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgcXVhbGlmaWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIHF1YWxpZnkoc3RyaW5nKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoLyhbIC1dKSg/ISQpL2csICckMT8nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGJhcmUtYm9uZXMgYEFycmF5I3JlZHVjZWAgbGlrZSB1dGlsaXR5IGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHsqfSBUaGUgYWNjdW11bGF0ZWQgcmVzdWx0LlxuICAgKi9cbiAgZnVuY3Rpb24gcmVkdWNlKGFycmF5LCBjYWxsYmFjaykge1xuICAgIHZhciBhY2N1bXVsYXRvciA9IG51bGw7XG4gICAgZWFjaChhcnJheSwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICBhY2N1bXVsYXRvciA9IGNhbGxiYWNrKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGFycmF5KTtcbiAgICB9KTtcbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIGZyb20gYSBzdHJpbmcuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byB0cmltLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgdHJpbW1lZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiB0cmltKHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC9eICt8ICskL2csICcnKTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IHBsYXRmb3JtIG9iamVjdC5cbiAgICpcbiAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAqIEBwYXJhbSB7T2JqZWN0fHN0cmluZ30gW3VhPW5hdmlnYXRvci51c2VyQWdlbnRdIFRoZSB1c2VyIGFnZW50IHN0cmluZyBvclxuICAgKiAgY29udGV4dCBvYmplY3QuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IEEgcGxhdGZvcm0gb2JqZWN0LlxuICAgKi9cbiAgZnVuY3Rpb24gcGFyc2UodWEpIHtcblxuICAgIC8qKiBUaGUgZW52aXJvbm1lbnQgY29udGV4dCBvYmplY3QuICovXG4gICAgdmFyIGNvbnRleHQgPSByb290O1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGEgY3VzdG9tIGNvbnRleHQgaXMgcHJvdmlkZWQuICovXG4gICAgdmFyIGlzQ3VzdG9tQ29udGV4dCA9IHVhICYmIHR5cGVvZiB1YSA9PSAnb2JqZWN0JyAmJiBnZXRDbGFzc09mKHVhKSAhPSAnU3RyaW5nJztcblxuICAgIC8vIEp1Z2dsZSBhcmd1bWVudHMuXG4gICAgaWYgKGlzQ3VzdG9tQ29udGV4dCkge1xuICAgICAgY29udGV4dCA9IHVhO1xuICAgICAgdWEgPSBudWxsO1xuICAgIH1cblxuICAgIC8qKiBCcm93c2VyIG5hdmlnYXRvciBvYmplY3QuICovXG4gICAgdmFyIG5hdiA9IGNvbnRleHQubmF2aWdhdG9yIHx8IHt9O1xuXG4gICAgLyoqIEJyb3dzZXIgdXNlciBhZ2VudCBzdHJpbmcuICovXG4gICAgdmFyIHVzZXJBZ2VudCA9IG5hdi51c2VyQWdlbnQgfHwgJyc7XG5cbiAgICB1YSB8fCAodWEgPSB1c2VyQWdlbnQpO1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGB0aGlzQmluZGluZ2AgaXMgdGhlIFtNb2R1bGVTY29wZV0uICovXG4gICAgdmFyIGlzTW9kdWxlU2NvcGUgPSBpc0N1c3RvbUNvbnRleHQgfHwgdGhpc0JpbmRpbmcgPT0gb2xkUm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGRldGVjdCBpZiBicm93c2VyIGlzIGxpa2UgQ2hyb21lLiAqL1xuICAgIHZhciBsaWtlQ2hyb21lID0gaXNDdXN0b21Db250ZXh0XG4gICAgICA/ICEhbmF2Lmxpa2VDaHJvbWVcbiAgICAgIDogL1xcYkNocm9tZVxcYi8udGVzdCh1YSkgJiYgIS9pbnRlcm5hbHxcXG4vaS50ZXN0KHRvU3RyaW5nLnRvU3RyaW5nKCkpO1xuXG4gICAgLyoqIEludGVybmFsIGBbW0NsYXNzXV1gIHZhbHVlIHNob3J0Y3V0cy4gKi9cbiAgICB2YXIgb2JqZWN0Q2xhc3MgPSAnT2JqZWN0JyxcbiAgICAgICAgYWlyUnVudGltZUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnU2NyaXB0QnJpZGdpbmdQcm94eU9iamVjdCcsXG4gICAgICAgIGVudmlyb0NsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnRW52aXJvbm1lbnQnLFxuICAgICAgICBqYXZhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIGNvbnRleHQuamF2YSkgPyAnSmF2YVBhY2thZ2UnIDogZ2V0Q2xhc3NPZihjb250ZXh0LmphdmEpLFxuICAgICAgICBwaGFudG9tQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdSdW50aW1lT2JqZWN0JztcblxuICAgIC8qKiBEZXRlY3QgSmF2YSBlbnZpcm9ubWVudHMuICovXG4gICAgdmFyIGphdmEgPSAvXFxiSmF2YS8udGVzdChqYXZhQ2xhc3MpICYmIGNvbnRleHQuamF2YTtcblxuICAgIC8qKiBEZXRlY3QgUmhpbm8uICovXG4gICAgdmFyIHJoaW5vID0gamF2YSAmJiBnZXRDbGFzc09mKGNvbnRleHQuZW52aXJvbm1lbnQpID09IGVudmlyb0NsYXNzO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBhbHBoYS4gKi9cbiAgICB2YXIgYWxwaGEgPSBqYXZhID8gJ2EnIDogJ1xcdTAzYjEnO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBiZXRhLiAqL1xuICAgIHZhciBiZXRhID0gamF2YSA/ICdiJyA6ICdcXHUwM2IyJztcblxuICAgIC8qKiBCcm93c2VyIGRvY3VtZW50IG9iamVjdC4gKi9cbiAgICB2YXIgZG9jID0gY29udGV4dC5kb2N1bWVudCB8fCB7fTtcblxuICAgIC8qKlxuICAgICAqIERldGVjdCBPcGVyYSBicm93c2VyIChQcmVzdG8tYmFzZWQpLlxuICAgICAqIGh0dHA6Ly93d3cuaG93dG9jcmVhdGUuY28udWsvb3BlcmFTdHVmZi9vcGVyYU9iamVjdC5odG1sXG4gICAgICogaHR0cDovL2Rldi5vcGVyYS5jb20vYXJ0aWNsZXMvdmlldy9vcGVyYS1taW5pLXdlYi1jb250ZW50LWF1dGhvcmluZy1ndWlkZWxpbmVzLyNvcGVyYW1pbmlcbiAgICAgKi9cbiAgICB2YXIgb3BlcmEgPSBjb250ZXh0Lm9wZXJhbWluaSB8fCBjb250ZXh0Lm9wZXJhO1xuXG4gICAgLyoqIE9wZXJhIGBbW0NsYXNzXV1gLiAqL1xuICAgIHZhciBvcGVyYUNsYXNzID0gcmVPcGVyYS50ZXN0KG9wZXJhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIG9wZXJhKSA/IG9wZXJhWydbW0NsYXNzXV0nXSA6IGdldENsYXNzT2Yob3BlcmEpKVxuICAgICAgPyBvcGVyYUNsYXNzXG4gICAgICA6IChvcGVyYSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqIFRlbXBvcmFyeSB2YXJpYWJsZSB1c2VkIG92ZXIgdGhlIHNjcmlwdCdzIGxpZmV0aW1lLiAqL1xuICAgIHZhciBkYXRhO1xuXG4gICAgLyoqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlLiAqL1xuICAgIHZhciBhcmNoID0gdWE7XG5cbiAgICAvKiogUGxhdGZvcm0gZGVzY3JpcHRpb24gYXJyYXkuICovXG4gICAgdmFyIGRlc2NyaXB0aW9uID0gW107XG5cbiAgICAvKiogUGxhdGZvcm0gYWxwaGEvYmV0YSBpbmRpY2F0b3IuICovXG4gICAgdmFyIHByZXJlbGVhc2UgPSBudWxsO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSB0aGF0IGVudmlyb25tZW50IGZlYXR1cmVzIHNob3VsZCBiZSB1c2VkIHRvIHJlc29sdmUgdGhlIHBsYXRmb3JtLiAqL1xuICAgIHZhciB1c2VGZWF0dXJlcyA9IHVhID09IHVzZXJBZ2VudDtcblxuICAgIC8qKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLiAqL1xuICAgIHZhciB2ZXJzaW9uID0gdXNlRmVhdHVyZXMgJiYgb3BlcmEgJiYgdHlwZW9mIG9wZXJhLnZlcnNpb24gPT0gJ2Z1bmN0aW9uJyAmJiBvcGVyYS52ZXJzaW9uKCk7XG5cbiAgICAvKiogQSBmbGFnIHRvIGluZGljYXRlIGlmIHRoZSBPUyBlbmRzIHdpdGggXCIvIFZlcnNpb25cIiAqL1xuICAgIHZhciBpc1NwZWNpYWxDYXNlZE9TO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBsYXlvdXQgZW5naW5lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbGF5b3V0ID0gZ2V0TGF5b3V0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0VkZ2VIVE1MJywgJ3BhdHRlcm4nOiAnRWRnZScgfSxcbiAgICAgICdUcmlkZW50JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1dlYktpdCcsICdwYXR0ZXJuJzogJ0FwcGxlV2ViS2l0JyB9LFxuICAgICAgJ2lDYWInLFxuICAgICAgJ1ByZXN0bycsXG4gICAgICAnTmV0RnJvbnQnLFxuICAgICAgJ1Rhc21hbicsXG4gICAgICAnS0hUTUwnLFxuICAgICAgJ0dlY2tvJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBicm93c2VyIG5hbWVzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBuYW1lID0gZ2V0TmFtZShbXG4gICAgICAnQWRvYmUgQUlSJyxcbiAgICAgICdBcm9yYScsXG4gICAgICAnQXZhbnQgQnJvd3NlcicsXG4gICAgICAnQnJlYWNoJyxcbiAgICAgICdDYW1pbm8nLFxuICAgICAgJ0VsZWN0cm9uJyxcbiAgICAgICdFcGlwaGFueScsXG4gICAgICAnRmVubmVjJyxcbiAgICAgICdGbG9jaycsXG4gICAgICAnR2FsZW9uJyxcbiAgICAgICdHcmVlbkJyb3dzZXInLFxuICAgICAgJ2lDYWInLFxuICAgICAgJ0ljZXdlYXNlbCcsXG4gICAgICAnSy1NZWxlb24nLFxuICAgICAgJ0tvbnF1ZXJvcicsXG4gICAgICAnTHVuYXNjYXBlJyxcbiAgICAgICdNYXh0aG9uJyxcbiAgICAgIHsgJ2xhYmVsJzogJ01pY3Jvc29mdCBFZGdlJywgJ3BhdHRlcm4nOiAnRWRnZScgfSxcbiAgICAgICdNaWRvcmknLFxuICAgICAgJ05vb2sgQnJvd3NlcicsXG4gICAgICAnUGFsZU1vb24nLFxuICAgICAgJ1BoYW50b21KUycsXG4gICAgICAnUmF2ZW4nLFxuICAgICAgJ1Jla29ucScsXG4gICAgICAnUm9ja01lbHQnLFxuICAgICAgeyAnbGFiZWwnOiAnU2Ftc3VuZyBJbnRlcm5ldCcsICdwYXR0ZXJuJzogJ1NhbXN1bmdCcm93c2VyJyB9LFxuICAgICAgJ1NlYU1vbmtleScsXG4gICAgICB7ICdsYWJlbCc6ICdTaWxrJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ1NsZWlwbmlyJyxcbiAgICAgICdTbGltQnJvd3NlcicsXG4gICAgICB7ICdsYWJlbCc6ICdTUldhcmUgSXJvbicsICdwYXR0ZXJuJzogJ0lyb24nIH0sXG4gICAgICAnU3VucmlzZScsXG4gICAgICAnU3dpZnRmb3gnLFxuICAgICAgJ1dhdGVyZm94JyxcbiAgICAgICdXZWJQb3NpdGl2ZScsXG4gICAgICAnT3BlcmEgTWluaScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYSBNaW5pJywgJ3BhdHRlcm4nOiAnT1BpT1MnIH0sXG4gICAgICAnT3BlcmEnLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEnLCAncGF0dGVybic6ICdPUFInIH0sXG4gICAgICAnQ2hyb21lJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBNb2JpbGUnLCAncGF0dGVybic6ICcoPzpDcmlPU3xDck1vKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0ZpcmVmb3gnLCAncGF0dGVybic6ICcoPzpGaXJlZm94fE1pbmVmaWVsZCknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94IGZvciBpT1MnLCAncGF0dGVybic6ICdGeGlPUycgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0lFJywgJ3BhdHRlcm4nOiAnSUVNb2JpbGUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ01TSUUnIH0sXG4gICAgICAnU2FmYXJpJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBwcm9kdWN0cyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgcHJvZHVjdCA9IGdldFByb2R1Y3QoW1xuICAgICAgeyAnbGFiZWwnOiAnQmxhY2tCZXJyeScsICdwYXR0ZXJuJzogJ0JCMTAnIH0sXG4gICAgICAnQmxhY2tCZXJyeScsXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUycsICdwYXR0ZXJuJzogJ0dULUk5MDAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMyJywgJ3BhdHRlcm4nOiAnR1QtSTkxMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzMnLCAncGF0dGVybic6ICdHVC1JOTMwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNCcsICdwYXR0ZXJuJzogJ0dULUk5NTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM1JywgJ3BhdHRlcm4nOiAnU00tRzkwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNicsICdwYXR0ZXJuJzogJ1NNLUc5MjAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYgRWRnZScsICdwYXR0ZXJuJzogJ1NNLUc5MjUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzcnLCAncGF0dGVybic6ICdTTS1HOTMwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTM1JyB9LFxuICAgICAgJ0dvb2dsZSBUVicsXG4gICAgICAnTHVtaWEnLFxuICAgICAgJ2lQYWQnLFxuICAgICAgJ2lQb2QnLFxuICAgICAgJ2lQaG9uZScsXG4gICAgICAnS2luZGxlJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0tpbmRsZSBGaXJlJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ05leHVzJyxcbiAgICAgICdOb29rJyxcbiAgICAgICdQbGF5Qm9vaycsXG4gICAgICAnUGxheVN0YXRpb24gVml0YScsXG4gICAgICAnUGxheVN0YXRpb24nLFxuICAgICAgJ1RvdWNoUGFkJyxcbiAgICAgICdUcmFuc2Zvcm1lcicsXG4gICAgICB7ICdsYWJlbCc6ICdXaWkgVScsICdwYXR0ZXJuJzogJ1dpaVUnIH0sXG4gICAgICAnV2lpJyxcbiAgICAgICdYYm94IE9uZScsXG4gICAgICB7ICdsYWJlbCc6ICdYYm94IDM2MCcsICdwYXR0ZXJuJzogJ1hib3gnIH0sXG4gICAgICAnWG9vbSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgbWFudWZhY3R1cmVycy4gKi9cbiAgICB2YXIgbWFudWZhY3R1cmVyID0gZ2V0TWFudWZhY3R1cmVyKHtcbiAgICAgICdBcHBsZSc6IHsgJ2lQYWQnOiAxLCAnaVBob25lJzogMSwgJ2lQb2QnOiAxIH0sXG4gICAgICAnQXJjaG9zJzoge30sXG4gICAgICAnQW1hem9uJzogeyAnS2luZGxlJzogMSwgJ0tpbmRsZSBGaXJlJzogMSB9LFxuICAgICAgJ0FzdXMnOiB7ICdUcmFuc2Zvcm1lcic6IDEgfSxcbiAgICAgICdCYXJuZXMgJiBOb2JsZSc6IHsgJ05vb2snOiAxIH0sXG4gICAgICAnQmxhY2tCZXJyeSc6IHsgJ1BsYXlCb29rJzogMSB9LFxuICAgICAgJ0dvb2dsZSc6IHsgJ0dvb2dsZSBUVic6IDEsICdOZXh1cyc6IDEgfSxcbiAgICAgICdIUCc6IHsgJ1RvdWNoUGFkJzogMSB9LFxuICAgICAgJ0hUQyc6IHt9LFxuICAgICAgJ0xHJzoge30sXG4gICAgICAnTWljcm9zb2Z0JzogeyAnWGJveCc6IDEsICdYYm94IE9uZSc6IDEgfSxcbiAgICAgICdNb3Rvcm9sYSc6IHsgJ1hvb20nOiAxIH0sXG4gICAgICAnTmludGVuZG8nOiB7ICdXaWkgVSc6IDEsICAnV2lpJzogMSB9LFxuICAgICAgJ05va2lhJzogeyAnTHVtaWEnOiAxIH0sXG4gICAgICAnU2Ftc3VuZyc6IHsgJ0dhbGF4eSBTJzogMSwgJ0dhbGF4eSBTMic6IDEsICdHYWxheHkgUzMnOiAxLCAnR2FsYXh5IFM0JzogMSB9LFxuICAgICAgJ1NvbnknOiB7ICdQbGF5U3RhdGlvbic6IDEsICdQbGF5U3RhdGlvbiBWaXRhJzogMSB9XG4gICAgfSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG9wZXJhdGluZyBzeXN0ZW1zIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBvcyA9IGdldE9TKFtcbiAgICAgICdXaW5kb3dzIFBob25lJyxcbiAgICAgICdBbmRyb2lkJyxcbiAgICAgICdDZW50T1MnLFxuICAgICAgeyAnbGFiZWwnOiAnQ2hyb21lIE9TJywgJ3BhdHRlcm4nOiAnQ3JPUycgfSxcbiAgICAgICdEZWJpYW4nLFxuICAgICAgJ0ZlZG9yYScsXG4gICAgICAnRnJlZUJTRCcsXG4gICAgICAnR2VudG9vJyxcbiAgICAgICdIYWlrdScsXG4gICAgICAnS3VidW50dScsXG4gICAgICAnTGludXggTWludCcsXG4gICAgICAnT3BlbkJTRCcsXG4gICAgICAnUmVkIEhhdCcsXG4gICAgICAnU3VTRScsXG4gICAgICAnVWJ1bnR1JyxcbiAgICAgICdYdWJ1bnR1JyxcbiAgICAgICdDeWd3aW4nLFxuICAgICAgJ1N5bWJpYW4gT1MnLFxuICAgICAgJ2hwd09TJyxcbiAgICAgICd3ZWJPUyAnLFxuICAgICAgJ3dlYk9TJyxcbiAgICAgICdUYWJsZXQgT1MnLFxuICAgICAgJ1RpemVuJyxcbiAgICAgICdMaW51eCcsXG4gICAgICAnTWFjIE9TIFgnLFxuICAgICAgJ01hY2ludG9zaCcsXG4gICAgICAnTWFjJyxcbiAgICAgICdXaW5kb3dzIDk4OycsXG4gICAgICAnV2luZG93cyAnXG4gICAgXSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgbGF5b3V0IGVuZ2luZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBsYXlvdXQgZW5naW5lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldExheW91dChndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCBSZWdFeHAoJ1xcXFxiJyArIChcbiAgICAgICAgICBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpXG4gICAgICAgICkgKyAnXFxcXGInLCAnaScpLmV4ZWModWEpICYmIChndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgbWFudWZhY3R1cmVyIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBvYmplY3Qgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBtYW51ZmFjdHVyZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TWFudWZhY3R1cmVyKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICAgIC8vIExvb2t1cCB0aGUgbWFudWZhY3R1cmVyIGJ5IHByb2R1Y3Qgb3Igc2NhbiB0aGUgVUEgZm9yIHRoZSBtYW51ZmFjdHVyZXIuXG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgKFxuICAgICAgICAgIHZhbHVlW3Byb2R1Y3RdIHx8XG4gICAgICAgICAgdmFsdWVbL15bYS16XSsoPzogK1thLXpdK1xcYikqL2kuZXhlYyhwcm9kdWN0KV0gfHxcbiAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHF1YWxpZnkoa2V5KSArICcoPzpcXFxcYnxcXFxcdypcXFxcZCknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICkgJiYga2V5O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGJyb3dzZXIgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBicm93c2VyIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TmFtZShndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCBSZWdFeHAoJ1xcXFxiJyArIChcbiAgICAgICAgICBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpXG4gICAgICAgICkgKyAnXFxcXGInLCAnaScpLmV4ZWModWEpICYmIChndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgT1MgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBPUyBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE9TKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnKD86L1tcXFxcZC5dK3xbIFxcXFx3Ll0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICByZXN1bHQgPSBjbGVhbnVwT1MocmVzdWx0LCBwYXR0ZXJuLCBndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBwcm9kdWN0IG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgcHJvZHVjdCBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFByb2R1Y3QoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKTtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgKHJlc3VsdCA9XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcgKlxcXFxkK1suXFxcXHdfXSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcgKlxcXFx3Ky1bXFxcXHddKicsICdpJykuZXhlYyh1YSkgfHxcbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/OjsgKig/OlthLXpdK1tfLV0pP1thLXpdK1xcXFxkK3xbXiAoKTstXSopJywgJ2knKS5leGVjKHVhKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIC8vIFNwbGl0IGJ5IGZvcndhcmQgc2xhc2ggYW5kIGFwcGVuZCBwcm9kdWN0IHZlcnNpb24gaWYgbmVlZGVkLlxuICAgICAgICAgIGlmICgocmVzdWx0ID0gU3RyaW5nKChndWVzcy5sYWJlbCAmJiAhUmVnRXhwKHBhdHRlcm4sICdpJykudGVzdChndWVzcy5sYWJlbCkpID8gZ3Vlc3MubGFiZWwgOiByZXN1bHQpLnNwbGl0KCcvJykpWzFdICYmICEvW1xcZC5dKy8udGVzdChyZXN1bHRbMF0pKSB7XG4gICAgICAgICAgICByZXN1bHRbMF0gKz0gJyAnICsgcmVzdWx0WzFdO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBDb3JyZWN0IGNoYXJhY3RlciBjYXNlIGFuZCBjbGVhbnVwIHN0cmluZy5cbiAgICAgICAgICBndWVzcyA9IGd1ZXNzLmxhYmVsIHx8IGd1ZXNzO1xuICAgICAgICAgIHJlc3VsdCA9IGZvcm1hdChyZXN1bHRbMF1cbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cChwYXR0ZXJuLCAnaScpLCBndWVzcylcbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cCgnOyAqKD86JyArIGd1ZXNzICsgJ1tfLV0pPycsICdpJyksICcgJylcbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cCgnKCcgKyBndWVzcyArICcpWy1fLl0/KFxcXFx3KScsICdpJyksICckMSAkMicpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzb2x2ZXMgdGhlIHZlcnNpb24gdXNpbmcgYW4gYXJyYXkgb2YgVUEgcGF0dGVybnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhdHRlcm5zIEFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHZlcnNpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0VmVyc2lvbihwYXR0ZXJucykge1xuICAgICAgcmV0dXJuIHJlZHVjZShwYXR0ZXJucywgZnVuY3Rpb24ocmVzdWx0LCBwYXR0ZXJuKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgKFJlZ0V4cChwYXR0ZXJuICtcbiAgICAgICAgICAnKD86LVtcXFxcZC5dKy98KD86IGZvciBbXFxcXHctXSspP1sgLy1dKShbXFxcXGQuXStbXiAoKTsvXy1dKiknLCAnaScpLmV4ZWModWEpIHx8IDApWzFdIHx8IG51bGw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgd2hlbiB0aGUgcGxhdGZvcm0gb2JqZWN0IGlzIGNvZXJjZWQgdG8gYSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbmFtZSB0b1N0cmluZ1xuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgYHBsYXRmb3JtLmRlc2NyaXB0aW9uYCBpZiBhdmFpbGFibGUsIGVsc2UgYW4gZW1wdHkgc3RyaW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvU3RyaW5nUGxhdGZvcm0oKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXNjcmlwdGlvbiB8fCAnJztcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBDb252ZXJ0IGxheW91dCB0byBhbiBhcnJheSBzbyB3ZSBjYW4gYWRkIGV4dHJhIGRldGFpbHMuXG4gICAgbGF5b3V0ICYmIChsYXlvdXQgPSBbbGF5b3V0XSk7XG5cbiAgICAvLyBEZXRlY3QgcHJvZHVjdCBuYW1lcyB0aGF0IGNvbnRhaW4gdGhlaXIgbWFudWZhY3R1cmVyJ3MgbmFtZS5cbiAgICBpZiAobWFudWZhY3R1cmVyICYmICFwcm9kdWN0KSB7XG4gICAgICBwcm9kdWN0ID0gZ2V0UHJvZHVjdChbbWFudWZhY3R1cmVyXSk7XG4gICAgfVxuICAgIC8vIENsZWFuIHVwIEdvb2dsZSBUVi5cbiAgICBpZiAoKGRhdGEgPSAvXFxiR29vZ2xlIFRWXFxiLy5leGVjKHByb2R1Y3QpKSkge1xuICAgICAgcHJvZHVjdCA9IGRhdGFbMF07XG4gICAgfVxuICAgIC8vIERldGVjdCBzaW11bGF0b3JzLlxuICAgIGlmICgvXFxiU2ltdWxhdG9yXFxiL2kudGVzdCh1YSkpIHtcbiAgICAgIHByb2R1Y3QgPSAocHJvZHVjdCA/IHByb2R1Y3QgKyAnICcgOiAnJykgKyAnU2ltdWxhdG9yJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIE1pbmkgOCsgcnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZSBvbiBpT1MuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhIE1pbmknICYmIC9cXGJPUGlPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ3J1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIE1vYmlsZSAxMS5cbiAgICBpZiAobmFtZSA9PSAnSUUnICYmIC9cXGJsaWtlIGlQaG9uZSBPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRhdGEgPSBwYXJzZSh1YS5yZXBsYWNlKC9saWtlIGlQaG9uZSBPUy8sICcnKSk7XG4gICAgICBtYW51ZmFjdHVyZXIgPSBkYXRhLm1hbnVmYWN0dXJlcjtcbiAgICAgIHByb2R1Y3QgPSBkYXRhLnByb2R1Y3Q7XG4gICAgfVxuICAgIC8vIERldGVjdCBpT1MuXG4gICAgZWxzZSBpZiAoL15pUC8udGVzdChwcm9kdWN0KSkge1xuICAgICAgbmFtZSB8fCAobmFtZSA9ICdTYWZhcmknKTtcbiAgICAgIG9zID0gJ2lPUycgKyAoKGRhdGEgPSAvIE9TIChbXFxkX10rKS9pLmV4ZWModWEpKVxuICAgICAgICA/ICcgJyArIGRhdGFbMV0ucmVwbGFjZSgvXy9nLCAnLicpXG4gICAgICAgIDogJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgS3VidW50dS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdLb25xdWVyb3InICYmICEvYnVudHUvaS50ZXN0KG9zKSkge1xuICAgICAgb3MgPSAnS3VidW50dSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBBbmRyb2lkIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKChtYW51ZmFjdHVyZXIgJiYgbWFudWZhY3R1cmVyICE9ICdHb29nbGUnICYmXG4gICAgICAgICgoL0Nocm9tZS8udGVzdChuYW1lKSAmJiAhL1xcYk1vYmlsZSBTYWZhcmlcXGIvaS50ZXN0KHVhKSkgfHwgL1xcYlZpdGFcXGIvLnRlc3QocHJvZHVjdCkpKSB8fFxuICAgICAgICAoL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpICYmIC9eQ2hyb21lLy50ZXN0KG5hbWUpICYmIC9cXGJWZXJzaW9uXFwvL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lID0gJ0FuZHJvaWQgQnJvd3Nlcic7XG4gICAgICBvcyA9IC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogJ0FuZHJvaWQnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgU2lsayBkZXNrdG9wL2FjY2VsZXJhdGVkIG1vZGVzLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1NpbGsnKSB7XG4gICAgICBpZiAoIS9cXGJNb2JpL2kudGVzdCh1YSkpIHtcbiAgICAgICAgb3MgPSAnQW5kcm9pZCc7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgfVxuICAgICAgaWYgKC9BY2NlbGVyYXRlZCAqPSAqdHJ1ZS9pLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2FjY2VsZXJhdGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBQYWxlTW9vbiBpZGVudGlmeWluZyBhcyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1BhbGVNb29uJyAmJiAoZGF0YSA9IC9cXGJGaXJlZm94XFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzIEZpcmVmb3ggJyArIGRhdGFbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBPUyBhbmQgcHJvZHVjdHMgcnVubmluZyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIChkYXRhID0gL1xcYihNb2JpbGV8VGFibGV0fFRWKVxcYi9pLmV4ZWModWEpKSkge1xuICAgICAgb3MgfHwgKG9zID0gJ0ZpcmVmb3ggT1MnKTtcbiAgICAgIHByb2R1Y3QgfHwgKHByb2R1Y3QgPSBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGZhbHNlIHBvc2l0aXZlcyBmb3IgRmlyZWZveC9TYWZhcmkuXG4gICAgZWxzZSBpZiAoIW5hbWUgfHwgKGRhdGEgPSAhL1xcYk1pbmVmaWVsZFxcYi9pLnRlc3QodWEpICYmIC9cXGIoPzpGaXJlZm94fFNhZmFyaSlcXGIvLmV4ZWMobmFtZSkpKSB7XG4gICAgICAvLyBFc2NhcGUgdGhlIGAvYCBmb3IgRmlyZWZveCAxLlxuICAgICAgaWYgKG5hbWUgJiYgIXByb2R1Y3QgJiYgL1tcXC8sXXxeW14oXSs/XFwpLy50ZXN0KHVhLnNsaWNlKHVhLmluZGV4T2YoZGF0YSArICcvJykgKyA4KSkpIHtcbiAgICAgICAgLy8gQ2xlYXIgbmFtZSBvZiBmYWxzZSBwb3NpdGl2ZXMuXG4gICAgICAgIG5hbWUgPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gUmVhc3NpZ24gYSBnZW5lcmljIG5hbWUuXG4gICAgICBpZiAoKGRhdGEgPSBwcm9kdWN0IHx8IG1hbnVmYWN0dXJlciB8fCBvcykgJiZcbiAgICAgICAgICAocHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgL1xcYig/OkFuZHJvaWR8U3ltYmlhbiBPU3xUYWJsZXQgT1N8d2ViT1MpXFxiLy50ZXN0KG9zKSkpIHtcbiAgICAgICAgbmFtZSA9IC9bYS16XSsoPzogSGF0KT8vaS5leGVjKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogZGF0YSkgKyAnIEJyb3dzZXInO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgQ2hyb21lIHZlcnNpb24gdG8gZGVzY3JpcHRpb24gZm9yIEVsZWN0cm9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0VsZWN0cm9uJyAmJiAoZGF0YSA9ICgvXFxiQ2hyb21lXFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyBkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IG5vbi1PcGVyYSAoUHJlc3RvLWJhc2VkKSB2ZXJzaW9ucyAob3JkZXIgaXMgaW1wb3J0YW50KS5cbiAgICBpZiAoIXZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSBnZXRWZXJzaW9uKFtcbiAgICAgICAgJyg/OkNsb3VkOXxDcmlPU3xDck1vfEVkZ2V8RnhpT1N8SUVNb2JpbGV8SXJvbnxPcGVyYSA/TWluaXxPUGlPU3xPUFJ8UmF2ZW58U2Ftc3VuZ0Jyb3dzZXJ8U2lsayg/IS9bXFxcXGQuXSskKSknLFxuICAgICAgICAnVmVyc2lvbicsXG4gICAgICAgIHF1YWxpZnkobmFtZSksXG4gICAgICAgICcoPzpGaXJlZm94fE1pbmVmaWVsZHxOZXRGcm9udCknXG4gICAgICBdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHN0dWJib3JuIGxheW91dCBlbmdpbmVzLlxuICAgIGlmICgoZGF0YSA9XG4gICAgICAgICAgbGF5b3V0ID09ICdpQ2FiJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID4gMyAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgIC9cXGJPcGVyYVxcYi8udGVzdChuYW1lKSAmJiAoL1xcYk9QUlxcYi8udGVzdCh1YSkgPyAnQmxpbmsnIDogJ1ByZXN0bycpIHx8XG4gICAgICAgICAgL1xcYig/Ok1pZG9yaXxOb29rfFNhZmFyaSlcXGIvaS50ZXN0KHVhKSAmJiAhL14oPzpUcmlkZW50fEVkZ2VIVE1MKSQvLnRlc3QobGF5b3V0KSAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgICFsYXlvdXQgJiYgL1xcYk1TSUVcXGIvaS50ZXN0KHVhKSAmJiAob3MgPT0gJ01hYyBPUycgPyAnVGFzbWFuJyA6ICdUcmlkZW50JykgfHxcbiAgICAgICAgICBsYXlvdXQgPT0gJ1dlYktpdCcgJiYgL1xcYlBsYXlTdGF0aW9uXFxiKD8hIFZpdGFcXGIpL2kudGVzdChuYW1lKSAmJiAnTmV0RnJvbnQnXG4gICAgICAgICkpIHtcbiAgICAgIGxheW91dCA9IFtkYXRhXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgUGhvbmUgNyBkZXNrdG9wIG1vZGUuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAoZGF0YSA9ICgvOyAqKD86WEJMV1B8WnVuZVdQKShcXGQrKS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lICcgKyAoL1xcKyQvLnRlc3QoZGF0YSkgPyBkYXRhIDogZGF0YSArICcueCcpO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDgueCBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAoL1xcYldQRGVza3RvcFxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBuYW1lID0gJ0lFIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lIDgueCc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIHZlcnNpb24gfHwgKHZlcnNpb24gPSAoL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkgfHwgMClbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgMTEgaWRlbnRpZnlpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAobmFtZSAhPSAnSUUnICYmIGxheW91dCA9PSAnVHJpZGVudCcgJiYgKGRhdGEgPSAvXFxicnY6KFtcXGQuXSspLy5leGVjKHVhKSkpIHtcbiAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzICcgKyBuYW1lICsgKHZlcnNpb24gPyAnICcgKyB2ZXJzaW9uIDogJycpKTtcbiAgICAgIH1cbiAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgdmVyc2lvbiA9IGRhdGFbMV07XG4gICAgfVxuICAgIC8vIExldmVyYWdlIGVudmlyb25tZW50IGZlYXR1cmVzLlxuICAgIGlmICh1c2VGZWF0dXJlcykge1xuICAgICAgLy8gRGV0ZWN0IHNlcnZlci1zaWRlIGVudmlyb25tZW50cy5cbiAgICAgIC8vIFJoaW5vIGhhcyBhIGdsb2JhbCBmdW5jdGlvbiB3aGlsZSBvdGhlcnMgaGF2ZSBhIGdsb2JhbCBvYmplY3QuXG4gICAgICBpZiAoaXNIb3N0VHlwZShjb250ZXh0LCAnZ2xvYmFsJykpIHtcbiAgICAgICAgaWYgKGphdmEpIHtcbiAgICAgICAgICBkYXRhID0gamF2YS5sYW5nLlN5c3RlbTtcbiAgICAgICAgICBhcmNoID0gZGF0YS5nZXRQcm9wZXJ0eSgnb3MuYXJjaCcpO1xuICAgICAgICAgIG9zID0gb3MgfHwgZGF0YS5nZXRQcm9wZXJ0eSgnb3MubmFtZScpICsgJyAnICsgZGF0YS5nZXRQcm9wZXJ0eSgnb3MudmVyc2lvbicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyaGlubykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2ZXJzaW9uID0gY29udGV4dC5yZXF1aXJlKCdyaW5nby9lbmdpbmUnKS52ZXJzaW9uLmpvaW4oJy4nKTtcbiAgICAgICAgICAgIG5hbWUgPSAnUmluZ29KUyc7XG4gICAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgICBpZiAoKGRhdGEgPSBjb250ZXh0LnN5c3RlbSkgJiYgZGF0YS5nbG9iYWwuc3lzdGVtID09IGNvbnRleHQuc3lzdGVtKSB7XG4gICAgICAgICAgICAgIG5hbWUgPSAnTmFyd2hhbCc7XG4gICAgICAgICAgICAgIG9zIHx8IChvcyA9IGRhdGFbMF0ub3MgfHwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdSaGlubyc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKFxuICAgICAgICAgIHR5cGVvZiBjb250ZXh0LnByb2Nlc3MgPT0gJ29iamVjdCcgJiYgIWNvbnRleHQucHJvY2Vzcy5icm93c2VyICYmXG4gICAgICAgICAgKGRhdGEgPSBjb250ZXh0LnByb2Nlc3MpXG4gICAgICAgICkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucyA9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLmVsZWN0cm9uID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ05vZGUgJyArIGRhdGEudmVyc2lvbnMubm9kZSk7XG4gICAgICAgICAgICAgIG5hbWUgPSAnRWxlY3Ryb24nO1xuICAgICAgICAgICAgICB2ZXJzaW9uID0gZGF0YS52ZXJzaW9ucy5lbGVjdHJvbjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMubncgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnQ2hyb21pdW0gJyArIHZlcnNpb24sICdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ05XLmpzJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMubnc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdOb2RlLmpzJztcbiAgICAgICAgICAgIGFyY2ggPSBkYXRhLmFyY2g7XG4gICAgICAgICAgICBvcyA9IGRhdGEucGxhdGZvcm07XG4gICAgICAgICAgICB2ZXJzaW9uID0gL1tcXGQuXSsvLmV4ZWMoZGF0YS52ZXJzaW9uKTtcbiAgICAgICAgICAgIHZlcnNpb24gPSB2ZXJzaW9uID8gdmVyc2lvblswXSA6IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgQWRvYmUgQUlSLlxuICAgICAgZWxzZSBpZiAoZ2V0Q2xhc3NPZigoZGF0YSA9IGNvbnRleHQucnVudGltZSkpID09IGFpclJ1bnRpbWVDbGFzcykge1xuICAgICAgICBuYW1lID0gJ0Fkb2JlIEFJUic7XG4gICAgICAgIG9zID0gZGF0YS5mbGFzaC5zeXN0ZW0uQ2FwYWJpbGl0aWVzLm9zO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IFBoYW50b21KUy5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnBoYW50b20pKSA9PSBwaGFudG9tQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdQaGFudG9tSlMnO1xuICAgICAgICB2ZXJzaW9uID0gKGRhdGEgPSBkYXRhLnZlcnNpb24gfHwgbnVsbCkgJiYgKGRhdGEubWFqb3IgKyAnLicgKyBkYXRhLm1pbm9yICsgJy4nICsgZGF0YS5wYXRjaCk7XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSUUgY29tcGF0aWJpbGl0eSBtb2Rlcy5cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBkb2MuZG9jdW1lbnRNb2RlID09ICdudW1iZXInICYmIChkYXRhID0gL1xcYlRyaWRlbnRcXC8oXFxkKykvaS5leGVjKHVhKSkpIHtcbiAgICAgICAgLy8gV2UncmUgaW4gY29tcGF0aWJpbGl0eSBtb2RlIHdoZW4gdGhlIFRyaWRlbnQgdmVyc2lvbiArIDQgZG9lc24ndFxuICAgICAgICAvLyBlcXVhbCB0aGUgZG9jdW1lbnQgbW9kZS5cbiAgICAgICAgdmVyc2lvbiA9IFt2ZXJzaW9uLCBkb2MuZG9jdW1lbnRNb2RlXTtcbiAgICAgICAgaWYgKChkYXRhID0gK2RhdGFbMV0gKyA0KSAhPSB2ZXJzaW9uWzFdKSB7XG4gICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnSUUgJyArIHZlcnNpb25bMV0gKyAnIG1vZGUnKTtcbiAgICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICcnKTtcbiAgICAgICAgICB2ZXJzaW9uWzFdID0gZGF0YTtcbiAgICAgICAgfVxuICAgICAgICB2ZXJzaW9uID0gbmFtZSA9PSAnSUUnID8gU3RyaW5nKHZlcnNpb25bMV0udG9GaXhlZCgxKSkgOiB2ZXJzaW9uWzBdO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIDExIG1hc2tpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAvXig/OkNocm9tZXxGaXJlZm94KVxcYi8udGVzdChuYW1lKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdtYXNraW5nIGFzICcgKyBuYW1lICsgJyAnICsgdmVyc2lvbik7XG4gICAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgICB2ZXJzaW9uID0gJzExLjAnO1xuICAgICAgICBsYXlvdXQgPSBbJ1RyaWRlbnQnXTtcbiAgICAgICAgb3MgPSAnV2luZG93cyc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zICYmIGZvcm1hdChvcyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBwcmVyZWxlYXNlIHBoYXNlcy5cbiAgICBpZiAodmVyc2lvbiAmJiAoZGF0YSA9XG4gICAgICAgICAgLyg/OlthYl18ZHB8cHJlfFthYl1cXGQrcHJlKSg/OlxcZCtcXCs/KT8kL2kuZXhlYyh2ZXJzaW9uKSB8fFxuICAgICAgICAgIC8oPzphbHBoYXxiZXRhKSg/OiA/XFxkKT8vaS5leGVjKHVhICsgJzsnICsgKHVzZUZlYXR1cmVzICYmIG5hdi5hcHBNaW5vclZlcnNpb24pKSB8fFxuICAgICAgICAgIC9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAnYSdcbiAgICAgICAgKSkge1xuICAgICAgcHJlcmVsZWFzZSA9IC9iL2kudGVzdChkYXRhKSA/ICdiZXRhJyA6ICdhbHBoYSc7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKFJlZ0V4cChkYXRhICsgJ1xcXFwrPyQnKSwgJycpICtcbiAgICAgICAgKHByZXJlbGVhc2UgPT0gJ2JldGEnID8gYmV0YSA6IGFscGhhKSArICgvXFxkK1xcKz8vLmV4ZWMoZGF0YSkgfHwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBNb2JpbGUuXG4gICAgaWYgKG5hbWUgPT0gJ0Zlbm5lYycgfHwgbmFtZSA9PSAnRmlyZWZveCcgJiYgL1xcYig/OkFuZHJvaWR8RmlyZWZveCBPUylcXGIvLnRlc3Qob3MpKSB7XG4gICAgICBuYW1lID0gJ0ZpcmVmb3ggTW9iaWxlJztcbiAgICB9XG4gICAgLy8gT2JzY3VyZSBNYXh0aG9uJ3MgdW5yZWxpYWJsZSB2ZXJzaW9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ01heHRob24nICYmIHZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSB2ZXJzaW9uLnJlcGxhY2UoL1xcLltcXGQuXSsvLCAnLngnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFhib3ggMzYwIGFuZCBYYm94IE9uZS5cbiAgICBlbHNlIGlmICgvXFxiWGJveFxcYi9pLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcpIHtcbiAgICAgICAgb3MgPSBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHByb2R1Y3QgPT0gJ1hib3ggMzYwJyAmJiAvXFxiSUVNb2JpbGVcXGIvLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ21vYmlsZSBtb2RlJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFkZCBtb2JpbGUgcG9zdGZpeC5cbiAgICBlbHNlIGlmICgoL14oPzpDaHJvbWV8SUV8T3BlcmEpJC8udGVzdChuYW1lKSB8fCBuYW1lICYmICFwcm9kdWN0ICYmICEvQnJvd3NlcnxNb2JpLy50ZXN0KG5hbWUpKSAmJlxuICAgICAgICAob3MgPT0gJ1dpbmRvd3MgQ0UnIHx8IC9Nb2JpL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lICs9ICcgTW9iaWxlJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIHBsYXRmb3JtIHByZXZpZXcuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnSUUnICYmIHVzZUZlYXR1cmVzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoY29udGV4dC5leHRlcm5hbCA9PT0gbnVsbCkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ3BsYXRmb3JtIHByZXZpZXcnKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2VtYmVkZGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBCbGFja0JlcnJ5IE9TIHZlcnNpb24uXG4gICAgLy8gaHR0cDovL2RvY3MuYmxhY2tiZXJyeS5jb20vZW4vZGV2ZWxvcGVycy9kZWxpdmVyYWJsZXMvMTgxNjkvSFRUUF9oZWFkZXJzX3NlbnRfYnlfQkJfQnJvd3Nlcl8xMjM0OTExXzExLmpzcFxuICAgIGVsc2UgaWYgKCgvXFxiQmxhY2tCZXJyeVxcYi8udGVzdChwcm9kdWN0KSB8fCAvXFxiQkIxMFxcYi8udGVzdCh1YSkpICYmIChkYXRhID1cbiAgICAgICAgICAoUmVnRXhwKHByb2R1Y3QucmVwbGFjZSgvICsvZywgJyAqJykgKyAnLyhbLlxcXFxkXSspJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fFxuICAgICAgICAgIHZlcnNpb25cbiAgICAgICAgKSkge1xuICAgICAgZGF0YSA9IFtkYXRhLCAvQkIxMC8udGVzdCh1YSldO1xuICAgICAgb3MgPSAoZGF0YVsxXSA/IChwcm9kdWN0ID0gbnVsbCwgbWFudWZhY3R1cmVyID0gJ0JsYWNrQmVycnknKSA6ICdEZXZpY2UgU29mdHdhcmUnKSArICcgJyArIGRhdGFbMF07XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGlkZW50aWZ5aW5nL21hc2tpbmcgaXRzZWxmIGFzIGFub3RoZXIgYnJvd3Nlci5cbiAgICAvLyBodHRwOi8vd3d3Lm9wZXJhLmNvbS9zdXBwb3J0L2tiL3ZpZXcvODQzL1xuICAgIGVsc2UgaWYgKHRoaXMgIT0gZm9yT3duICYmIHByb2R1Y3QgIT0gJ1dpaScgJiYgKFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiBvcGVyYSkgfHxcbiAgICAgICAgICAoL09wZXJhLy50ZXN0KG5hbWUpICYmIC9cXGIoPzpNU0lFfEZpcmVmb3gpXFxiL2kudGVzdCh1YSkpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGJPUyBYICg/OlxcZCtcXC4pezIsfS8udGVzdChvcykpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0lFJyAmJiAoXG4gICAgICAgICAgICAob3MgJiYgIS9eV2luLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gNS41KSB8fFxuICAgICAgICAgICAgL1xcYldpbmRvd3MgWFBcXGIvLnRlc3Qob3MpICYmIHZlcnNpb24gPiA4IHx8XG4gICAgICAgICAgICB2ZXJzaW9uID09IDggJiYgIS9cXGJUcmlkZW50XFxiLy50ZXN0KHVhKVxuICAgICAgICAgICkpXG4gICAgICAgICkgJiYgIXJlT3BlcmEudGVzdCgoZGF0YSA9IHBhcnNlLmNhbGwoZm9yT3duLCB1YS5yZXBsYWNlKHJlT3BlcmEsICcnKSArICc7JykpKSAmJiBkYXRhLm5hbWUpIHtcbiAgICAgIC8vIFdoZW4gXCJpZGVudGlmeWluZ1wiLCB0aGUgVUEgY29udGFpbnMgYm90aCBPcGVyYSBhbmQgdGhlIG90aGVyIGJyb3dzZXIncyBuYW1lLlxuICAgICAgZGF0YSA9ICdpbmcgYXMgJyArIGRhdGEubmFtZSArICgoZGF0YSA9IGRhdGEudmVyc2lvbikgPyAnICcgKyBkYXRhIDogJycpO1xuICAgICAgaWYgKHJlT3BlcmEudGVzdChuYW1lKSkge1xuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpICYmIG9zID09ICdNYWMgT1MnKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGRhdGEgPSAnaWRlbnRpZnknICsgZGF0YTtcbiAgICAgIH1cbiAgICAgIC8vIFdoZW4gXCJtYXNraW5nXCIsIHRoZSBVQSBjb250YWlucyBvbmx5IHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGVsc2Uge1xuICAgICAgICBkYXRhID0gJ21hc2snICsgZGF0YTtcbiAgICAgICAgaWYgKG9wZXJhQ2xhc3MpIHtcbiAgICAgICAgICBuYW1lID0gZm9ybWF0KG9wZXJhQ2xhc3MucmVwbGFjZSgvKFthLXpdKShbQS1aXSkvZywgJyQxICQyJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5hbWUgPSAnT3BlcmEnO1xuICAgICAgICB9XG4gICAgICAgIGlmICgvXFxiSUVcXGIvLnRlc3QoZGF0YSkpIHtcbiAgICAgICAgICBvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF1c2VGZWF0dXJlcykge1xuICAgICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsYXlvdXQgPSBbJ1ByZXN0byddO1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdlYktpdCBOaWdodGx5IGFuZCBhcHByb3hpbWF0ZSBDaHJvbWUvU2FmYXJpIHZlcnNpb25zLlxuICAgIGlmICgoZGF0YSA9ICgvXFxiQXBwbGVXZWJLaXRcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAvLyBDb3JyZWN0IGJ1aWxkIG51bWJlciBmb3IgbnVtZXJpYyBjb21wYXJpc29uLlxuICAgICAgLy8gKGUuZy4gXCI1MzIuNVwiIGJlY29tZXMgXCI1MzIuMDVcIilcbiAgICAgIGRhdGEgPSBbcGFyc2VGbG9hdChkYXRhLnJlcGxhY2UoL1xcLihcXGQpJC8sICcuMCQxJykpLCBkYXRhXTtcbiAgICAgIC8vIE5pZ2h0bHkgYnVpbGRzIGFyZSBwb3N0Zml4ZWQgd2l0aCBhIFwiK1wiLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgZGF0YVsxXS5zbGljZSgtMSkgPT0gJysnKSB7XG4gICAgICAgIG5hbWUgPSAnV2ViS2l0IE5pZ2h0bHknO1xuICAgICAgICBwcmVyZWxlYXNlID0gJ2FscGhhJztcbiAgICAgICAgdmVyc2lvbiA9IGRhdGFbMV0uc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuICAgICAgLy8gQ2xlYXIgaW5jb3JyZWN0IGJyb3dzZXIgdmVyc2lvbnMuXG4gICAgICBlbHNlIGlmICh2ZXJzaW9uID09IGRhdGFbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uID09IChkYXRhWzJdID0gKC9cXGJTYWZhcmlcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHRoZSBmdWxsIENocm9tZSB2ZXJzaW9uIHdoZW4gYXZhaWxhYmxlLlxuICAgICAgZGF0YVsxXSA9ICgvXFxiQ2hyb21lXFwvKFtcXGQuXSspL2kuZXhlYyh1YSkgfHwgMClbMV07XG4gICAgICAvLyBEZXRlY3QgQmxpbmsgbGF5b3V0IGVuZ2luZS5cbiAgICAgIGlmIChkYXRhWzBdID09IDUzNy4zNiAmJiBkYXRhWzJdID09IDUzNy4zNiAmJiBwYXJzZUZsb2F0KGRhdGFbMV0pID49IDI4ICYmIGxheW91dCA9PSAnV2ViS2l0Jykge1xuICAgICAgICBsYXlvdXQgPSBbJ0JsaW5rJ107XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSmF2YVNjcmlwdENvcmUuXG4gICAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY3Njg0NzQvaG93LWNhbi1pLWRldGVjdC13aGljaC1qYXZhc2NyaXB0LWVuZ2luZS12OC1vci1qc2MtaXMtdXNlZC1hdC1ydW50aW1lLWluLWFuZHJvaVxuICAgICAgaWYgKCF1c2VGZWF0dXJlcyB8fCAoIWxpa2VDaHJvbWUgJiYgIWRhdGFbMV0pKSB7XG4gICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJ2xpa2UgU2FmYXJpJyk7XG4gICAgICAgIGRhdGEgPSAoZGF0YSA9IGRhdGFbMF0sIGRhdGEgPCA0MDAgPyAxIDogZGF0YSA8IDUwMCA/IDIgOiBkYXRhIDwgNTI2ID8gMyA6IGRhdGEgPCA1MzMgPyA0IDogZGF0YSA8IDUzNCA/ICc0KycgOiBkYXRhIDwgNTM1ID8gNSA6IGRhdGEgPCA1MzcgPyA2IDogZGF0YSA8IDUzOCA/IDcgOiBkYXRhIDwgNjAxID8gOCA6ICc4Jyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIENocm9tZScpO1xuICAgICAgICBkYXRhID0gZGF0YVsxXSB8fCAoZGF0YSA9IGRhdGFbMF0sIGRhdGEgPCA1MzAgPyAxIDogZGF0YSA8IDUzMiA/IDIgOiBkYXRhIDwgNTMyLjA1ID8gMyA6IGRhdGEgPCA1MzMgPyA0IDogZGF0YSA8IDUzNC4wMyA/IDUgOiBkYXRhIDwgNTM0LjA3ID8gNiA6IGRhdGEgPCA1MzQuMTAgPyA3IDogZGF0YSA8IDUzNC4xMyA/IDggOiBkYXRhIDwgNTM0LjE2ID8gOSA6IGRhdGEgPCA1MzQuMjQgPyAxMCA6IGRhdGEgPCA1MzQuMzAgPyAxMSA6IGRhdGEgPCA1MzUuMDEgPyAxMiA6IGRhdGEgPCA1MzUuMDIgPyAnMTMrJyA6IGRhdGEgPCA1MzUuMDcgPyAxNSA6IGRhdGEgPCA1MzUuMTEgPyAxNiA6IGRhdGEgPCA1MzUuMTkgPyAxNyA6IGRhdGEgPCA1MzYuMDUgPyAxOCA6IGRhdGEgPCA1MzYuMTAgPyAxOSA6IGRhdGEgPCA1MzcuMDEgPyAyMCA6IGRhdGEgPCA1MzcuMTEgPyAnMjErJyA6IGRhdGEgPCA1MzcuMTMgPyAyMyA6IGRhdGEgPCA1MzcuMTggPyAyNCA6IGRhdGEgPCA1MzcuMjQgPyAyNSA6IGRhdGEgPCA1MzcuMzYgPyAyNiA6IGxheW91dCAhPSAnQmxpbmsnID8gJzI3JyA6ICcyOCcpO1xuICAgICAgfVxuICAgICAgLy8gQWRkIHRoZSBwb3N0Zml4IG9mIFwiLnhcIiBvciBcIitcIiBmb3IgYXBwcm94aW1hdGUgdmVyc2lvbnMuXG4gICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSArPSAnICcgKyAoZGF0YSArPSB0eXBlb2YgZGF0YSA9PSAnbnVtYmVyJyA/ICcueCcgOiAvWy4rXS8udGVzdChkYXRhKSA/ICcnIDogJysnKSk7XG4gICAgICAvLyBPYnNjdXJlIHZlcnNpb24gZm9yIHNvbWUgU2FmYXJpIDEtMiByZWxlYXNlcy5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmICghdmVyc2lvbiB8fCBwYXJzZUludCh2ZXJzaW9uKSA+IDQ1KSkge1xuICAgICAgICB2ZXJzaW9uID0gZGF0YTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGRlc2t0b3AgbW9kZXMuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhJyAmJiAgKGRhdGEgPSAvXFxiemJvdnx6dmF2JC8uZXhlYyhvcykpKSB7XG4gICAgICBuYW1lICs9ICcgJztcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgaWYgKGRhdGEgPT0gJ3p2YXYnKSB7XG4gICAgICAgIG5hbWUgKz0gJ01pbmknO1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5hbWUgKz0gJ01vYmlsZSc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhICsgJyQnKSwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQ2hyb21lIGRlc2t0b3AgbW9kZS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTYWZhcmknICYmIC9cXGJDaHJvbWVcXGIvLmV4ZWMobGF5b3V0ICYmIGxheW91dFsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgbmFtZSA9ICdDaHJvbWUgTW9iaWxlJztcbiAgICAgIHZlcnNpb24gPSBudWxsO1xuXG4gICAgICBpZiAoL1xcYk9TIFhcXGIvLnRlc3Qob3MpKSB7XG4gICAgICAgIG1hbnVmYWN0dXJlciA9ICdBcHBsZSc7XG4gICAgICAgIG9zID0gJ2lPUyA0LjMrJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gU3RyaXAgaW5jb3JyZWN0IE9TIHZlcnNpb25zLlxuICAgIGlmICh2ZXJzaW9uICYmIHZlcnNpb24uaW5kZXhPZigoZGF0YSA9IC9bXFxkLl0rJC8uZXhlYyhvcykpKSA9PSAwICYmXG4gICAgICAgIHVhLmluZGV4T2YoJy8nICsgZGF0YSArICctJykgPiAtMSkge1xuICAgICAgb3MgPSB0cmltKG9zLnJlcGxhY2UoZGF0YSwgJycpKTtcbiAgICB9XG4gICAgLy8gQWRkIGxheW91dCBlbmdpbmUuXG4gICAgaWYgKGxheW91dCAmJiAhL1xcYig/OkF2YW50fE5vb2spXFxiLy50ZXN0KG5hbWUpICYmIChcbiAgICAgICAgL0Jyb3dzZXJ8THVuYXNjYXBlfE1heHRob24vLnRlc3QobmFtZSkgfHxcbiAgICAgICAgbmFtZSAhPSAnU2FmYXJpJyAmJiAvXmlPUy8udGVzdChvcykgJiYgL1xcYlNhZmFyaVxcYi8udGVzdChsYXlvdXRbMV0pIHx8XG4gICAgICAgIC9eKD86QWRvYmV8QXJvcmF8QnJlYWNofE1pZG9yaXxPcGVyYXxQaGFudG9tfFJla29ucXxSb2NrfFNhbXN1bmcgSW50ZXJuZXR8U2xlaXBuaXJ8V2ViKS8udGVzdChuYW1lKSAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICAvLyBEb24ndCBhZGQgbGF5b3V0IGRldGFpbHMgdG8gZGVzY3JpcHRpb24gaWYgdGhleSBhcmUgZmFsc2V5LlxuICAgICAgKGRhdGEgPSBsYXlvdXRbbGF5b3V0Lmxlbmd0aCAtIDFdKSAmJiBkZXNjcmlwdGlvbi5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICAvLyBDb21iaW5lIGNvbnRleHR1YWwgaW5mb3JtYXRpb24uXG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgZGVzY3JpcHRpb24gPSBbJygnICsgZGVzY3JpcHRpb24uam9pbignOyAnKSArICcpJ107XG4gICAgfVxuICAgIC8vIEFwcGVuZCBtYW51ZmFjdHVyZXIgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiBwcm9kdWN0ICYmIHByb2R1Y3QuaW5kZXhPZihtYW51ZmFjdHVyZXIpIDwgMCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnb24gJyArIG1hbnVmYWN0dXJlcik7XG4gICAgfVxuICAgIC8vIEFwcGVuZCBwcm9kdWN0IHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChwcm9kdWN0KSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCgvXm9uIC8udGVzdChkZXNjcmlwdGlvbltkZXNjcmlwdGlvbi5sZW5ndGggLSAxXSkgPyAnJyA6ICdvbiAnKSArIHByb2R1Y3QpO1xuICAgIH1cbiAgICAvLyBQYXJzZSB0aGUgT1MgaW50byBhbiBvYmplY3QuXG4gICAgaWYgKG9zKSB7XG4gICAgICBkYXRhID0gLyAoW1xcZC4rXSspJC8uZXhlYyhvcyk7XG4gICAgICBpc1NwZWNpYWxDYXNlZE9TID0gZGF0YSAmJiBvcy5jaGFyQXQob3MubGVuZ3RoIC0gZGF0YVswXS5sZW5ndGggLSAxKSA9PSAnLyc7XG4gICAgICBvcyA9IHtcbiAgICAgICAgJ2FyY2hpdGVjdHVyZSc6IDMyLFxuICAgICAgICAnZmFtaWx5JzogKGRhdGEgJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gb3MucmVwbGFjZShkYXRhWzBdLCAnJykgOiBvcyxcbiAgICAgICAgJ3ZlcnNpb24nOiBkYXRhID8gZGF0YVsxXSA6IG51bGwsXG4gICAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciB2ZXJzaW9uID0gdGhpcy52ZXJzaW9uO1xuICAgICAgICAgIHJldHVybiB0aGlzLmZhbWlseSArICgodmVyc2lvbiAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyAnICcgKyB2ZXJzaW9uIDogJycpICsgKHRoaXMuYXJjaGl0ZWN0dXJlID09IDY0ID8gJyA2NC1iaXQnIDogJycpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBBZGQgYnJvd3Nlci9PUyBhcmNoaXRlY3R1cmUuXG4gICAgaWYgKChkYXRhID0gL1xcYig/OkFNRHxJQXxXaW58V09XfHg4Nl98eCk2NFxcYi9pLmV4ZWMoYXJjaCkpICYmICEvXFxiaTY4NlxcYi9pLnRlc3QoYXJjaCkpIHtcbiAgICAgIGlmIChvcykge1xuICAgICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICAgICAgb3MuZmFtaWx5ID0gb3MuZmFtaWx5LnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhKSwgJycpO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICAgIG5hbWUgJiYgKC9cXGJXT1c2NFxcYi9pLnRlc3QodWEpIHx8XG4gICAgICAgICAgKHVzZUZlYXR1cmVzICYmIC9cXHcoPzo4NnwzMikkLy50ZXN0KG5hdi5jcHVDbGFzcyB8fCBuYXYucGxhdGZvcm0pICYmICEvXFxiV2luNjQ7IHg2NFxcYi9pLnRlc3QodWEpKSlcbiAgICAgICkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCczMi1iaXQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQ2hyb21lIDM5IGFuZCBhYm92ZSBvbiBPUyBYIGlzIGFsd2F5cyA2NC1iaXQuXG4gICAgZWxzZSBpZiAoXG4gICAgICAgIG9zICYmIC9eT1MgWC8udGVzdChvcy5mYW1pbHkpICYmXG4gICAgICAgIG5hbWUgPT0gJ0Nocm9tZScgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+PSAzOVxuICAgICkge1xuICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgfVxuXG4gICAgdWEgfHwgKHVhID0gbnVsbCk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gb2JqZWN0LlxuICAgICAqXG4gICAgICogQG5hbWUgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICB2YXIgcGxhdGZvcm0gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBkZXNjcmlwdGlvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyJ3MgbGF5b3V0IGVuZ2luZS5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBsYXlvdXQgZW5naW5lcyBpbmNsdWRlOlxuICAgICAqIFwiQmxpbmtcIiwgXCJFZGdlSFRNTFwiLCBcIkdlY2tvXCIsIFwiVHJpZGVudFwiIGFuZCBcIldlYktpdFwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmxheW91dCA9IGxheW91dCAmJiBsYXlvdXRbMF07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCdzIG1hbnVmYWN0dXJlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIG1hbnVmYWN0dXJlcnMgaW5jbHVkZTpcbiAgICAgKiBcIkFwcGxlXCIsIFwiQXJjaG9zXCIsIFwiQW1hem9uXCIsIFwiQXN1c1wiLCBcIkJhcm5lcyAmIE5vYmxlXCIsIFwiQmxhY2tCZXJyeVwiLFxuICAgICAqIFwiR29vZ2xlXCIsIFwiSFBcIiwgXCJIVENcIiwgXCJMR1wiLCBcIk1pY3Jvc29mdFwiLCBcIk1vdG9yb2xhXCIsIFwiTmludGVuZG9cIixcbiAgICAgKiBcIk5va2lhXCIsIFwiU2Ftc3VuZ1wiIGFuZCBcIlNvbnlcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5tYW51ZmFjdHVyZXIgPSBtYW51ZmFjdHVyZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3Nlci9lbnZpcm9ubWVudC5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBicm93c2VyIG5hbWVzIGluY2x1ZGU6XG4gICAgICogXCJDaHJvbWVcIiwgXCJFbGVjdHJvblwiLCBcIkZpcmVmb3hcIiwgXCJGaXJlZm94IGZvciBpT1NcIiwgXCJJRVwiLFxuICAgICAqIFwiTWljcm9zb2Z0IEVkZ2VcIiwgXCJQaGFudG9tSlNcIiwgXCJTYWZhcmlcIiwgXCJTZWFNb25rZXlcIiwgXCJTaWxrXCIsXG4gICAgICogXCJPcGVyYSBNaW5pXCIgYW5kIFwiT3BlcmFcIlxuICAgICAqXG4gICAgICogTW9iaWxlIHZlcnNpb25zIG9mIHNvbWUgYnJvd3NlcnMgaGF2ZSBcIk1vYmlsZVwiIGFwcGVuZGVkIHRvIHRoZWlyIG5hbWU6XG4gICAgICogZWcuIFwiQ2hyb21lIE1vYmlsZVwiLCBcIkZpcmVmb3ggTW9iaWxlXCIsIFwiSUUgTW9iaWxlXCIgYW5kIFwiT3BlcmEgTW9iaWxlXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubmFtZSA9IG5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYWxwaGEvYmV0YSByZWxlYXNlIGluZGljYXRvci5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJlcmVsZWFzZSA9IHByZXJlbGVhc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCBob3N0aW5nIHRoZSBicm93c2VyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIHByb2R1Y3RzIGluY2x1ZGU6XG4gICAgICpcbiAgICAgKiBcIkJsYWNrQmVycnlcIiwgXCJHYWxheHkgUzRcIiwgXCJMdW1pYVwiLCBcImlQYWRcIiwgXCJpUG9kXCIsIFwiaVBob25lXCIsIFwiS2luZGxlXCIsXG4gICAgICogXCJLaW5kbGUgRmlyZVwiLCBcIk5leHVzXCIsIFwiTm9va1wiLCBcIlBsYXlCb29rXCIsIFwiVG91Y2hQYWRcIiBhbmQgXCJUcmFuc2Zvcm1lclwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByb2R1Y3QgPSBwcm9kdWN0O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIncyB1c2VyIGFnZW50IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udWEgPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyL2Vudmlyb25tZW50IHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnZlcnNpb24gPSBuYW1lICYmIHZlcnNpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgb3BlcmF0aW5nIHN5c3RlbS5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm9zID0gb3MgfHwge1xuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlIHRoZSBPUyBpcyBidWlsdCBmb3IuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBudW1iZXJ8bnVsbFxuICAgICAgICovXG4gICAgICAnYXJjaGl0ZWN0dXJlJzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgZmFtaWx5IG9mIHRoZSBPUy5cbiAgICAgICAqXG4gICAgICAgKiBDb21tb24gdmFsdWVzIGluY2x1ZGU6XG4gICAgICAgKiBcIldpbmRvd3NcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IFIyIC8gN1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggLyBWaXN0YVwiLFxuICAgICAgICogXCJXaW5kb3dzIFhQXCIsIFwiT1MgWFwiLCBcIlVidW50dVwiLCBcIkRlYmlhblwiLCBcIkZlZG9yYVwiLCBcIlJlZCBIYXRcIiwgXCJTdVNFXCIsXG4gICAgICAgKiBcIkFuZHJvaWRcIiwgXCJpT1NcIiBhbmQgXCJXaW5kb3dzIFBob25lXCJcbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICAgKi9cbiAgICAgICdmYW1pbHknOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSB2ZXJzaW9uIG9mIHRoZSBPUy5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICAgKi9cbiAgICAgICd2ZXJzaW9uJzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBSZXR1cm5zIHRoZSBPUyBzdHJpbmcuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgT1Mgc3RyaW5nLlxuICAgICAgICovXG4gICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHsgcmV0dXJuICdudWxsJzsgfVxuICAgIH07XG5cbiAgICBwbGF0Zm9ybS5wYXJzZSA9IHBhcnNlO1xuICAgIHBsYXRmb3JtLnRvU3RyaW5nID0gdG9TdHJpbmdQbGF0Zm9ybTtcblxuICAgIGlmIChwbGF0Zm9ybS52ZXJzaW9uKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KHZlcnNpb24pO1xuICAgIH1cbiAgICBpZiAocGxhdGZvcm0ubmFtZSkge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdChuYW1lKTtcbiAgICB9XG4gICAgaWYgKG9zICYmIG5hbWUgJiYgIShvcyA9PSBTdHJpbmcob3MpLnNwbGl0KCcgJylbMF0gJiYgKG9zID09IG5hbWUuc3BsaXQoJyAnKVswXSB8fCBwcm9kdWN0KSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2gocHJvZHVjdCA/ICcoJyArIG9zICsgJyknIDogJ29uICcgKyBvcyk7XG4gICAgfVxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gZGVzY3JpcHRpb24uam9pbignICcpO1xuICAgIH1cbiAgICByZXR1cm4gcGxhdGZvcm07XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvLyBFeHBvcnQgcGxhdGZvcm0uXG4gIHZhciBwbGF0Zm9ybSA9IHBhcnNlKCk7XG5cbiAgLy8gU29tZSBBTUQgYnVpbGQgb3B0aW1pemVycywgbGlrZSByLmpzLCBjaGVjayBmb3IgY29uZGl0aW9uIHBhdHRlcm5zIGxpa2UgdGhlIGZvbGxvd2luZzpcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PSAnb2JqZWN0JyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gRXhwb3NlIHBsYXRmb3JtIG9uIHRoZSBnbG9iYWwgb2JqZWN0IHRvIHByZXZlbnQgZXJyb3JzIHdoZW4gcGxhdGZvcm0gaXNcbiAgICAvLyBsb2FkZWQgYnkgYSBzY3JpcHQgdGFnIGluIHRoZSBwcmVzZW5jZSBvZiBhbiBBTUQgbG9hZGVyLlxuICAgIC8vIFNlZSBodHRwOi8vcmVxdWlyZWpzLm9yZy9kb2NzL2Vycm9ycy5odG1sI21pc21hdGNoIGZvciBtb3JlIGRldGFpbHMuXG4gICAgcm9vdC5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuXG4gICAgLy8gRGVmaW5lIGFzIGFuIGFub255bW91cyBtb2R1bGUgc28gcGxhdGZvcm0gY2FuIGJlIGFsaWFzZWQgdGhyb3VnaCBwYXRoIG1hcHBpbmcuXG4gICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHBsYXRmb3JtO1xuICAgIH0pO1xuICB9XG4gIC8vIENoZWNrIGZvciBgZXhwb3J0c2AgYWZ0ZXIgYGRlZmluZWAgaW4gY2FzZSBhIGJ1aWxkIG9wdGltaXplciBhZGRzIGFuIGBleHBvcnRzYCBvYmplY3QuXG4gIGVsc2UgaWYgKGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUpIHtcbiAgICAvLyBFeHBvcnQgZm9yIENvbW1vbkpTIHN1cHBvcnQuXG4gICAgZm9yT3duKHBsYXRmb3JtLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICBmcmVlRXhwb3J0c1trZXldID0gdmFsdWU7XG4gICAgfSk7XG4gIH1cbiAgZWxzZSB7XG4gICAgLy8gRXhwb3J0IHRvIHRoZSBnbG9iYWwgb2JqZWN0LlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcbiAgfVxufS5jYWxsKHRoaXMpKTtcbiIsInZhciBncmFtbWFyID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIHY6IFt7XG4gICAgICBuYW1lOiAndmVyc2lvbicsXG4gICAgICByZWc6IC9eKFxcZCopJC9cbiAgfV0sXG4gIG86IFt7IC8vbz0tIDIwNTE4IDAgSU4gSVA0IDIwMy4wLjExMy4xXG4gICAgLy8gTkI6IHNlc3Npb25JZCB3aWxsIGJlIGEgU3RyaW5nIGluIG1vc3QgY2FzZXMgYmVjYXVzZSBpdCBpcyBodWdlXG4gICAgbmFtZTogJ29yaWdpbicsXG4gICAgcmVnOiAvXihcXFMqKSAoXFxkKikgKFxcZCopIChcXFMqKSBJUChcXGQpIChcXFMqKS8sXG4gICAgbmFtZXM6IFsndXNlcm5hbWUnLCAnc2Vzc2lvbklkJywgJ3Nlc3Npb25WZXJzaW9uJywgJ25ldFR5cGUnLCAnaXBWZXInLCAnYWRkcmVzcyddLFxuICAgIGZvcm1hdDogXCIlcyAlcyAlZCAlcyBJUCVkICVzXCJcbiAgfV0sXG4gIC8vIGRlZmF1bHQgcGFyc2luZyBvZiB0aGVzZSBvbmx5ICh0aG91Z2ggc29tZSBvZiB0aGVzZSBmZWVsIG91dGRhdGVkKVxuICBzOiBbeyBuYW1lOiAnbmFtZScgfV0sXG4gIGk6IFt7IG5hbWU6ICdkZXNjcmlwdGlvbicgfV0sXG4gIHU6IFt7IG5hbWU6ICd1cmknIH1dLFxuICBlOiBbeyBuYW1lOiAnZW1haWwnIH1dLFxuICBwOiBbeyBuYW1lOiAncGhvbmUnIH1dLFxuICB6OiBbeyBuYW1lOiAndGltZXpvbmVzJyB9XSwgLy8gVE9ETzogdGhpcyBvbmUgY2FuIGFjdHVhbGx5IGJlIHBhcnNlZCBwcm9wZXJseS4uXG4gIHI6IFt7IG5hbWU6ICdyZXBlYXRzJyB9XSwgICAvLyBUT0RPOiB0aGlzIG9uZSBjYW4gYWxzbyBiZSBwYXJzZWQgcHJvcGVybHlcbiAgLy9rOiBbe31dLCAvLyBvdXRkYXRlZCB0aGluZyBpZ25vcmVkXG4gIHQ6IFt7IC8vdD0wIDBcbiAgICBuYW1lOiAndGltaW5nJyxcbiAgICByZWc6IC9eKFxcZCopIChcXGQqKS8sXG4gICAgbmFtZXM6IFsnc3RhcnQnLCAnc3RvcCddLFxuICAgIGZvcm1hdDogXCIlZCAlZFwiXG4gIH1dLFxuICBjOiBbeyAvL2M9SU4gSVA0IDEwLjQ3LjE5Ny4yNlxuICAgICAgbmFtZTogJ2Nvbm5lY3Rpb24nLFxuICAgICAgcmVnOiAvXklOIElQKFxcZCkgKFxcUyopLyxcbiAgICAgIG5hbWVzOiBbJ3ZlcnNpb24nLCAnaXAnXSxcbiAgICAgIGZvcm1hdDogXCJJTiBJUCVkICVzXCJcbiAgfV0sXG4gIGI6IFt7IC8vYj1BUzo0MDAwXG4gICAgICBwdXNoOiAnYmFuZHdpZHRoJyxcbiAgICAgIHJlZzogL14oVElBU3xBU3xDVHxSUnxSUyk6KFxcZCopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbGltaXQnXSxcbiAgICAgIGZvcm1hdDogXCIlczolc1wiXG4gIH1dLFxuICBtOiBbeyAvL209dmlkZW8gNTE3NDQgUlRQL0FWUCAxMjYgOTcgOTggMzQgMzFcbiAgICAgIC8vIE5COiBzcGVjaWFsIC0gcHVzaGVzIHRvIHNlc3Npb25cbiAgICAgIC8vIFRPRE86IHJ0cC9mbXRwIHNob3VsZCBiZSBmaWx0ZXJlZCBieSB0aGUgcGF5bG9hZHMgZm91bmQgaGVyZT9cbiAgICAgIHJlZzogL14oXFx3KikgKFxcZCopIChbXFx3XFwvXSopKD86ICguKikpPy8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ3BvcnQnLCAncHJvdG9jb2wnLCAncGF5bG9hZHMnXSxcbiAgICAgIGZvcm1hdDogXCIlcyAlZCAlcyAlc1wiXG4gIH1dLFxuICBhOiBbXG4gICAgeyAvL2E9cnRwbWFwOjExMCBvcHVzLzQ4MDAwLzJcbiAgICAgIHB1c2g6ICdydHAnLFxuICAgICAgcmVnOiAvXnJ0cG1hcDooXFxkKikgKFtcXHdcXC1dKikoPzpcXHMqXFwvKFxcZCopKD86XFxzKlxcLyhcXFMqKSk/KT8vLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb2RlYycsICdyYXRlJywgJ2VuY29kaW5nJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5lbmNvZGluZykgP1xuICAgICAgICAgIFwicnRwbWFwOiVkICVzLyVzLyVzXCI6XG4gICAgICAgICAgby5yYXRlID9cbiAgICAgICAgICBcInJ0cG1hcDolZCAlcy8lc1wiOlxuICAgICAgICAgIFwicnRwbWFwOiVkICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Zm10cDoxMDggcHJvZmlsZS1sZXZlbC1pZD0yNDtvYmplY3Q9MjM7Yml0cmF0ZT02NDAwMFxuICAgICAgLy9hPWZtdHA6MTExIG1pbnB0aW1lPTEwOyB1c2VpbmJhbmRmZWM9MVxuICAgICAgcHVzaDogJ2ZtdHAnLFxuICAgICAgcmVnOiAvXmZtdHA6KFxcZCopIChbXFxTfCBdKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb25maWcnXSxcbiAgICAgIGZvcm1hdDogXCJmbXRwOiVkICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWNvbnRyb2w6c3RyZWFtaWQ9MFxuICAgICAgICBuYW1lOiAnY29udHJvbCcsXG4gICAgICAgIHJlZzogL15jb250cm9sOiguKikvLFxuICAgICAgICBmb3JtYXQ6IFwiY29udHJvbDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwOjY1MTc5IElOIElQNCAxOTMuODQuNzcuMTk0XG4gICAgICBuYW1lOiAncnRjcCcsXG4gICAgICByZWc6IC9ecnRjcDooXFxkKikoPzogKFxcUyopIElQKFxcZCkgKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsncG9ydCcsICduZXRUeXBlJywgJ2lwVmVyJywgJ2FkZHJlc3MnXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmFkZHJlc3MgIT0gbnVsbCkgP1xuICAgICAgICAgIFwicnRjcDolZCAlcyBJUCVkICVzXCI6XG4gICAgICAgICAgXCJydGNwOiVkXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IHRyci1pbnQgMTAwXG4gICAgICBwdXNoOiAncnRjcEZiVHJySW50JyxcbiAgICAgIHJlZzogL15ydGNwLWZiOihcXCp8XFxkKikgdHJyLWludCAoXFxkKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICd2YWx1ZSddLFxuICAgICAgZm9ybWF0OiBcInJ0Y3AtZmI6JWQgdHJyLWludCAlZFwiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IG5hY2sgcnBzaVxuICAgICAgcHVzaDogJ3J0Y3BGYicsXG4gICAgICByZWc6IC9ecnRjcC1mYjooXFwqfFxcZCopIChbXFx3LV9dKikoPzogKFtcXHctX10qKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAndHlwZScsICdzdWJ0eXBlJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zdWJ0eXBlICE9IG51bGwpID9cbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXNcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPWV4dG1hcDoyIHVybjppZXRmOnBhcmFtczpydHAtaGRyZXh0OnRvZmZzZXRcbiAgICAgIC8vYT1leHRtYXA6MS9yZWN2b25seSBVUkktZ3BzLXN0cmluZ1xuICAgICAgcHVzaDogJ2V4dCcsXG4gICAgICByZWc6IC9eZXh0bWFwOihbXFx3X1xcL10qKSAoXFxTKikoPzogKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsndmFsdWUnLCAndXJpJywgJ2NvbmZpZyddLCAvLyB2YWx1ZSBtYXkgaW5jbHVkZSBcIi9kaXJlY3Rpb25cIiBzdWZmaXhcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmNvbmZpZyAhPSBudWxsKSA/XG4gICAgICAgICAgXCJleHRtYXA6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcImV4dG1hcDolcyAlc1wiO1xuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAgLy9hPWNyeXB0bzoxIEFFU19DTV8xMjhfSE1BQ19TSEExXzgwIGlubGluZTpQUzF1UUNWZWVDRkNhblZtY2prcFB5d2pOV2hjWUQwbVhYdHhhVkJSfDJeMjB8MTozMlxuICAgICAgcHVzaDogJ2NyeXB0bycsXG4gICAgICByZWc6IC9eY3J5cHRvOihcXGQqKSAoW1xcd19dKikgKFxcUyopKD86IChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2lkJywgJ3N1aXRlJywgJ2NvbmZpZycsICdzZXNzaW9uQ29uZmlnJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zZXNzaW9uQ29uZmlnICE9IG51bGwpID9cbiAgICAgICAgICBcImNyeXB0bzolZCAlcyAlcyAlc1wiOlxuICAgICAgICAgIFwiY3J5cHRvOiVkICVzICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1zZXR1cDphY3RwYXNzXG4gICAgICBuYW1lOiAnc2V0dXAnLFxuICAgICAgcmVnOiAvXnNldHVwOihcXHcqKS8sXG4gICAgICBmb3JtYXQ6IFwic2V0dXA6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9bWlkOjFcbiAgICAgIG5hbWU6ICdtaWQnLFxuICAgICAgcmVnOiAvXm1pZDooW15cXHNdKikvLFxuICAgICAgZm9ybWF0OiBcIm1pZDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkOjBjOGIwNjRkLWQ4MDctNDNiNC1iNDM0LWY5MmE4ODlkODU4NyA5ODE3ODY4NS1kNDA5LTQ2ZTAtOGUxNi03ZWYwZGIwZGI2NGFcbiAgICAgIG5hbWU6ICdtc2lkJyxcbiAgICAgIHJlZzogL15tc2lkOiguKikvLFxuICAgICAgZm9ybWF0OiBcIm1zaWQ6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9cHRpbWU6MjBcbiAgICAgIG5hbWU6ICdwdGltZScsXG4gICAgICByZWc6IC9ecHRpbWU6KFxcZCopLyxcbiAgICAgIGZvcm1hdDogXCJwdGltZTolZFwiXG4gICAgfSxcbiAgICB7IC8vYT1tYXhwdGltZTo2MFxuICAgICAgbmFtZTogJ21heHB0aW1lJyxcbiAgICAgIHJlZzogL15tYXhwdGltZTooXFxkKikvLFxuICAgICAgZm9ybWF0OiBcIm1heHB0aW1lOiVkXCJcbiAgICB9LFxuICAgIHsgLy9hPXNlbmRyZWN2XG4gICAgICBuYW1lOiAnZGlyZWN0aW9uJyxcbiAgICAgIHJlZzogL14oc2VuZHJlY3Z8cmVjdm9ubHl8c2VuZG9ubHl8aW5hY3RpdmUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLWxpdGVcbiAgICAgIG5hbWU6ICdpY2VsaXRlJyxcbiAgICAgIHJlZzogL14oaWNlLWxpdGUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLXVmcmFnOkY3Z0lcbiAgICAgIG5hbWU6ICdpY2VVZnJhZycsXG4gICAgICByZWc6IC9eaWNlLXVmcmFnOihcXFMqKS8sXG4gICAgICBmb3JtYXQ6IFwiaWNlLXVmcmFnOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1wd2Q6eDljbWwvWXppY2hWMitYbGhpTXU4Z1xuICAgICAgbmFtZTogJ2ljZVB3ZCcsXG4gICAgICByZWc6IC9eaWNlLXB3ZDooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1wd2Q6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9ZmluZ2VycHJpbnQ6U0hBLTEgMDA6MTE6MjI6MzM6NDQ6NTU6NjY6Nzc6ODg6OTk6QUE6QkI6Q0M6REQ6RUU6RkY6MDA6MTE6MjI6MzNcbiAgICAgIG5hbWU6ICdmaW5nZXJwcmludCcsXG4gICAgICByZWc6IC9eZmluZ2VycHJpbnQ6KFxcUyopIChcXFMqKS8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ2hhc2gnXSxcbiAgICAgIGZvcm1hdDogXCJmaW5nZXJwcmludDolcyAlc1wiXG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Y2FuZGlkYXRlOjAgMSBVRFAgMjExMzY2NzMyNyAyMDMuMC4xMTMuMSA1NDQwMCB0eXAgaG9zdFxuICAgICAgLy9hPWNhbmRpZGF0ZToxMTYyODc1MDgxIDEgdWRwIDIxMTM5MzcxNTEgMTkyLjE2OC4zNC43NSA2MDAxNyB0eXAgaG9zdCBnZW5lcmF0aW9uIDBcbiAgICAgIC8vYT1jYW5kaWRhdGU6MzI4OTkxMjk1NyAyIHVkcCAxODQ1NTAxNjk1IDE5My44NC43Ny4xOTQgNjAwMTcgdHlwIHNyZmx4IHJhZGRyIDE5Mi4xNjguMzQuNzUgcnBvcnQgNjAwMTcgZ2VuZXJhdGlvbiAwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjIyOTgxNTYyMCAxIHRjcCAxNTE4MjgwNDQ3IDE5Mi4xNjguMTUwLjE5IDYwMDE3IHR5cCBob3N0IHRjcHR5cGUgYWN0aXZlIGdlbmVyYXRpb24gMFxuICAgICAgLy9hPWNhbmRpZGF0ZTozMjg5OTEyOTU3IDIgdGNwIDE4NDU1MDE2OTUgMTkzLjg0Ljc3LjE5NCA2MDAxNyB0eXAgc3JmbHggcmFkZHIgMTkyLjE2OC4zNC43NSBycG9ydCA2MDAxNyB0Y3B0eXBlIHBhc3NpdmUgZ2VuZXJhdGlvbiAwXG4gICAgICBwdXNoOidjYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL15jYW5kaWRhdGU6KFxcUyopIChcXGQqKSAoXFxTKikgKFxcZCopIChcXFMqKSAoXFxkKikgdHlwIChcXFMqKSg/OiByYWRkciAoXFxTKikgcnBvcnQgKFxcZCopKT8oPzogdGNwdHlwZSAoXFxTKikpPyg/OiBnZW5lcmF0aW9uIChcXGQqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2ZvdW5kYXRpb24nLCAnY29tcG9uZW50JywgJ3RyYW5zcG9ydCcsICdwcmlvcml0eScsICdpcCcsICdwb3J0JywgJ3R5cGUnLCAncmFkZHInLCAncnBvcnQnLCAndGNwdHlwZScsICdnZW5lcmF0aW9uJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHZhciBzdHIgPSBcImNhbmRpZGF0ZTolcyAlZCAlcyAlZCAlcyAlZCB0eXAgJXNcIjtcblxuICAgICAgICBzdHIgKz0gKG8ucmFkZHIgIT0gbnVsbCkgPyBcIiByYWRkciAlcyBycG9ydCAlZFwiIDogXCIldiV2XCI7XG5cbiAgICAgICAgLy8gTkI6IGNhbmRpZGF0ZSBoYXMgdGhyZWUgb3B0aW9uYWwgY2h1bmtzLCBzbyAldm9pZCBtaWRkbGVzIG9uZSBpZiBpdCdzIG1pc3NpbmdcbiAgICAgICAgc3RyICs9IChvLnRjcHR5cGUgIT0gbnVsbCkgPyBcIiB0Y3B0eXBlICVzXCIgOiBcIiV2XCI7XG5cbiAgICAgICAgaWYgKG8uZ2VuZXJhdGlvbiAhPSBudWxsKSB7XG4gICAgICAgICAgc3RyICs9IFwiIGdlbmVyYXRpb24gJWRcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9ZW5kLW9mLWNhbmRpZGF0ZXMgKGtlZXAgYWZ0ZXIgdGhlIGNhbmRpZGF0ZXMgbGluZSBmb3IgcmVhZGFiaWxpdHkpXG4gICAgICBuYW1lOiAnZW5kT2ZDYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL14oZW5kLW9mLWNhbmRpZGF0ZXMpL1xuICAgIH0sXG4gICAgeyAvL2E9cmVtb3RlLWNhbmRpZGF0ZXM6MSAyMDMuMC4xMTMuMSA1NDQwMCAyIDIwMy4wLjExMy4xIDU0NDAxIC4uLlxuICAgICAgbmFtZTogJ3JlbW90ZUNhbmRpZGF0ZXMnLFxuICAgICAgcmVnOiAvXnJlbW90ZS1jYW5kaWRhdGVzOiguKikvLFxuICAgICAgZm9ybWF0OiBcInJlbW90ZS1jYW5kaWRhdGVzOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1vcHRpb25zOmdvb2dsZS1pY2VcbiAgICAgIG5hbWU6ICdpY2VPcHRpb25zJyxcbiAgICAgIHJlZzogL15pY2Utb3B0aW9uczooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1vcHRpb25zOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXNzcmM6MjU2NjEwNzU2OSBjbmFtZTp0OVlVOE0xVXhURjhZMUExXG4gICAgICBwdXNoOiBcInNzcmNzXCIsXG4gICAgICByZWc6IC9ec3NyYzooXFxkKikgKFtcXHdfXSopOiguKikvLFxuICAgICAgbmFtZXM6IFsnaWQnLCAnYXR0cmlidXRlJywgJ3ZhbHVlJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYzolZCAlczolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1zc3JjLWdyb3VwOkZFQyAxIDJcbiAgICAgIHB1c2g6IFwic3NyY0dyb3Vwc1wiLFxuICAgICAgcmVnOiAvXnNzcmMtZ3JvdXA6KFxcdyopICguKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWNzJywgJ3NzcmNzJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYy1ncm91cDolcyAlc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkLXNlbWFudGljOiBXTVMgSnZsYW01WDNTWDFPUDZwbjIweldvZ3ZhS0p6NUhqZjlPbmxWXG4gICAgICBuYW1lOiBcIm1zaWRTZW1hbnRpY1wiLFxuICAgICAgcmVnOiAvXm1zaWQtc2VtYW50aWM6XFxzPyhcXHcqKSAoXFxTKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWMnLCAndG9rZW4nXSxcbiAgICAgIGZvcm1hdDogXCJtc2lkLXNlbWFudGljOiAlcyAlc1wiIC8vIHNwYWNlIGFmdGVyIFwiOlwiIGlzIG5vdCBhY2NpZGVudGFsXG4gICAgfSxcbiAgICB7IC8vYT1ncm91cDpCVU5ETEUgYXVkaW8gdmlkZW9cbiAgICAgIHB1c2g6ICdncm91cHMnLFxuICAgICAgcmVnOiAvXmdyb3VwOihcXHcqKSAoLiopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbWlkcyddLFxuICAgICAgZm9ybWF0OiBcImdyb3VwOiVzICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtbXV4XG4gICAgICBuYW1lOiAncnRjcE11eCcsXG4gICAgICByZWc6IC9eKHJ0Y3AtbXV4KS9cbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtcnNpemVcbiAgICAgIG5hbWU6ICdydGNwUnNpemUnLFxuICAgICAgcmVnOiAvXihydGNwLXJzaXplKS9cbiAgICB9LFxuICAgIHsgLy8gYW55IGE9IHRoYXQgd2UgZG9uJ3QgdW5kZXJzdGFuZCBpcyBrZXB0cyB2ZXJiYXRpbSBvbiBtZWRpYS5pbnZhbGlkXG4gICAgICBwdXNoOiAnaW52YWxpZCcsXG4gICAgICBuYW1lczogW1widmFsdWVcIl1cbiAgICB9XG4gIF1cbn07XG5cbi8vIHNldCBzZW5zaWJsZSBkZWZhdWx0cyB0byBhdm9pZCBwb2xsdXRpbmcgdGhlIGdyYW1tYXIgd2l0aCBib3JpbmcgZGV0YWlsc1xuT2JqZWN0LmtleXMoZ3JhbW1hcikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gIHZhciBvYmpzID0gZ3JhbW1hcltrZXldO1xuICBvYmpzLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgIGlmICghb2JqLnJlZykge1xuICAgICAgb2JqLnJlZyA9IC8oLiopLztcbiAgICB9XG4gICAgaWYgKCFvYmouZm9ybWF0KSB7XG4gICAgICBvYmouZm9ybWF0ID0gXCIlc1wiO1xuICAgIH1cbiAgfSk7XG59KTtcbiIsInZhciBwYXJzZXIgPSByZXF1aXJlKCcuL3BhcnNlcicpO1xudmFyIHdyaXRlciA9IHJlcXVpcmUoJy4vd3JpdGVyJyk7XG5cbmV4cG9ydHMud3JpdGUgPSB3cml0ZXI7XG5leHBvcnRzLnBhcnNlID0gcGFyc2VyLnBhcnNlO1xuZXhwb3J0cy5wYXJzZUZtdHBDb25maWcgPSBwYXJzZXIucGFyc2VGbXRwQ29uZmlnO1xuZXhwb3J0cy5wYXJzZVBheWxvYWRzID0gcGFyc2VyLnBhcnNlUGF5bG9hZHM7XG5leHBvcnRzLnBhcnNlUmVtb3RlQ2FuZGlkYXRlcyA9IHBhcnNlci5wYXJzZVJlbW90ZUNhbmRpZGF0ZXM7XG4iLCJ2YXIgdG9JbnRJZkludCA9IGZ1bmN0aW9uICh2KSB7XG4gIHJldHVybiBTdHJpbmcoTnVtYmVyKHYpKSA9PT0gdiA/IE51bWJlcih2KSA6IHY7XG59O1xuXG52YXIgYXR0YWNoUHJvcGVydGllcyA9IGZ1bmN0aW9uIChtYXRjaCwgbG9jYXRpb24sIG5hbWVzLCByYXdOYW1lKSB7XG4gIGlmIChyYXdOYW1lICYmICFuYW1lcykge1xuICAgIGxvY2F0aW9uW3Jhd05hbWVdID0gdG9JbnRJZkludChtYXRjaFsxXSk7XG4gIH1cbiAgZWxzZSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgaWYgKG1hdGNoW2krMV0gIT0gbnVsbCkge1xuICAgICAgICBsb2NhdGlvbltuYW1lc1tpXV0gPSB0b0ludElmSW50KG1hdGNoW2krMV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxudmFyIHBhcnNlUmVnID0gZnVuY3Rpb24gKG9iaiwgbG9jYXRpb24sIGNvbnRlbnQpIHtcbiAgdmFyIG5lZWRzQmxhbmsgPSBvYmoubmFtZSAmJiBvYmoubmFtZXM7XG4gIGlmIChvYmoucHVzaCAmJiAhbG9jYXRpb25bb2JqLnB1c2hdKSB7XG4gICAgbG9jYXRpb25bb2JqLnB1c2hdID0gW107XG4gIH1cbiAgZWxzZSBpZiAobmVlZHNCbGFuayAmJiAhbG9jYXRpb25bb2JqLm5hbWVdKSB7XG4gICAgbG9jYXRpb25bb2JqLm5hbWVdID0ge307XG4gIH1cbiAgdmFyIGtleUxvY2F0aW9uID0gb2JqLnB1c2ggP1xuICAgIHt9IDogIC8vIGJsYW5rIG9iamVjdCB0aGF0IHdpbGwgYmUgcHVzaGVkXG4gICAgbmVlZHNCbGFuayA/IGxvY2F0aW9uW29iai5uYW1lXSA6IGxvY2F0aW9uOyAvLyBvdGhlcndpc2UsIG5hbWVkIGxvY2F0aW9uIG9yIHJvb3RcblxuICBhdHRhY2hQcm9wZXJ0aWVzKGNvbnRlbnQubWF0Y2gob2JqLnJlZyksIGtleUxvY2F0aW9uLCBvYmoubmFtZXMsIG9iai5uYW1lKTtcblxuICBpZiAob2JqLnB1c2gpIHtcbiAgICBsb2NhdGlvbltvYmoucHVzaF0ucHVzaChrZXlMb2NhdGlvbik7XG4gIH1cbn07XG5cbnZhciBncmFtbWFyID0gcmVxdWlyZSgnLi9ncmFtbWFyJyk7XG52YXIgdmFsaWRMaW5lID0gUmVnRXhwLnByb3RvdHlwZS50ZXN0LmJpbmQoL14oW2Etel0pPSguKikvKTtcblxuZXhwb3J0cy5wYXJzZSA9IGZ1bmN0aW9uIChzZHApIHtcbiAgdmFyIHNlc3Npb24gPSB7fVxuICAgICwgbWVkaWEgPSBbXVxuICAgICwgbG9jYXRpb24gPSBzZXNzaW9uOyAvLyBwb2ludHMgYXQgd2hlcmUgcHJvcGVydGllcyBnbyB1bmRlciAob25lIG9mIHRoZSBhYm92ZSlcblxuICAvLyBwYXJzZSBsaW5lcyB3ZSB1bmRlcnN0YW5kXG4gIHNkcC5zcGxpdCgvKFxcclxcbnxcXHJ8XFxuKS8pLmZpbHRlcih2YWxpZExpbmUpLmZvckVhY2goZnVuY3Rpb24gKGwpIHtcbiAgICB2YXIgdHlwZSA9IGxbMF07XG4gICAgdmFyIGNvbnRlbnQgPSBsLnNsaWNlKDIpO1xuICAgIGlmICh0eXBlID09PSAnbScpIHtcbiAgICAgIG1lZGlhLnB1c2goe3J0cDogW10sIGZtdHA6IFtdfSk7XG4gICAgICBsb2NhdGlvbiA9IG1lZGlhW21lZGlhLmxlbmd0aC0xXTsgLy8gcG9pbnQgYXQgbGF0ZXN0IG1lZGlhIGxpbmVcbiAgICB9XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IChncmFtbWFyW3R5cGVdIHx8IFtdKS5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgdmFyIG9iaiA9IGdyYW1tYXJbdHlwZV1bal07XG4gICAgICBpZiAob2JqLnJlZy50ZXN0KGNvbnRlbnQpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVJlZyhvYmosIGxvY2F0aW9uLCBjb250ZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHNlc3Npb24ubWVkaWEgPSBtZWRpYTsgLy8gbGluayBpdCB1cFxuICByZXR1cm4gc2Vzc2lvbjtcbn07XG5cbnZhciBmbXRwUmVkdWNlciA9IGZ1bmN0aW9uIChhY2MsIGV4cHIpIHtcbiAgdmFyIHMgPSBleHByLnNwbGl0KCc9Jyk7XG4gIGlmIChzLmxlbmd0aCA9PT0gMikge1xuICAgIGFjY1tzWzBdXSA9IHRvSW50SWZJbnQoc1sxXSk7XG4gIH1cbiAgcmV0dXJuIGFjYztcbn07XG5cbmV4cG9ydHMucGFyc2VGbXRwQ29uZmlnID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KC9cXDtcXHM/LykucmVkdWNlKGZtdHBSZWR1Y2VyLCB7fSk7XG59O1xuXG5leHBvcnRzLnBhcnNlUGF5bG9hZHMgPSBmdW5jdGlvbiAoc3RyKSB7XG4gIHJldHVybiBzdHIuc3BsaXQoJyAnKS5tYXAoTnVtYmVyKTtcbn07XG5cbmV4cG9ydHMucGFyc2VSZW1vdGVDYW5kaWRhdGVzID0gZnVuY3Rpb24gKHN0cikge1xuICB2YXIgY2FuZGlkYXRlcyA9IFtdO1xuICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoJyAnKS5tYXAodG9JbnRJZkludCk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpICs9IDMpIHtcbiAgICBjYW5kaWRhdGVzLnB1c2goe1xuICAgICAgY29tcG9uZW50OiBwYXJ0c1tpXSxcbiAgICAgIGlwOiBwYXJ0c1tpICsgMV0sXG4gICAgICBwb3J0OiBwYXJ0c1tpICsgMl1cbiAgICB9KTtcbiAgfVxuICByZXR1cm4gY2FuZGlkYXRlcztcbn07XG4iLCJ2YXIgZ3JhbW1hciA9IHJlcXVpcmUoJy4vZ3JhbW1hcicpO1xuXG4vLyBjdXN0b21pemVkIHV0aWwuZm9ybWF0IC0gZGlzY2FyZHMgZXhjZXNzIGFyZ3VtZW50cyBhbmQgY2FuIHZvaWQgbWlkZGxlIG9uZXNcbnZhciBmb3JtYXRSZWdFeHAgPSAvJVtzZHYlXS9nO1xudmFyIGZvcm1hdCA9IGZ1bmN0aW9uIChmb3JtYXRTdHIpIHtcbiAgdmFyIGkgPSAxO1xuICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgdmFyIGxlbiA9IGFyZ3MubGVuZ3RoO1xuICByZXR1cm4gZm9ybWF0U3RyLnJlcGxhY2UoZm9ybWF0UmVnRXhwLCBmdW5jdGlvbiAoeCkge1xuICAgIGlmIChpID49IGxlbikge1xuICAgICAgcmV0dXJuIHg7IC8vIG1pc3NpbmcgYXJndW1lbnRcbiAgICB9XG4gICAgdmFyIGFyZyA9IGFyZ3NbaV07XG4gICAgaSArPSAxO1xuICAgIHN3aXRjaCAoeCkge1xuICAgICAgY2FzZSAnJSUnOlxuICAgICAgICByZXR1cm4gJyUnO1xuICAgICAgY2FzZSAnJXMnOlxuICAgICAgICByZXR1cm4gU3RyaW5nKGFyZyk7XG4gICAgICBjYXNlICclZCc6XG4gICAgICAgIHJldHVybiBOdW1iZXIoYXJnKTtcbiAgICAgIGNhc2UgJyV2JzpcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfSk7XG4gIC8vIE5COiB3ZSBkaXNjYXJkIGV4Y2VzcyBhcmd1bWVudHMgLSB0aGV5IGFyZSB0eXBpY2FsbHkgdW5kZWZpbmVkIGZyb20gbWFrZUxpbmVcbn07XG5cbnZhciBtYWtlTGluZSA9IGZ1bmN0aW9uICh0eXBlLCBvYmosIGxvY2F0aW9uKSB7XG4gIHZhciBzdHIgPSBvYmouZm9ybWF0IGluc3RhbmNlb2YgRnVuY3Rpb24gP1xuICAgIChvYmouZm9ybWF0KG9iai5wdXNoID8gbG9jYXRpb24gOiBsb2NhdGlvbltvYmoubmFtZV0pKSA6XG4gICAgb2JqLmZvcm1hdDtcblxuICB2YXIgYXJncyA9IFt0eXBlICsgJz0nICsgc3RyXTtcbiAgaWYgKG9iai5uYW1lcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqLm5hbWVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICB2YXIgbiA9IG9iai5uYW1lc1tpXTtcbiAgICAgIGlmIChvYmoubmFtZSkge1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVdW25dKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgeyAvLyBmb3IgbUxpbmUgYW5kIHB1c2ggYXR0cmlidXRlc1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVzW2ldXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIGFyZ3MucHVzaChsb2NhdGlvbltvYmoubmFtZV0pO1xuICB9XG4gIHJldHVybiBmb3JtYXQuYXBwbHkobnVsbCwgYXJncyk7XG59O1xuXG4vLyBSRkMgc3BlY2lmaWVkIG9yZGVyXG4vLyBUT0RPOiBleHRlbmQgdGhpcyB3aXRoIGFsbCB0aGUgcmVzdFxudmFyIGRlZmF1bHRPdXRlck9yZGVyID0gW1xuICAndicsICdvJywgJ3MnLCAnaScsXG4gICd1JywgJ2UnLCAncCcsICdjJyxcbiAgJ2InLCAndCcsICdyJywgJ3onLCAnYSdcbl07XG52YXIgZGVmYXVsdElubmVyT3JkZXIgPSBbJ2knLCAnYycsICdiJywgJ2EnXTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzZXNzaW9uLCBvcHRzKSB7XG4gIG9wdHMgPSBvcHRzIHx8IHt9O1xuICAvLyBlbnN1cmUgY2VydGFpbiBwcm9wZXJ0aWVzIGV4aXN0XG4gIGlmIChzZXNzaW9uLnZlcnNpb24gPT0gbnVsbCkge1xuICAgIHNlc3Npb24udmVyc2lvbiA9IDA7IC8vIFwidj0wXCIgbXVzdCBiZSB0aGVyZSAob25seSBkZWZpbmVkIHZlcnNpb24gYXRtKVxuICB9XG4gIGlmIChzZXNzaW9uLm5hbWUgPT0gbnVsbCkge1xuICAgIHNlc3Npb24ubmFtZSA9IFwiIFwiOyAvLyBcInM9IFwiIG11c3QgYmUgdGhlcmUgaWYgbm8gbWVhbmluZ2Z1bCBuYW1lIHNldFxuICB9XG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBpZiAobUxpbmUucGF5bG9hZHMgPT0gbnVsbCkge1xuICAgICAgbUxpbmUucGF5bG9hZHMgPSBcIlwiO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIG91dGVyT3JkZXIgPSBvcHRzLm91dGVyT3JkZXIgfHwgZGVmYXVsdE91dGVyT3JkZXI7XG4gIHZhciBpbm5lck9yZGVyID0gb3B0cy5pbm5lck9yZGVyIHx8IGRlZmF1bHRJbm5lck9yZGVyO1xuICB2YXIgc2RwID0gW107XG5cbiAgLy8gbG9vcCB0aHJvdWdoIG91dGVyT3JkZXIgZm9yIG1hdGNoaW5nIHByb3BlcnRpZXMgb24gc2Vzc2lvblxuICBvdXRlck9yZGVyLmZvckVhY2goZnVuY3Rpb24gKHR5cGUpIHtcbiAgICBncmFtbWFyW3R5cGVdLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgICAgaWYgKG9iai5uYW1lIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoubmFtZV0gIT0gbnVsbCkge1xuICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIHNlc3Npb24pKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoucHVzaF0gIT0gbnVsbCkge1xuICAgICAgICBzZXNzaW9uW29iai5wdXNoXS5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIHNkcC5wdXNoKG1ha2VMaW5lKHR5cGUsIG9iaiwgZWwpKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIHRoZW4gZm9yIGVhY2ggbWVkaWEgbGluZSwgZm9sbG93IHRoZSBpbm5lck9yZGVyXG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBzZHAucHVzaChtYWtlTGluZSgnbScsIGdyYW1tYXIubVswXSwgbUxpbmUpKTtcblxuICAgIGlubmVyT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAodHlwZSkge1xuICAgICAgZ3JhbW1hclt0eXBlXS5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgaWYgKG9iai5uYW1lIGluIG1MaW5lICYmIG1MaW5lW29iai5uYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBtTGluZSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIG1MaW5lICYmIG1MaW5lW29iai5wdXNoXSAhPSBudWxsKSB7XG4gICAgICAgICAgbUxpbmVbb2JqLnB1c2hdLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIGVsKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gc2RwLmpvaW4oJ1xcclxcbicpICsgJ1xcclxcbic7XG59O1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGFycmF5RXF1YWxzKGFycmF5KSB7XG4gICAgLy8gaWYgdGhlIG90aGVyIGFycmF5IGlzIGEgZmFsc3kgdmFsdWUsIHJldHVyblxuICAgIGlmICghYXJyYXkpXG4gICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgIC8vIGNvbXBhcmUgbGVuZ3RocyAtIGNhbiBzYXZlIGEgbG90IG9mIHRpbWVcbiAgICBpZiAodGhpcy5sZW5ndGggIT0gYXJyYXkubGVuZ3RoKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgbmVzdGVkIGFycmF5c1xuICAgICAgICBpZiAodGhpc1tpXSBpbnN0YW5jZW9mIEFycmF5ICYmIGFycmF5W2ldIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIHJlY3Vyc2UgaW50byB0aGUgbmVzdGVkIGFycmF5c1xuICAgICAgICAgICAgaWYgKCFhcnJheUVxdWFscy5hcHBseSh0aGlzW2ldLCBbYXJyYXlbaV1dKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpc1tpXSAhPSBhcnJheVtpXSkge1xuICAgICAgICAgICAgLy8gV2FybmluZyAtIHR3byBkaWZmZXJlbnQgb2JqZWN0IGluc3RhbmNlcyB3aWxsIG5ldmVyIGJlIGVxdWFsOlxuICAgICAgICAgICAgLy8ge3g6MjB9ICE9IHt4OjIwfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufTtcblxuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnRzLkludGVyb3AgPSByZXF1aXJlKCcuL2ludGVyb3AnKTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyogZ2xvYmFsIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbiAqL1xuLyogZ2xvYmFsIFJUQ0ljZUNhbmRpZGF0ZSAqL1xuLyoganNoaW50IC1XMDk3ICovXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIHRyYW5zZm9ybSA9IHJlcXVpcmUoJy4vdHJhbnNmb3JtJyk7XG52YXIgYXJyYXlFcXVhbHMgPSByZXF1aXJlKCcuL2FycmF5LWVxdWFscycpO1xuXG5mdW5jdGlvbiBJbnRlcm9wKCkge1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtYXAgaG9sZHMgdGhlIG1vc3QgcmVjZW50IFVuaWZpZWQgUGxhbiBvZmZlci9hbnN3ZXIgU0RQIHRoYXQgd2FzXG4gICAgICogY29udmVydGVkIHRvIFBsYW4gQiwgd2l0aCB0aGUgU0RQIHR5cGUgKCdvZmZlcicgb3IgJ2Fuc3dlcicpIGFzIGtleXMgYW5kXG4gICAgICogdGhlIFNEUCBzdHJpbmcgYXMgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHR5cGUge3t9fVxuICAgICAqL1xuICAgIHRoaXMuY2FjaGUgPSB7XG4gICAgICAgIG1sQjJVTWFwIDoge30sXG4gICAgICAgIG1sVTJCTWFwIDoge31cbiAgICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEludGVyb3A7XG5cbi8qKlxuICogQ2hhbmdlcyB0aGUgY2FuZGlkYXRlIGFyZ3MgdG8gbWF0Y2ggd2l0aCB0aGUgcmVsYXRlZCBVbmlmaWVkIFBsYW5cbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuY2FuZGlkYXRlVG9VbmlmaWVkUGxhbiA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHZhciBjYW5kID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuXG4gICAgY2FuZC5zZHBNTGluZUluZGV4ID0gdGhpcy5jYWNoZS5tbEIyVU1hcFtjYW5kLnNkcE1MaW5lSW5kZXhdO1xuICAgIC8qIFRPRE86IGNoYW5nZSBzZHBNaWQgdG8gKGF1ZGlvfHZpZGVvKS1TU1JDICovXG5cbiAgICByZXR1cm4gY2FuZDtcbn07XG5cbi8qKlxuICogQ2hhbmdlcyB0aGUgY2FuZGlkYXRlIGFyZ3MgdG8gbWF0Y2ggd2l0aCB0aGUgcmVsYXRlZCBQbGFuIEJcbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuY2FuZGlkYXRlVG9QbGFuQiA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHZhciBjYW5kID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuXG4gICAgaWYgKGNhbmQuc2RwTWlkLmluZGV4T2YoJ2F1ZGlvJykgPT09IDApIHtcbiAgICAgIGNhbmQuc2RwTWlkID0gJ2F1ZGlvJztcbiAgICB9IGVsc2UgaWYgKGNhbmQuc2RwTWlkLmluZGV4T2YoJ3ZpZGVvJykgPT09IDApIHtcbiAgICAgIGNhbmQuc2RwTWlkID0gJ3ZpZGVvJztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5kaWRhdGUgd2l0aCAnICsgY2FuZC5zZHBNaWQgKyAnIG5vdCBhbGxvd2VkJyk7XG4gICAgfVxuXG4gICAgY2FuZC5zZHBNTGluZUluZGV4ID0gdGhpcy5jYWNoZS5tbFUyQk1hcFtjYW5kLnNkcE1MaW5lSW5kZXhdO1xuXG4gICAgcmV0dXJuIGNhbmQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBtLWxpbmUgd2l0aCB0aGUgZ2l2ZW4gbWVkaWEgdHlwZSBhbmQgd2l0aCBhXG4gKiBkaXJlY3Rpb24gd2hpY2ggYWxsb3dzIHNlbmRpbmcsIGluIHRoZSBsYXN0IFVuaWZpZWQgUGxhbiBkZXNjcmlwdGlvbiB3aXRoXG4gKiB0eXBlIFwiYW5zd2VyXCIgY29udmVydGVkIHRvIFBsYW4gQi4gUmV0dXJucyB7bnVsbH0gaWYgdGhlcmUgaXMgbm8gc2F2ZWRcbiAqIGFuc3dlciwgb3IgaWYgbm9uZSBvZiBpdHMgbS1saW5lcyB3aXRoIHRoZSBnaXZlbiB0eXBlIGFsbG93IHNlbmRpbmcuXG4gKiBAcGFyYW0gdHlwZSB0aGUgbWVkaWEgdHlwZSAoXCJhdWRpb1wiIG9yIFwidmlkZW9cIikuXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyID0gZnVuY3Rpb24odHlwZSkge1xuICAgIGlmICghdGhpcy5jYWNoZS5hbnN3ZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UodGhpcy5jYWNoZS5hbnN3ZXIpO1xuICAgIGlmIChzZXNzaW9uICYmIHNlc3Npb24ubWVkaWEgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSl7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vzc2lvbi5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHNlc3Npb24ubWVkaWFbaV0udHlwZSA9PSB0eXBlICYmXG4gICAgICAgICAgICAgICAgKCFzZXNzaW9uLm1lZGlhW2ldLmRpcmVjdGlvbiAvKiBkZWZhdWx0IHRvIHNlbmRyZWN2ICovIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn07XG5cbi8qKlxuICogVGhpcyBtZXRob2QgdHJhbnNmb3JtcyBhIFVuaWZpZWQgUGxhbiBTRFAgdG8gYW4gZXF1aXZhbGVudCBQbGFuIEIgU0RQLiBBXG4gKiBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIHRyYW5zZm9ybXMgdGhlIFNEUCB0byBQbGFuIEIgYmVmb3JlIHBhc3NpbmcgaXQgdG8gdGhlXG4gKiBhcHBsaWNhdGlvbi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvUGxhbkIgPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBPYmplY3RpZnkgdGhlIFNEUCBmb3IgZWFzaWVyIG1hbmlwdWxhdGlvbi5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFVuaWZpZWQgUGxhbiBTRFAuIFBsYW4gQlxuICAgIC8vIFNEUCBoYXMgYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA8PSAzICYmIHNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBVbmlmaWVkIFBsYW4uJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vI2VuZHJlZ2lvblxuXG4gICAgLy8gSEFDSyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMTEzNDQzXG4gICAgdmFyIHNkcCA9IGRlc2Muc2RwO1xuICAgIHZhciByZXdyaXRlID0gZmFsc2U7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB1TGluZSA9IHNlc3Npb24ubWVkaWFbaV07XG4gICAgICAgIHVMaW5lLnJ0cC5mb3JFYWNoKGZ1bmN0aW9uKHJ0cCkge1xuICAgICAgICAgICAgaWYgKHJ0cC5jb2RlYyA9PT0gJ05VTEwnKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHJld3JpdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBvZmZlciA9IHRyYW5zZm9ybS5wYXJzZShzZWxmLmNhY2hlLm9mZmVyKTtcbiAgICAgICAgICAgICAgICBydHAuY29kZWMgPSBvZmZlci5tZWRpYVtpXS5ydHBbMF0uY29kZWM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAocmV3cml0ZSkge1xuICAgICAgICBzZHAgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG4gICAgfVxuXG4gICAgLy8gVW5pZmllZCBQbGFuIFNEUCBpcyBvdXIgXCJwcmVjaW91c1wiLiBDYWNoZSBpdCBmb3IgbGF0ZXIgdXNlIGluIHRoZSBQbGFuIEJcbiAgICAvLyAtPiBVbmlmaWVkIFBsYW4gdHJhbnNmb3JtYXRpb24uXG4gICAgdGhpcy5jYWNoZVtkZXNjLnR5cGVdID0gc2RwO1xuXG4gICAgLy8jcmVnaW9uIENvbnZlcnQgZnJvbSBVbmlmaWVkIFBsYW4gdG8gUGxhbiBCLlxuXG4gICAgLy8gV2UgcmVidWlsZCB0aGUgc2Vzc2lvbi5tZWRpYSBhcnJheS5cbiAgICB2YXIgbWVkaWEgPSBzZXNzaW9uLm1lZGlhO1xuICAgIHNlc3Npb24ubWVkaWEgPSBbXTtcblxuICAgIC8vIEFzc29jaWF0aXZlIGFycmF5IHRoYXQgbWFwcyBjaGFubmVsIHR5cGVzIHRvIGNoYW5uZWwgb2JqZWN0cyBmb3IgZmFzdFxuICAgIC8vIGFjY2VzcyB0byBjaGFubmVsIG9iamVjdHMgYnkgdGhlaXIgdHlwZSwgZS5nLiB0eXBlMmJsWydhdWRpbyddLT5jaGFubmVsXG4gICAgLy8gb2JqLlxuICAgIHZhciB0eXBlMmJsID0ge307XG5cbiAgICAvLyBVc2VkIHRvIGJ1aWxkIHRoZSBncm91cDpCVU5ETEUgdmFsdWUgYWZ0ZXIgdGhlIGNoYW5uZWxzIGNvbnN0cnVjdGlvblxuICAgIC8vIGxvb3AuXG4gICAgdmFyIHR5cGVzID0gW107XG5cbiAgICBtZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKHVMaW5lKSB7XG4gICAgICAgIC8vIHJ0Y3AtbXV4IGlzIHJlcXVpcmVkIGluIHRoZSBQbGFuIEIgU0RQLlxuICAgICAgICBpZiAoKHR5cGVvZiB1TGluZS5ydGNwTXV4ICE9PSAnc3RyaW5nJyB8fFxuICAgICAgICAgICAgdUxpbmUucnRjcE11eCAhPT0gJ3J0Y3AtbXV4JykgJiZcbiAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29udmVydCB0byBQbGFuIEIgYmVjYXVzZSBtLWxpbmVzICcgK1xuICAgICAgICAgICAgICAgICd3aXRob3V0IHRoZSBydGNwLW11eCBhdHRyaWJ1dGUgd2VyZSBmb3VuZC4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHdlIGRvbid0IGhhdmUgYSBjaGFubmVsIGZvciB0aGlzIHVMaW5lLnR5cGUgT1IgdGhlIHNlbGVjdGVkIGlzXG4gICAgICAgIC8vIGluYWN0aXZlLCB0aGVuIHNlbGVjdCB0aGlzIHVMaW5lIGFzIHRoZSBjaGFubmVsIGJhc2lzLlxuICAgICAgICBpZiAodHlwZW9mIHR5cGUyYmxbdUxpbmUudHlwZV0gPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLmRpcmVjdGlvbiA9PT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXSA9IHVMaW5lO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVMaW5lLnByb3RvY29sICE9IHR5cGUyYmxbdUxpbmUudHlwZV0ucHJvdG9jb2wpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHRvIFBsYW4gQiBiZWNhdXNlIG0tbGluZXMgJyArXG4gICAgICAgICAgICAgICdoYXZlIGRpZmZlcmVudCBwcm90b2NvbHMgYW5kIHRoaXMgbGlicmFyeSBkb2VzIG5vdCBoYXZlICcgK1xuICAgICAgICAgICAgICAnc3VwcG9ydCBmb3IgdGhhdCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVMaW5lLnBheWxvYWRzICE9IHR5cGUyYmxbdUxpbmUudHlwZV0ucGF5bG9hZHMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHRvIFBsYW4gQiBiZWNhdXNlIG0tbGluZXMgJyArXG4gICAgICAgICAgICAgICdoYXZlIGRpZmZlcmVudCBwYXlsb2FkcyBhbmQgdGhpcyBsaWJyYXJ5IGRvZXMgbm90IGhhdmUgJyArXG4gICAgICAgICAgICAgICdzdXBwb3J0IGZvciB0aGF0Jyk7XG4gICAgICAgIH1cblxuICAgIH0pO1xuXG4gICAgLy8gSW1wbG9kZSB0aGUgVW5pZmllZCBQbGFuIG0tbGluZXMvdHJhY2tzIGludG8gUGxhbiBCIGNoYW5uZWxzLlxuICAgIG1lZGlhLmZvckVhY2goZnVuY3Rpb24odUxpbmUpIHtcbiAgICAgICAgaWYgKHVMaW5lLnR5cGUgPT09ICdhcHBsaWNhdGlvbicpIHtcbiAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG4gICAgICAgICAgICB0eXBlcy5wdXNoKHVMaW5lLm1pZCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgc291cmNlcyB0byB0aGUgY2hhbm5lbCBhbmQgaGFuZGxlIGE9bXNpZC5cbiAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5zb3VyY2VzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgT2JqZWN0LmtleXModUxpbmUuc291cmNlcykuZm9yRWFjaChmdW5jdGlvbihzc3JjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXMgIT09ICdvYmplY3QnKVxuICAgICAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXMgPSB7fTtcblxuICAgICAgICAgICAgICAgIC8vIEFzc2lnbiB0aGUgc291cmNlcyB0byB0aGUgY2hhbm5lbC5cbiAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXNbc3NyY10gPVxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5tc2lkICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbiBQbGFuIEIgdGhlIG1zaWQgaXMgYW4gU1NSQyBhdHRyaWJ1dGUuIEFsc28sIHdlIGRvbid0XG4gICAgICAgICAgICAgICAgICAgIC8vIGNhcmUgYWJvdXQgdGhlIG9ic29sZXRlIGxhYmVsIGFuZCBtc2xhYmVsIGF0dHJpYnV0ZXMuXG4gICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGUgdGhhdCBpdCBpcyBub3QgZ3VhcmFudGVlZCB0aGF0IHRoZSB1TGluZSB3aWxsXG4gICAgICAgICAgICAgICAgICAgIC8vIGhhdmUgYW4gbXNpZC4gcmVjdm9ubHkgY2hhbm5lbHMgaW4gcGFydGljdWxhciBkb24ndCBoYXZlXG4gICAgICAgICAgICAgICAgICAgIC8vIG9uZS5cbiAgICAgICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzW3NzcmNdLm1zaWQgPVxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubXNpZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gTk9URSBzc3JjcyBpbiBzc3JjIGdyb3VwcyB3aWxsIHNoYXJlIG1zaWRzLCBhc1xuICAgICAgICAgICAgICAgIC8vIGRyYWZ0LXViZXJ0aS1ydGN3ZWItcGxhbi0wMCBtYW5kYXRlcy5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHNzcmMgZ3JvdXBzIHRvIHRoZSBjaGFubmVsLlxuICAgICAgICBpZiAodHlwZW9mIHVMaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheSh1TGluZS5zc3JjR3JvdXBzKSkge1xuXG4gICAgICAgICAgICAvLyBDcmVhdGUgdGhlIHNzcmNHcm91cHMgYXJyYXksIGlmIGl0J3Mgbm90IGRlZmluZWQuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcyA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgIUFycmF5LmlzQXJyYXkodHlwZTJibFt1TGluZS50eXBlXS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcyA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMgPVxuICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3Vwcy5jb25jYXQoXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNzcmNHcm91cHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUyYmxbdUxpbmUudHlwZV0gPT09IHVMaW5lKSB7XG4gICAgICAgICAgICAvLyBQbGFuIEIgbWlkcyBhcmUgaW4gWydhdWRpbycsICd2aWRlbycsICdkYXRhJ11cbiAgICAgICAgICAgIHVMaW5lLm1pZCA9IHVMaW5lLnR5cGU7XG5cbiAgICAgICAgICAgIC8vIFBsYW4gQiBkb2Vzbid0IHN1cHBvcnQvbmVlZCB0aGUgYnVuZGxlLW9ubHkgYXR0cmlidXRlLlxuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLmJ1bmRsZU9ubHk7XG5cbiAgICAgICAgICAgIC8vIEluIFBsYW4gQiB0aGUgbXNpZCBpcyBhbiBTU1JDIGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuXG5cdCAgICBpZiAodUxpbmUudHlwZSA9PSBtZWRpYVswXS50eXBlKSB7XG5cdCAgICAgIHR5cGVzLnVuc2hpZnQodUxpbmUudHlwZSk7XG5cdCAgICAgIC8vIEFkZCB0aGUgY2hhbm5lbCB0byB0aGUgbmV3IG1lZGlhIGFycmF5LlxuXHQgICAgICBzZXNzaW9uLm1lZGlhLnVuc2hpZnQodUxpbmUpO1xuXHQgICAgfSBlbHNlIHtcblx0ICAgICAgdHlwZXMucHVzaCh1TGluZS50eXBlKTtcblx0ICAgICAgLy8gQWRkIHRoZSBjaGFubmVsIHRvIHRoZSBuZXcgbWVkaWEgYXJyYXkuXG5cdCAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG5cdCAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAvLyBXZSByZWdlbmVyYXRlIHRoZSBCVU5ETEUgZ3JvdXAgd2l0aCB0aGUgbmV3IG1pZHMuXG4gICAgICBzZXNzaW9uLmdyb3Vwcy5zb21lKGZ1bmN0aW9uKGdyb3VwKSB7XG5cdCAgaWYgKGdyb3VwLnR5cGUgPT09ICdCVU5ETEUnKSB7XG5cdCAgICAgIGdyb3VwLm1pZHMgPSB0eXBlcy5qb2luKCcgJyk7XG5cdCAgICAgIHJldHVybiB0cnVlO1xuXHQgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIG1zaWQgc2VtYW50aWNcbiAgICBzZXNzaW9uLm1zaWRTZW1hbnRpYyA9IHtcbiAgICAgICAgc2VtYW50aWM6ICdXTVMnLFxuICAgICAgICB0b2tlbjogJyonXG4gICAgfTtcblxuICAgIHZhciByZXNTdHIgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG5cbiAgICByZXR1cm4gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgIHR5cGU6IGRlc2MudHlwZSxcbiAgICAgICAgc2RwOiByZXNTdHJcbiAgICB9KTtcblxuICAgIC8vI2VuZHJlZ2lvblxufTtcblxuLyogZm9sbG93IHJ1bGVzIGRlZmluZWQgaW4gUkZDNDE0NSAqL1xuZnVuY3Rpb24gYWRkU2V0dXBBdHRyKHVMaW5lKSB7XG4gICAgaWYgKHR5cGVvZiB1TGluZS5zZXR1cCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh1TGluZS5zZXR1cCA9PT0gXCJhY3RpdmVcIikge1xuICAgICAgICAgICAgdUxpbmUuc2V0dXAgPSBcInBhc3NpdmVcIjtcbiAgICB9IGVsc2UgaWYgKHVMaW5lLnNldHVwID09PSBcInBhc3NpdmVcIikge1xuICAgICAgICB1TGluZS5zZXR1cCA9IFwiYWN0aXZlXCI7XG4gICAgfVxufVxuXG4vKipcbiAqIFRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYSBQbGFuIEIgU0RQIHRvIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIFNEUC4gQVxuICogUGVlckNvbm5lY3Rpb24gd3JhcHBlciB0cmFuc2Zvcm1zIHRoZSBTRFAgdG8gVW5pZmllZCBQbGFuIGJlZm9yZSBwYXNzaW5nIGl0XG4gKiB0byBGRi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvVW5pZmllZFBsYW4gPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFBsYW4gQiBTRFAuIFBsYW4gQiBTRFAgaGFzXG4gICAgLy8gYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA+IDMgfHwgIXNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBQbGFuIEIuJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vIE1ha2Ugc3VyZSB0aGlzIFBsYW4gQiBTRFAgY2FuIGJlIGNvbnZlcnRlZCB0byBhIFVuaWZpZWQgUGxhbiBTRFAuXG4gICAgdmFyIG1pZHMgPSBbXTtcbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24obSkge1xuICAgICAgICBtaWRzLnB1c2gobS5taWQpO1xuICAgIH0pO1xuXG4gICAgdmFyIGhhc0J1bmRsZSA9IGZhbHNlO1xuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG4gICAgICAgIGhhc0J1bmRsZSA9IHNlc3Npb24uZ3JvdXBzLmV2ZXJ5KGZ1bmN0aW9uKGcpIHtcbiAgICAgICAgICAgIHJldHVybiBnLnR5cGUgIT09ICdCVU5ETEUnIHx8XG4gICAgICAgICAgICAgICAgYXJyYXlFcXVhbHMuYXBwbHkoZy5taWRzLnNvcnQoKSwgW21pZHMuc29ydCgpXSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICghaGFzQnVuZGxlKSB7XG4gICAgICAgIHZhciBtdXN0QmVCdW5kbGUgPSBmYWxzZTtcblxuICAgICAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgaWYgKG0uZGlyZWN0aW9uICE9PSAnaW5hY3RpdmUnKSB7XG4gICAgICAgICAgICAgICAgbXVzdEJlQnVuZGxlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKG11c3RCZUJ1bmRsZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNvbnZlcnQgdG8gVW5pZmllZCBQbGFuIGJlY2F1c2UgbS1saW5lcyB0aGF0XCIgK1xuICAgICAgICAgICAgICBcIiBhcmUgbm90IGJ1bmRsZWQgd2VyZSBmb3VuZC5cIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyNlbmRyZWdpb25cblxuXG4gICAgLy8jcmVnaW9uIENvbnZlcnQgZnJvbSBQbGFuIEIgdG8gVW5pZmllZCBQbGFuLlxuXG4gICAgLy8gVW5mb3J0dW5hdGVseSwgYSBQbGFuIEIgb2ZmZXIvYW5zd2VyIGRvZXNuJ3QgaGF2ZSBlbm91Z2ggaW5mb3JtYXRpb24gdG9cbiAgICAvLyByZWJ1aWxkIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIG9mZmVyL2Fuc3dlci5cbiAgICAvL1xuICAgIC8vIEZvciBleGFtcGxlLCBpZiB0aGlzIGlzIGEgbG9jYWwgYW5zd2VyIChpbiBVbmlmaWVkIFBsYW4gc3R5bGUpIHRoYXQgd2VcbiAgICAvLyBjb252ZXJ0IHRvIFBsYW4gQiBwcmlvciB0byBoYW5kaW5nIGl0IG92ZXIgdG8gdGhlIGFwcGxpY2F0aW9uICh0aGVcbiAgICAvLyBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIGNhbGxlZCB1cywgZm9yIGluc3RhbmNlLCBhZnRlciBhIHN1Y2Nlc3NmdWxcbiAgICAvLyBjcmVhdGVBbnN3ZXIpLCB3ZSB3YW50IHRvIHJlbWVtYmVyIHRoZSBtLWxpbmUgYXQgd2hpY2ggd2UndmUgc2VlbiB0aGVcbiAgICAvLyAobG9jYWwpIFNTUkMuIFRoYXQncyBiZWNhdXNlIHdoZW4gdGhlIGFwcGxpY2F0aW9uIHdhbnRzIHRvIGRvIGNhbGwgdGhlXG4gICAgLy8gU0xEIG1ldGhvZCwgZm9yY2luZyB1cyB0byBkbyB0aGUgaW52ZXJzZSB0cmFuc2Zvcm1hdGlvbiAoZnJvbSBQbGFuIEIgdG9cbiAgICAvLyBVbmlmaWVkIFBsYW4pLCB3ZSBuZWVkIHRvIGtub3cgdG8gd2hpY2ggbS1saW5lIHRvIGFzc2lnbiB0aGUgKGxvY2FsKVxuICAgIC8vIFNTUkMuIFdlIGFsc28gbmVlZCB0byBrbm93IGFsbCB0aGUgb3RoZXIgbS1saW5lcyB0aGF0IHRoZSBvcmlnaW5hbFxuICAgIC8vIGFuc3dlciBoYWQgYW5kIGluY2x1ZGUgdGhlbSBpbiB0aGUgdHJhbnNmb3JtZWQgYW5zd2VyIGFzIHdlbGwuXG4gICAgLy9cbiAgICAvLyBBbm90aGVyIGV4YW1wbGUgaXMgaWYgdGhpcyBpcyBhIHJlbW90ZSBvZmZlciB0aGF0IHdlIGNvbnZlcnQgdG8gUGxhbiBCXG4gICAgLy8gcHJpb3IgdG8gZ2l2aW5nIGl0IHRvIHRoZSBhcHBsaWNhdGlvbiwgd2Ugd2FudCB0byByZW1lbWJlciB0aGUgbWlkIGF0XG4gICAgLy8gd2hpY2ggd2UndmUgc2VlbiB0aGUgKHJlbW90ZSkgU1NSQy5cbiAgICAvL1xuICAgIC8vIEluIHRoZSBpdGVyYXRpb24gdGhhdCBmb2xsb3dzLCB3ZSB1c2UgdGhlIGNhY2hlZCBVbmlmaWVkIFBsYW4gKGlmIGl0XG4gICAgLy8gZXhpc3RzKSB0byBhc3NpZ24gbWlkcyB0byBzc3Jjcy5cblxuICAgIHZhciB0eXBlO1xuICAgIGlmIChkZXNjLnR5cGUgPT09ICdhbnN3ZXInKSB7XG4gICAgICAgIHR5cGUgPSAnb2ZmZXInO1xuICAgIH0gZWxzZSBpZiAoZGVzYy50eXBlID09PSAnb2ZmZXInKSB7XG4gICAgICAgIHR5cGUgPSAnYW5zd2VyJztcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUeXBlICdcIiArIGRlc2MudHlwZSArIFwiJyBub3Qgc3VwcG9ydGVkLlwiKTtcbiAgICB9XG5cbiAgICB2YXIgY2FjaGVkO1xuICAgIGlmICh0eXBlb2YgdGhpcy5jYWNoZVt0eXBlXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY2FjaGVkID0gdHJhbnNmb3JtLnBhcnNlKHRoaXMuY2FjaGVbdHlwZV0pO1xuICAgIH1cblxuICAgIHZhciByZWN2b25seVNzcmNzID0ge1xuICAgICAgICBhdWRpbzoge30sXG4gICAgICAgIHZpZGVvOiB7fVxuICAgIH07XG5cbiAgICAvLyBBIGhlbHBlciBtYXAgdGhhdCBzZW5kcyBtaWRzIHRvIG0tbGluZSBvYmplY3RzLiBXZSB1c2UgaXQgbGF0ZXIgdG9cbiAgICAvLyByZWJ1aWxkIHRoZSBVbmlmaWVkIFBsYW4gc3R5bGUgc2Vzc2lvbi5tZWRpYSBhcnJheS5cbiAgICB2YXIgbWlkMnVsID0ge307XG4gICAgdmFyIGJJZHggPSAwO1xuICAgIHZhciB1SWR4ID0gMDtcblxuICAgIHZhciBzb3VyY2VzMnVsID0ge307XG5cbiAgICB2YXIgY2FuZGlkYXRlcztcbiAgICB2YXIgaWNlVWZyYWc7XG4gICAgdmFyIGljZVB3ZDtcbiAgICB2YXIgZmluZ2VycHJpbnQ7XG4gICAgdmFyIHBheWxvYWRzID0ge307XG4gICAgdmFyIHJ0Y3BGYiA9IHt9O1xuICAgIHZhciBydHAgPSB7fTtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbihiTGluZSkge1xuICAgICAgICBpZiAoKHR5cGVvZiBiTGluZS5ydGNwTXV4ICE9PSAnc3RyaW5nJyB8fFxuICAgICAgICAgICAgYkxpbmUucnRjcE11eCAhPT0gJ3J0Y3AtbXV4JykgJiZcbiAgICAgICAgICAgIGJMaW5lLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNvbnZlcnQgdG8gVW5pZmllZCBQbGFuIGJlY2F1c2UgbS1saW5lcyBcIiArXG4gICAgICAgICAgICAgICAgXCJ3aXRob3V0IHRoZSBydGNwLW11eCBhdHRyaWJ1dGUgd2VyZSBmb3VuZC5cIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYkxpbmUudHlwZSA9PT0gJ2FwcGxpY2F0aW9uJykge1xuICAgICAgICAgICAgbWlkMnVsW2JMaW5lLm1pZF0gPSBiTGluZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdpdGggcnRjcC1tdXggYW5kIGJ1bmRsZSBhbGwgdGhlIGNoYW5uZWxzIHNob3VsZCBoYXZlIHRoZSBzYW1lIElDRVxuICAgICAgICAvLyBzdHVmZi5cbiAgICAgICAgdmFyIHNvdXJjZXMgPSBiTGluZS5zb3VyY2VzO1xuICAgICAgICB2YXIgc3NyY0dyb3VwcyA9IGJMaW5lLnNzcmNHcm91cHM7XG4gICAgICAgIHZhciBwb3J0ID0gYkxpbmUucG9ydDtcblxuICAgICAgICAvKiBDaHJvbWUgYWRkcyBkaWZmZXJlbnQgY2FuZGlkYXRlcyBldmVuIHVzaW5nIGJ1bmRsZSwgc28gd2UgY29uY2F0IHRoZSBjYW5kaWRhdGVzIGxpc3QgKi9cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5jYW5kaWRhdGVzICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNhbmRpZGF0ZXMgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBjYW5kaWRhdGVzID0gY2FuZGlkYXRlcy5jb25jYXQoYkxpbmUuY2FuZGlkYXRlcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbmRpZGF0ZXMgPSBiTGluZS5jYW5kaWRhdGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCh0eXBlb2YgaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpICYmICh0eXBlb2YgYkxpbmUuaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpICYmIChpY2VVZnJhZyAhPSBiTGluZS5pY2VVZnJhZykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgQlVORExFIHN1cHBvcnRlZCwgaWNlVWZyYWcgbXVzdCBiZSB0aGUgc2FtZSBmb3IgYWxsIG0tbGluZXMuXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TGFzdCBpY2VVZnJhZzogXCIgKyBpY2VVZnJhZyArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGljZVVmcmFnOiBcIiArIGJMaW5lLmljZVVmcmFnXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5pY2VVZnJhZyAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGljZVVmcmFnID0gYkxpbmUuaWNlVWZyYWc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHR5cGVvZiBpY2VQd2QgIT0gJ3VuZGVmaW5lZCcpICYmICh0eXBlb2YgYkxpbmUuaWNlUHdkICE9ICd1bmRlZmluZWQnKSAmJiAoaWNlUHdkICE9IGJMaW5lLmljZVB3ZCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgQlVORExFIHN1cHBvcnRlZCwgaWNlUHdkIG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgaWNlUHdkOiBcIiArIGljZVB3ZCArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGljZVB3ZDogXCIgKyBiTGluZS5pY2VQd2RcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGJMaW5lLmljZVB3ZCAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGljZVB3ZCA9IGJMaW5lLmljZVB3ZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgodHlwZW9mIGZpbmdlcnByaW50ICE9ICd1bmRlZmluZWQnKSAmJiAodHlwZW9mIGJMaW5lLmZpbmdlcnByaW50ICE9ICd1bmRlZmluZWQnKSAmJlxuICAgICAgICAgICAgKGZpbmdlcnByaW50LnR5cGUgIT0gYkxpbmUuZmluZ2VycHJpbnQudHlwZSB8fCBmaW5nZXJwcmludC5oYXNoICE9IGJMaW5lLmZpbmdlcnByaW50Lmhhc2gpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IEJVTkRMRSBzdXBwb3J0ZWQsIGZpbmdlcnByaW50IG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgZmluZ2VycHJpbnQ6IFwiICsgSlNPTi5zdHJpbmdpZnkoZmluZ2VycHJpbnQpICsgXCJcXG5cIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcXHROZXcgZmluZ2VycHJpbnQ6IFwiICsgSlNPTi5zdHJpbmdpZnkoYkxpbmUuZmluZ2VycHJpbnQpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5maW5nZXJwcmludCAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGZpbmdlcnByaW50ID0gYkxpbmUuZmluZ2VycHJpbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBwYXlsb2Fkc1tiTGluZS50eXBlXSA9IGJMaW5lLnBheWxvYWRzO1xuICAgICAgICBydGNwRmJbYkxpbmUudHlwZV0gPSBiTGluZS5ydGNwRmI7XG4gICAgICAgIHJ0cFtiTGluZS50eXBlXSA9IGJMaW5lLnJ0cDtcblxuICAgICAgICAvLyBpbnZlcnRlZCBzc3JjIGdyb3VwIG1hcFxuICAgICAgICB2YXIgc3NyYzJncm91cCA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICAgIHNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgLy8gWFhYIFRoaXMgbWlnaHQgYnJha2UgaWYgYW4gU1NSQyBpcyBpbiBtb3JlIHRoYW4gb25lIGdyb3VwXG4gICAgICAgICAgICAgICAgLy8gZm9yIHNvbWUgcmVhc29uLlxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyY0dyb3VwLnNzcmNzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmNHcm91cC5zc3JjcykpIHtcbiAgICAgICAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzLmZvckVhY2goZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyYzJncm91cFtzc3JjXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzc3JjMmdyb3VwW3NzcmNdID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNzcmMyZ3JvdXBbc3NyY10ucHVzaChzc3JjR3JvdXApO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHNzcmMgdG8gbS1saW5lIGluZGV4LlxuICAgICAgICB2YXIgc3NyYzJtbCA9IHt9O1xuXG4gICAgICAgIGlmICh0eXBlb2Ygc291cmNlcyA9PT0gJ29iamVjdCcpIHtcblxuICAgICAgICAgICAgLy8gV2UnbGwgdXNlIHRoZSBcImJMaW5lXCIgb2JqZWN0IGFzIGEgcHJvdG90eXBlIGZvciBlYWNoIG5ldyBcIm1MaW5lXCJcbiAgICAgICAgICAgIC8vIHRoYXQgd2UgY3JlYXRlLCBidXQgZmlyc3Qgd2UgbmVlZCB0byBjbGVhbiBpdCB1cCBhIGJpdC5cbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5zb3VyY2VzO1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLnNzcmNHcm91cHM7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuY2FuZGlkYXRlcztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5pY2VVZnJhZztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5pY2VQd2Q7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuZmluZ2VycHJpbnQ7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUucG9ydDtcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5taWQ7XG5cbiAgICAgICAgICAgIC8vIEV4cGxvZGUgdGhlIFBsYW4gQiBjaGFubmVsIHNvdXJjZXMgd2l0aCBvbmUgbS1saW5lIHBlciBzb3VyY2UuXG4gICAgICAgICAgICBPYmplY3Qua2V5cyhzb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uKHNzcmMpIHtcblxuICAgICAgICAgICAgICAgIC8vIFRoZSAodW5pZmllZCkgbS1saW5lIGZvciB0aGlzIFNTUkMuIFdlIGVpdGhlciBjcmVhdGUgaXQgZnJvbVxuICAgICAgICAgICAgICAgIC8vIHNjcmF0Y2ggb3IsIGlmIGl0J3MgYSBncm91cGVkIFNTUkMsIHdlIHJlLXVzZSBhIHJlbGF0ZWRcbiAgICAgICAgICAgICAgICAvLyBtbGluZS4gSW4gb3RoZXIgd29yZHMsIGlmIHRoZSBzb3VyY2UgaXMgZ3JvdXBlZCB3aXRoIGFub3RoZXJcbiAgICAgICAgICAgICAgICAvLyBzb3VyY2UsIHB1dCB0aGUgdHdvIHRvZ2V0aGVyIGluIHRoZSBzYW1lIG0tbGluZS5cbiAgICAgICAgICAgICAgICB2YXIgdUxpbmU7XG5cbiAgICAgICAgICAgICAgICAvLyBXZSBhc3N1bWUgaGVyZSB0aGF0IHdlIGFyZSB0aGUgYW5zd2VyZXIgaW4gdGhlIE8vQSwgc28gYW55XG4gICAgICAgICAgICAgICAgLy8gb2ZmZXJzIHdoaWNoIHdlIHRyYW5zbGF0ZSBjb21lIGZyb20gdGhlIHJlbW90ZSBzaWRlLCB3aGlsZVxuICAgICAgICAgICAgICAgIC8vIGFuc3dlcnMgYXJlIGxvY2FsLiBTbyB0aGUgY2hlY2sgYmVsb3cgaXMgdG8gbWFrZSB0aGF0IHdlXG4gICAgICAgICAgICAgICAgLy8gaGFuZGxlIHJlY2VpdmUtb25seSBTU1JDcyBpbiBhIHNwZWNpYWwgd2F5IG9ubHkgaWYgdGhleSBjb21lXG4gICAgICAgICAgICAgICAgLy8gZnJvbSB0aGUgcmVtb3RlIHNpZGUuXG4gICAgICAgICAgICAgICAgaWYgKGRlc2MudHlwZT09PSdvZmZlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2Ugd2FudCB0byBkZXRlY3QgU1NSQ3Mgd2hpY2ggYXJlIHVzZWQgYnkgYSByZW1vdGUgcGVlclxuICAgICAgICAgICAgICAgICAgICAvLyBpbiBhbiBtLWxpbmUgd2l0aCBkaXJlY3Rpb249cmVjdm9ubHkgKGkuZS4gdGhleSBhcmVcbiAgICAgICAgICAgICAgICAgICAgLy8gYmVpbmcgdXNlZCBmb3IgUlRDUCBvbmx5KS5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBpbmZvcm1hdGlvbiB3b3VsZCBoYXZlIGdvdHRlbiBsb3N0IGlmIHRoZSByZW1vdGVcbiAgICAgICAgICAgICAgICAgICAgLy8gcGVlciB1c2VkIFVuaWZpZWQgUGxhbiBhbmQgdGhlaXIgbG9jYWwgZGVzY3JpcHRpb24gd2FzXG4gICAgICAgICAgICAgICAgICAgIC8vIHRyYW5zbGF0ZWQgdG8gUGxhbiBCLiBTbyB3ZSB1c2UgdGhlIGxhY2sgb2YgYW4gTVNJRFxuICAgICAgICAgICAgICAgICAgICAvLyBhdHRyaWJ1dGUgdG8gZGVkdWNlIGEgXCJyZWNlaXZlIG9ubHlcIiBTU1JDLlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNvdXJjZXNbc3NyY10ubXNpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjdm9ubHlTc3Jjc1tiTGluZS50eXBlXVtzc3JjXSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWNlaXZlLW9ubHkgU1NSQ3MgbXVzdCBub3QgY3JlYXRlIG5ldyBtLWxpbmVzLiBXZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2lsbCBhc3NpZ24gdGhlbSB0byBhbiBleGlzdGluZyBtLWxpbmUgbGF0ZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNzcmMyZ3JvdXBbc3NyY10gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoc3NyYzJncm91cFtzc3JjXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3NyYzJncm91cFtzc3JjXS5zb21lKGZ1bmN0aW9uIChzc3JjR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNzcmNHcm91cC5zc3JjcyAqaXMqIGFuIEFycmF5LCBubyBuZWVkIHRvIGNoZWNrXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhZ2FpbiBoZXJlLlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNzcmNHcm91cC5zc3Jjcy5zb21lKGZ1bmN0aW9uIChyZWxhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjMm1sW3JlbGF0ZWRdID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZSA9IHNzcmMybWxbcmVsYXRlZF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVMaW5lID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbS1saW5lIGFscmVhZHkgZXhpc3RzLiBKdXN0IGFkZCB0aGUgc291cmNlLlxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID0gc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIFwiYkxpbmVcIiBhcyBhIHByb3RvdHlwZSBmb3IgdGhlIFwidUxpbmVcIi5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUgPSBPYmplY3QuY3JlYXRlKGJMaW5lKTtcbiAgICAgICAgICAgICAgICAgICAgc3NyYzJtbFtzc3JjXSA9IHVMaW5lO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc291cmNlc1tzc3JjXS5tc2lkICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXNzaWduIHRoZSBtc2lkIG9mIHRoZSBzb3VyY2UgdG8gdGhlIG0tbGluZS4gTm90ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhhdCBpdCBpcyBub3QgZ3VhcmFudGVlZCB0aGF0IHRoZSBzb3VyY2Ugd2lsbCBoYXZlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtc2lkLiBJbiBwYXJ0aWN1bGFyIFwicmVjdm9ubHlcIiBzb3VyY2VzIGRvbid0IGhhdmUgYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1zaWQuIE5vdGUgdGhhdCBcInJlY3Zvbmx5XCIgaXMgYSB0ZXJtIG9ubHkgZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZm9yIG0tbGluZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5tc2lkID0gc291cmNlc1tzc3JjXS5tc2lkO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIGFzc2lnbiBvbmUgU1NSQyBwZXIgbWVkaWEgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID0gc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc3NyY0dyb3VwcyA9IHNzcmMyZ3JvdXBbc3NyY107XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHRoZSBjYWNoZWQgVW5pZmllZCBQbGFuIFNEUCAoaWYgaXQgZXhpc3RzKSB0byBhc3NpZ25cbiAgICAgICAgICAgICAgICAgICAgLy8gU1NSQ3MgdG8gbWlkcy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjYWNoZWQgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlb2YgY2FjaGVkLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShjYWNoZWQubWVkaWEpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZC5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtLnNvdXJjZXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKG0uc291cmNlcykuZm9yRWFjaChmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMgPT09IHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5taWQgPSBtLm1pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVMaW5lLm1pZCA9PT0gJ3VuZGVmaW5lZCcpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyBhbiBTU1JDIHRoYXQgd2Ugc2VlIGZvciB0aGUgZmlyc3QgdGltZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGl0IGEgbmV3IG1pZC4gVGhpcyBpcyB0eXBpY2FsbHkgdGhlIGNhc2Ugd2hlblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBtZXRob2QgaXMgY2FsbGVkIHRvIHRyYW5zZm9ybSBhIHJlbW90ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGVzY3JpcHRpb24gZm9yIHRoZSBmaXJzdCB0aW1lIG9yIHdoZW4gdGhlcmUgaXMgYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbmV3IFNTUkMgaW4gdGhlIHJlbW90ZSBkZXNjcmlwdGlvbiBiZWNhdXNlIGEgbmV3XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwZWVyIGhhcyBqb2luZWQgdGhlIGNvbmZlcmVuY2UuIExvY2FsIFNTUkNzIHNob3VsZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaGF2ZSBhbHJlYWR5IGJlZW4gYWRkZWQgdG8gdGhlIG1hcCBpbiB0aGUgdG9QbGFuQlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWV0aG9kLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2UgRkYgZ2VuZXJhdGVzIGFuc3dlcnMgaW4gVW5pZmllZCBQbGFuIHN0eWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UgTVVTVCBhbHJlYWR5IGhhdmUgYSBjYWNoZWQgYW5zd2VyIHdpdGggYWxsIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbG9jYWwgU1NSQ3MgbWFwcGVkIHRvIHNvbWUgbS1saW5lL21pZC5cblxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubWlkID0gW2JMaW5lLnR5cGUsICctJywgc3NyY10uam9pbignJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBJbmNsdWRlIHRoZSBjYW5kaWRhdGVzIGluIHRoZSAxc3QgbWVkaWEgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVVmcmFnID0gaWNlVWZyYWc7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUucG9ydCA9IHBvcnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgbWlkMnVsW3VMaW5lLm1pZF0gPSB1TGluZTtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlczJ1bFt1SWR4XSA9IHVMaW5lLnNvdXJjZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWNoZS5tbFUyQk1hcFt1SWR4XSA9IGJJZHg7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNhY2hlLm1sQjJVTWFwW2JJZHhdID0gdUlkeDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB1SWR4Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHVMaW5lID0gYkxpbmU7XG5cbiAgICAgICAgICB1TGluZS5jYW5kaWRhdGVzID0gY2FuZGlkYXRlcztcbiAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICB1TGluZS5maW5nZXJwcmludCA9IGZpbmdlcnByaW50O1xuICAgICAgICAgIHVMaW5lLnBvcnQgPSBwb3J0O1xuXG4gICAgICAgICAgbWlkMnVsW3VMaW5lLm1pZF0gPSB1TGluZTtcblxuICAgICAgICAgIHNlbGYuY2FjaGUubWxVMkJNYXBbdUlkeF0gPSBiSWR4O1xuICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHNlbGYuY2FjaGUubWxCMlVNYXBbYklkeF0gPSB1SWR4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGJJZHgrKztcbiAgICB9KTtcblxuICAgIC8vIFJlYnVpbGQgdGhlIG1lZGlhIGFycmF5IGluIHRoZSByaWdodCBvcmRlciBhbmQgYWRkIHRoZSBtaXNzaW5nIG1MaW5lc1xuICAgIC8vIChtaXNzaW5nIGZyb20gdGhlIFBsYW4gQiBTRFApLlxuICAgIHNlc3Npb24ubWVkaWEgPSBbXTtcbiAgICBtaWRzID0gW107IC8vIHJldXNlXG5cbiAgICBpZiAoZGVzYy50eXBlID09PSAnYW5zd2VyJykge1xuXG4gICAgICAgIC8vIFRoZSBtZWRpYSBsaW5lcyBpbiB0aGUgYW5zd2VyIG11c3QgbWF0Y2ggdGhlIG1lZGlhIGxpbmVzIGluIHRoZVxuICAgICAgICAvLyBvZmZlci4gVGhlIG9yZGVyIGlzIGltcG9ydGFudCB0b28uIEhlcmUgd2UgYXNzdW1lIHRoYXQgRmlyZWZveCBpc1xuICAgICAgICAvLyB0aGUgYW5zd2VyZXIsIHNvIHdlIG1lcmVseSBoYXZlIHRvIHVzZSB0aGUgcmVjb25zdHJ1Y3RlZCAodW5pZmllZClcbiAgICAgICAgLy8gYW5zd2VyIHRvIHVwZGF0ZSB0aGUgY2FjaGVkICh1bmlmaWVkKSBhbnN3ZXIgYWNjb3JkaW5nbHkuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEluIHRoZSBnZW5lcmFsIGNhc2UsIG9uZSB3b3VsZCBoYXZlIHRvIHVzZSB0aGUgY2FjaGVkICh1bmlmaWVkKVxuICAgICAgICAvLyBvZmZlciB0byBmaW5kIHRoZSBtLWxpbmVzIHRoYXQgYXJlIG1pc3NpbmcgZnJvbSB0aGUgcmVjb25zdHJ1Y3RlZFxuICAgICAgICAvLyBhbnN3ZXIsIHBvdGVudGlhbGx5IGdyYWJiaW5nIHRoZW0gZnJvbSB0aGUgY2FjaGVkICh1bmlmaWVkKSBhbnN3ZXIuXG4gICAgICAgIC8vIE9uZSBoYXMgdG8gYmUgY2FyZWZ1bCB3aXRoIHRoaXMgYXBwcm9hY2ggYmVjYXVzZSBpbmFjdGl2ZSBtLWxpbmVzIGRvXG4gICAgICAgIC8vIG5vdCBhbHdheXMgaGF2ZSBhbiBtaWQsIG1ha2luZyBpdCB0cmlja3kgKGltcG9zc2libGU/KSB0byBmaW5kIHdoZXJlXG4gICAgICAgIC8vIGV4YWN0bHkgYW5kIHdoaWNoIG0tbGluZXMgYXJlIG1pc3NpbmcgZnJvbSB0aGUgcmVjb25zdHJ1Y3RlZCBhbnN3ZXIuXG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjYWNoZWQubWVkaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB1TGluZSA9IGNhY2hlZC5tZWRpYVtpXTtcblxuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICBkZWxldGUgdUxpbmUuc291cmNlcztcbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zc3JjR3JvdXBzO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHNvdXJjZXMydWxbaV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAncmVjdm9ubHknO1xuICAgICAgICAgICAgICBlbHNlIGlmICh1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kb25seScpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnaW5hY3RpdmUnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKCF1TGluZS5kaXJlY3Rpb25cbiAgICAgICAgICAgICAgICAgIHx8IHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JylcbiAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICAgIGVsc2UgaWYgKHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3JlY3Zvbmx5JylcbiAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdzZW5kb25seSc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHVMaW5lLnNvdXJjZXMgPSBzb3VyY2VzMnVsW2ldO1xuICAgICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgICAgdUxpbmUuaWNlUHdkID0gaWNlUHdkO1xuICAgICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcblxuICAgICAgICAgICAgdUxpbmUucnRwID0gcnRwW3VMaW5lLnR5cGVdO1xuICAgICAgICAgICAgdUxpbmUucGF5bG9hZHMgPSBwYXlsb2Fkc1t1TGluZS50eXBlXTtcbiAgICAgICAgICAgIHVMaW5lLnJ0Y3BGYiA9IHJ0Y3BGYlt1TGluZS50eXBlXTtcblxuICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5taWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgLy8gaW5hY3RpdmUgbGluZXMgZG9uJ3QvbWF5IG5vdCBoYXZlIGFuIG1pZC5cbiAgICAgICAgICAgICAgICBtaWRzLnB1c2godUxpbmUubWlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgLy8gU0RQIG9mZmVyL2Fuc3dlciAoYW5kIHRoZSBKU0VQIHNwZWMpIGZvcmJpZHMgcmVtb3ZpbmcgYW4gbS1zZWN0aW9uXG4gICAgICAgIC8vIHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzLiBJZiB3ZSBhcmUgbm8gbG9uZ2VyIGludGVyZXN0ZWQgaW4gc2VuZGluZyBhXG4gICAgICAgIC8vIHRyYWNrLCB3ZSBqdXN0IHJlbW92ZSB0aGUgbXNpZCBhbmQgc3NyYyBhdHRyaWJ1dGVzIGFuZCBzZXQgaXQgdG9cbiAgICAgICAgLy8gZWl0aGVyIGE9cmVjdm9ubHkgKGFzIHRoZSByZW9mZmVyZXIsIHdlIG11c3QgdXNlIHJlY3Zvbmx5IGlmIHRoZVxuICAgICAgICAvLyBvdGhlciBzaWRlIHdhcyBwcmV2aW91c2x5IHNlbmRpbmcgb24gdGhlIG0tc2VjdGlvbiwgYnV0IHdlIGNhbiBhbHNvXG4gICAgICAgIC8vIGxlYXZlIHRoZSBwb3NzaWJpbGl0eSBvcGVuIGlmIGl0IHdhc24ndCBwcmV2aW91c2x5IGluIHVzZSksIG9yXG4gICAgICAgIC8vIGE9aW5hY3RpdmUuXG5cbiAgICAgICAgaWYgKHR5cGVvZiBjYWNoZWQgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICB0eXBlb2YgY2FjaGVkLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgQXJyYXkuaXNBcnJheShjYWNoZWQubWVkaWEpKSB7XG4gICAgICAgICAgICBjYWNoZWQubWVkaWEuZm9yRWFjaChmdW5jdGlvbih1TGluZSkge1xuICAgICAgICAgICAgICAgIG1pZHMucHVzaCh1TGluZS5taWQpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWlkMnVsW3VMaW5lLm1pZF0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaChtaWQydWxbdUxpbmUubWlkXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zb3VyY2VzO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdUxpbmUuc3NyY0dyb3VwcztcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXVMaW5lLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnc2VuZG9ubHknO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdyZWN2b25seScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdpbmFjdGl2ZSc7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhZGRTZXR1cEF0dHIgKHVMaW5lKTtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBhbGwgdGhlIHJlbWFpbmluZyAobmV3KSBtLWxpbmVzIG9mIHRoZSB0cmFuc2Zvcm1lZCBTRFAuXG4gICAgICAgIE9iamVjdC5rZXlzKG1pZDJ1bCkuZm9yRWFjaChmdW5jdGlvbihtaWQpIHtcbiAgICAgICAgICAgIGlmIChtaWRzLmluZGV4T2YobWlkKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtaWRzLnB1c2gobWlkKTtcbiAgICAgICAgICAgICAgICBpZiAobWlkMnVsW21pZF0uZGlyZWN0aW9uID09PSAncmVjdm9ubHknKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYSByZW1vdGUgcmVjdm9ubHkgY2hhbm5lbC4gQWRkIGl0cyBTU1JDIHRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyBhcHByb3ByaWF0ZSBzZW5kcmVjdiBvciBzZW5kb25seSBjaGFubmVsLlxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPKGdwKSB3aGF0IGlmIHdlIGRvbid0IGhhdmUgc2VuZHJlY3Yvc2VuZG9ubHlcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hhbm5lbD9cblxuICAgICAgICAgICAgICAgICAgICB2YXIgZG9uZSA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEuc29tZShmdW5jdGlvbiAodUxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLnR5cGUgPT09IG1pZDJ1bFttaWRdLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtaWQydWxbbWlkXSBzaG91bGRuJ3QgaGF2ZSBhbnkgc3NyYy1ncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhtaWQydWxbbWlkXS5zb3VyY2VzKS5mb3JFYWNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pZDJ1bFttaWRdLnNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb25lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2gobWlkMnVsW21pZF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKG1pZDJ1bFttaWRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEFmdGVyIHdlIGhhdmUgY29uc3RydWN0ZWQgdGhlIFBsYW4gVW5pZmllZCBtLWxpbmVzIHdlIGNhbiBmaWd1cmUgb3V0XG4gICAgLy8gd2hlcmUgKGluIHdoaWNoIG0tbGluZSkgdG8gcGxhY2UgdGhlICdyZWN2b25seSBTU1JDcycuXG4gICAgLy8gTm90ZTogd2UgYXNzdW1lIGhlcmUgdGhhdCB3ZSBhcmUgdGhlIGFuc3dlcmVyIGluIHRoZSBPL0EsIHNvIGFueSBvZmZlcnNcbiAgICAvLyB3aGljaCB3ZSB0cmFuc2xhdGUgY29tZSBmcm9tIHRoZSByZW1vdGUgc2lkZSwgd2hpbGUgYW5zd2VycyBhcmUgbG9jYWxcbiAgICAvLyAoYW5kIHNvIG91ciBsYXN0IGxvY2FsIGRlc2NyaXB0aW9uIGlzIGNhY2hlZCBhcyBhbiAnYW5zd2VyJykuXG4gICAgW1wiYXVkaW9cIiwgXCJ2aWRlb1wiXS5mb3JFYWNoKGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIGlmICghc2Vzc2lvbiB8fCAhc2Vzc2lvbi5tZWRpYSB8fCAhQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB2YXIgaWR4ID0gbnVsbDtcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGlkeCA9IHNlbGYuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyKHR5cGUpO1xuICAgICAgICAgICAgaWYgKGlkeCA9PT0gbnVsbCl7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyB0aGUgZmlyc3Qgb2ZmZXIgd2UgcmVjZWl2ZSwgd2UgZG9uJ3QgaGF2ZSBhXG4gICAgICAgICAgICAgICAgLy8gY2FjaGVkIGFuc3dlci4gQXNzdW1lIHRoYXQgd2Ugd2lsbCBiZSBzZW5kaW5nIG1lZGlhIHVzaW5nXG4gICAgICAgICAgICAgICAgLy8gdGhlIGZpcnN0IG0tbGluZSBmb3IgZWFjaCBtZWRpYSB0eXBlLlxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZXNzaW9uLm1lZGlhW2ldLnR5cGUgPT09IHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkeCA9IGk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpZHggJiYgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPiBpZHgpIHtcbiAgICAgICAgICAgIHZhciBtTGluZSA9IHNlc3Npb24ubWVkaWFbaWR4XTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmZvckVhY2goZnVuY3Rpb24oc3NyYykge1xuICAgICAgICAgICAgICAgIGlmIChtTGluZS5zb3VyY2VzICYmIG1MaW5lLnNvdXJjZXNbc3NyY10pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiUmVwbGFjaW5nIGFuIGV4aXN0aW5nIFNTUkMuXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIW1MaW5lLnNvdXJjZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgbUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIG1MaW5lLnNvdXJjZXNbc3NyY10gPSByZWN2b25seVNzcmNzW3R5cGVdW3NzcmNdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAvLyBXZSByZWdlbmVyYXRlIHRoZSBCVU5ETEUgZ3JvdXAgKHNpbmNlIHdlIHJlZ2VuZXJhdGVkIHRoZSBtaWRzKVxuICAgICAgc2Vzc2lvbi5ncm91cHMuc29tZShmdW5jdGlvbihncm91cCkge1xuXHQgIGlmIChncm91cC50eXBlID09PSAnQlVORExFJykge1xuXHQgICAgICBncm91cC5taWRzID0gbWlkcy5qb2luKCcgJyk7XG5cdCAgICAgIHJldHVybiB0cnVlO1xuXHQgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIG1zaWQgc2VtYW50aWNcbiAgICBzZXNzaW9uLm1zaWRTZW1hbnRpYyA9IHtcbiAgICAgICAgc2VtYW50aWM6ICdXTVMnLFxuICAgICAgICB0b2tlbjogJyonXG4gICAgfTtcblxuICAgIHZhciByZXNTdHIgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG5cbiAgICAvLyBDYWNoZSB0aGUgdHJhbnNmb3JtZWQgU0RQIChVbmlmaWVkIFBsYW4pIGZvciBsYXRlciByZS11c2UgaW4gdGhpc1xuICAgIC8vIGZ1bmN0aW9uLlxuICAgIHRoaXMuY2FjaGVbZGVzYy50eXBlXSA9IHJlc1N0cjtcblxuICAgIHJldHVybiBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgICAgdHlwZTogZGVzYy50eXBlLFxuICAgICAgICBzZHA6IHJlc1N0clxuICAgIH0pO1xuXG4gICAgLy8jZW5kcmVnaW9uXG59O1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgdHJhbnNmb3JtID0gcmVxdWlyZSgnc2RwLXRyYW5zZm9ybScpO1xuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24oc2Vzc2lvbiwgb3B0cykge1xuXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSkge1xuXG4gICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtTGluZSkge1xuICAgICAgLy8gZXhwYW5kIHNvdXJjZXMgdG8gc3NyY3NcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc291cmNlcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgT2JqZWN0LmtleXMobUxpbmUuc291cmNlcykubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbUxpbmUuc3NyY3MgPSBbXTtcbiAgICAgICAgICBPYmplY3Qua2V5cyhtTGluZS5zb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gbUxpbmUuc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHNvdXJjZSkuZm9yRWFjaChmdW5jdGlvbiAoYXR0cmlidXRlKSB7XG4gICAgICAgICAgICAgIG1MaW5lLnNzcmNzLnB1c2goe1xuICAgICAgICAgICAgICAgIGlkOiBzc3JjLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogYXR0cmlidXRlLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBzb3VyY2VbYXR0cmlidXRlXVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGRlbGV0ZSBtTGluZS5zb3VyY2VzO1xuICAgICAgICB9XG5cbiAgICAgIC8vIGpvaW4gc3NyY3MgaW4gc3NyYyBncm91cHNcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmNHcm91cC5zc3JjcykpIHtcbiAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzID0gc3NyY0dyb3VwLnNzcmNzLmpvaW4oJyAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gam9pbiBncm91cCBtaWRzXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLmdyb3VwcykpIHtcblxuICAgIHNlc3Npb24uZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgIGlmICh0eXBlb2YgZy5taWRzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KGcubWlkcykpIHtcbiAgICAgICAgZy5taWRzID0gZy5taWRzLmpvaW4oJyAnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbiwgb3B0cyk7XG59O1xuXG5leHBvcnRzLnBhcnNlID0gZnVuY3Rpb24oc2RwKSB7XG4gIHZhciBzZXNzaW9uID0gdHJhbnNmb3JtLnBhcnNlKHNkcCk7XG5cbiAgaWYgKHR5cGVvZiBzZXNzaW9uICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygc2Vzc2lvbi5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpIHtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICAgIC8vIGdyb3VwIHNvdXJjZXMgYXR0cmlidXRlcyBieSBzc3JjXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KG1MaW5lLnNzcmNzKSkge1xuICAgICAgICBtTGluZS5zb3VyY2VzID0ge307XG4gICAgICAgIG1MaW5lLnNzcmNzLmZvckVhY2goZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICBpZiAoIW1MaW5lLnNvdXJjZXNbc3NyYy5pZF0pXG4gICAgICAgICAgbUxpbmUuc291cmNlc1tzc3JjLmlkXSA9IHt9O1xuICAgICAgICBtTGluZS5zb3VyY2VzW3NzcmMuaWRdW3NzcmMuYXR0cmlidXRlXSA9IHNzcmMudmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlbGV0ZSBtTGluZS5zc3JjcztcbiAgICAgIH1cblxuICAgICAgLy8gc3BsaXQgc3NyY3MgaW4gc3NyYyBncm91cHNcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzID0gc3NyY0dyb3VwLnNzcmNzLnNwbGl0KCcgJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuICAvLyBzcGxpdCBncm91cCBtaWRzXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLmdyb3VwcykpIHtcblxuICAgIHNlc3Npb24uZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgIGlmICh0eXBlb2YgZy5taWRzID09PSAnc3RyaW5nJykge1xuICAgICAgICBnLm1pZHMgPSBnLm1pZHMuc3BsaXQoJyAnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzZXNzaW9uO1xufTtcblxuIiwiLyohXG4gKiBVQVBhcnNlci5qcyB2MC43LjE4XG4gKiBMaWdodHdlaWdodCBKYXZhU2NyaXB0LWJhc2VkIFVzZXItQWdlbnQgc3RyaW5nIHBhcnNlclxuICogaHR0cHM6Ly9naXRodWIuY29tL2ZhaXNhbG1hbi91YS1wYXJzZXItanNcbiAqXG4gKiBDb3B5cmlnaHQgwqkgMjAxMi0yMDE2IEZhaXNhbCBTYWxtYW4gPGZ5emxtYW5AZ21haWwuY29tPlxuICogRHVhbCBsaWNlbnNlZCB1bmRlciBHUEx2MiBvciBNSVRcbiAqL1xuXG4oZnVuY3Rpb24gKHdpbmRvdywgdW5kZWZpbmVkKSB7XG5cbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvLy8vLy8vLy8vLy8vL1xuICAgIC8vIENvbnN0YW50c1xuICAgIC8vLy8vLy8vLy8vLy9cblxuXG4gICAgdmFyIExJQlZFUlNJT04gID0gJzAuNy4xOCcsXG4gICAgICAgIEVNUFRZICAgICAgID0gJycsXG4gICAgICAgIFVOS05PV04gICAgID0gJz8nLFxuICAgICAgICBGVU5DX1RZUEUgICA9ICdmdW5jdGlvbicsXG4gICAgICAgIFVOREVGX1RZUEUgID0gJ3VuZGVmaW5lZCcsXG4gICAgICAgIE9CSl9UWVBFICAgID0gJ29iamVjdCcsXG4gICAgICAgIFNUUl9UWVBFICAgID0gJ3N0cmluZycsXG4gICAgICAgIE1BSk9SICAgICAgID0gJ21ham9yJywgLy8gZGVwcmVjYXRlZFxuICAgICAgICBNT0RFTCAgICAgICA9ICdtb2RlbCcsXG4gICAgICAgIE5BTUUgICAgICAgID0gJ25hbWUnLFxuICAgICAgICBUWVBFICAgICAgICA9ICd0eXBlJyxcbiAgICAgICAgVkVORE9SICAgICAgPSAndmVuZG9yJyxcbiAgICAgICAgVkVSU0lPTiAgICAgPSAndmVyc2lvbicsXG4gICAgICAgIEFSQ0hJVEVDVFVSRT0gJ2FyY2hpdGVjdHVyZScsXG4gICAgICAgIENPTlNPTEUgICAgID0gJ2NvbnNvbGUnLFxuICAgICAgICBNT0JJTEUgICAgICA9ICdtb2JpbGUnLFxuICAgICAgICBUQUJMRVQgICAgICA9ICd0YWJsZXQnLFxuICAgICAgICBTTUFSVFRWICAgICA9ICdzbWFydHR2JyxcbiAgICAgICAgV0VBUkFCTEUgICAgPSAnd2VhcmFibGUnLFxuICAgICAgICBFTUJFRERFRCAgICA9ICdlbWJlZGRlZCc7XG5cblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gSGVscGVyXG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgdXRpbCA9IHtcbiAgICAgICAgZXh0ZW5kIDogZnVuY3Rpb24gKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIHtcbiAgICAgICAgICAgIHZhciBtYXJnZWRSZWdleGVzID0ge307XG4gICAgICAgICAgICBmb3IgKHZhciBpIGluIHJlZ2V4ZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uc1tpXSAmJiBleHRlbnNpb25zW2ldLmxlbmd0aCAlIDIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2VkUmVnZXhlc1tpXSA9IGV4dGVuc2lvbnNbaV0uY29uY2F0KHJlZ2V4ZXNbaV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcmdlZFJlZ2V4ZXNbaV0gPSByZWdleGVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXJnZWRSZWdleGVzO1xuICAgICAgICB9LFxuICAgICAgICBoYXMgOiBmdW5jdGlvbiAoc3RyMSwgc3RyMikge1xuICAgICAgICAgIGlmICh0eXBlb2Ygc3RyMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHN0cjIudG9Mb3dlckNhc2UoKS5pbmRleE9mKHN0cjEudG9Mb3dlckNhc2UoKSkgIT09IC0xO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsb3dlcml6ZSA6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHIudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfSxcbiAgICAgICAgbWFqb3IgOiBmdW5jdGlvbiAodmVyc2lvbikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZih2ZXJzaW9uKSA9PT0gU1RSX1RZUEUgPyB2ZXJzaW9uLnJlcGxhY2UoL1teXFxkXFwuXS9nLCcnKS5zcGxpdChcIi5cIilbMF0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIHRyaW0gOiBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eW1xcc1xcdUZFRkZcXHhBMF0rfFtcXHNcXHVGRUZGXFx4QTBdKyQvZywgJycpO1xuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gTWFwIGhlbHBlclxuICAgIC8vLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciBtYXBwZXIgPSB7XG5cbiAgICAgICAgcmd4IDogZnVuY3Rpb24gKHVhLCBhcnJheXMpIHtcblxuICAgICAgICAgICAgLy92YXIgcmVzdWx0ID0ge30sXG4gICAgICAgICAgICB2YXIgaSA9IDAsIGosIGssIHAsIHEsIG1hdGNoZXMsIG1hdGNoOy8vLCBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAgICAgICAvKi8vIGNvbnN0cnVjdCBvYmplY3QgYmFyZWJvbmVzXG4gICAgICAgICAgICBmb3IgKHAgPSAwOyBwIDwgYXJnc1sxXS5sZW5ndGg7IHArKykge1xuICAgICAgICAgICAgICAgIHEgPSBhcmdzWzFdW3BdO1xuICAgICAgICAgICAgICAgIHJlc3VsdFt0eXBlb2YgcSA9PT0gT0JKX1RZUEUgPyBxWzBdIDogcV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9Ki9cblxuICAgICAgICAgICAgLy8gbG9vcCB0aHJvdWdoIGFsbCByZWdleGVzIG1hcHNcbiAgICAgICAgICAgIHdoaWxlIChpIDwgYXJyYXlzLmxlbmd0aCAmJiAhbWF0Y2hlcykge1xuXG4gICAgICAgICAgICAgICAgdmFyIHJlZ2V4ID0gYXJyYXlzW2ldLCAgICAgICAvLyBldmVuIHNlcXVlbmNlICgwLDIsNCwuLilcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSBhcnJheXNbaSArIDFdOyAgIC8vIG9kZCBzZXF1ZW5jZSAoMSwzLDUsLi4pXG4gICAgICAgICAgICAgICAgaiA9IGsgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gdHJ5IG1hdGNoaW5nIHVhc3RyaW5nIHdpdGggcmVnZXhlc1xuICAgICAgICAgICAgICAgIHdoaWxlIChqIDwgcmVnZXgubGVuZ3RoICYmICFtYXRjaGVzKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IHJlZ2V4W2orK10uZXhlYyh1YSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwID0gMDsgcCA8IHByb3BzLmxlbmd0aDsgcCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBtYXRjaGVzWysra107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcSA9IHByb3BzW3BdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIGdpdmVuIHByb3BlcnR5IGlzIGFjdHVhbGx5IGFycmF5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBxID09PSBPQkpfVFlQRSAmJiBxLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHEubGVuZ3RoID09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcVsxXSA9PSBGVU5DX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhc3NpZ24gbW9kaWZpZWQgbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXS5jYWxsKHRoaXMsIG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGdpdmVuIHZhbHVlLCBpZ25vcmUgcmVnZXggbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayB3aGV0aGVyIGZ1bmN0aW9uIG9yIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHFbMV0gPT09IEZVTkNfVFlQRSAmJiAhKHFbMV0uZXhlYyAmJiBxWzFdLnRlc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FsbCBmdW5jdGlvbiAodXN1YWxseSBzdHJpbmcgbWFwcGVyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbcVswXV0gPSBtYXRjaCA/IHFbMV0uY2FsbCh0aGlzLCBtYXRjaCwgcVsyXSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNhbml0aXplIG1hdGNoIHVzaW5nIGdpdmVuIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gbWF0Y2gucmVwbGFjZShxWzFdLCBxWzJdKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gcVszXS5jYWxsKHRoaXMsIG1hdGNoLnJlcGxhY2UocVsxXSwgcVsyXSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txXSA9IG1hdGNoID8gbWF0Y2ggOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMpO1xuICAgICAgICAgICAgLy9yZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICBzdHIgOiBmdW5jdGlvbiAoc3RyLCBtYXApIHtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBtYXApIHtcbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBhcnJheVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWFwW2ldID09PSBPQkpfVFlQRSAmJiBtYXBbaV0ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1hcFtpXS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHV0aWwuaGFzKG1hcFtpXVtqXSwgc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoaSA9PT0gVU5LTk9XTikgPyB1bmRlZmluZWQgOiBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh1dGlsLmhhcyhtYXBbaV0sIHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChpID09PSBVTktOT1dOKSA/IHVuZGVmaW5lZCA6IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgICAgfVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIFN0cmluZyBtYXBcbiAgICAvLy8vLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgbWFwcyA9IHtcblxuICAgICAgICBicm93c2VyIDoge1xuICAgICAgICAgICAgb2xkc2FmYXJpIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICcxLjAnICAgOiAnLzgnLFxuICAgICAgICAgICAgICAgICAgICAnMS4yJyAgIDogJy8xJyxcbiAgICAgICAgICAgICAgICAgICAgJzEuMycgICA6ICcvMycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAnICAgOiAnLzQxMicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMicgOiAnLzQxNicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMycgOiAnLzQxNycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuNCcgOiAnLzQxOScsXG4gICAgICAgICAgICAgICAgICAgICc/JyAgICAgOiAnLydcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGV2aWNlIDoge1xuICAgICAgICAgICAgYW1hem9uIDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRmlyZSBQaG9uZScgOiBbJ1NEJywgJ0tGJ11cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3ByaW50IDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRXZvIFNoaWZ0IDRHJyA6ICc3MzczS1QnXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB2ZW5kb3IgOiB7XG4gICAgICAgICAgICAgICAgICAgICdIVEMnICAgICAgIDogJ0FQQScsXG4gICAgICAgICAgICAgICAgICAgICdTcHJpbnQnICAgIDogJ1NwcmludCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgb3MgOiB7XG4gICAgICAgICAgICB3aW5kb3dzIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICdNRScgICAgICAgIDogJzQuOTAnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgMy4xMScgICA6ICdOVDMuNTEnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgNC4wJyAgICA6ICdOVDQuMCcsXG4gICAgICAgICAgICAgICAgICAgICcyMDAwJyAgICAgIDogJ05UIDUuMCcsXG4gICAgICAgICAgICAgICAgICAgICdYUCcgICAgICAgIDogWydOVCA1LjEnLCAnTlQgNS4yJ10sXG4gICAgICAgICAgICAgICAgICAgICdWaXN0YScgICAgIDogJ05UIDYuMCcsXG4gICAgICAgICAgICAgICAgICAgICc3JyAgICAgICAgIDogJ05UIDYuMScsXG4gICAgICAgICAgICAgICAgICAgICc4JyAgICAgICAgIDogJ05UIDYuMicsXG4gICAgICAgICAgICAgICAgICAgICc4LjEnICAgICAgIDogJ05UIDYuMycsXG4gICAgICAgICAgICAgICAgICAgICcxMCcgICAgICAgIDogWydOVCA2LjQnLCAnTlQgMTAuMCddLFxuICAgICAgICAgICAgICAgICAgICAnUlQnICAgICAgICA6ICdBUk0nXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy9cbiAgICAvLyBSZWdleCBtYXBcbiAgICAvLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciByZWdleGVzID0ge1xuXG4gICAgICAgIGJyb3dzZXIgOiBbW1xuXG4gICAgICAgICAgICAvLyBQcmVzdG8gYmFzZWRcbiAgICAgICAgICAgIC8ob3BlcmFcXHNtaW5pKVxcLyhbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1pbmlcbiAgICAgICAgICAgIC8ob3BlcmFcXHNbbW9iaWxldGFiXSspLit2ZXJzaW9uXFwvKFtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1vYmkvVGFibGV0XG4gICAgICAgICAgICAvKG9wZXJhKS4rdmVyc2lvblxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhID4gOS44MFxuICAgICAgICAgICAgLyhvcGVyYSlbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgPCA5LjgwXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhvcGlvcylbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgbWluaSBvbiBpcGhvbmUgPj0gOC4wXG4gICAgICAgICAgICBdLCBbW05BTUUsICdPcGVyYSBNaW5pJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9cXHMob3ByKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIFdlYmtpdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gTWl4ZWRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvKGx1bmFzY2FwZXxtYXh0aG9ufG5ldGZyb250fGphc21pbmV8YmxhemVyKVtcXC9cXHNdPyhbXFx3XFwuXSopL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEx1bmFzY2FwZS9NYXh0aG9uL05ldGZyb250L0phc21pbmUvQmxhemVyXG5cbiAgICAgICAgICAgIC8vIFRyaWRlbnQgYmFzZWRcbiAgICAgICAgICAgIC8oYXZhbnRcXHN8aWVtb2JpbGV8c2xpbXxiYWlkdSkoPzpicm93c2VyKT9bXFwvXFxzXT8oW1xcd1xcLl0qKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdmFudC9JRU1vYmlsZS9TbGltQnJvd3Nlci9CYWlkdVxuICAgICAgICAgICAgLyg/Om1zfFxcKCkoaWUpXFxzKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW50ZXJuZXQgRXhwbG9yZXJcblxuICAgICAgICAgICAgLy8gV2Via2l0L0tIVE1MIGJhc2VkXG4gICAgICAgICAgICAvKHJla29ucSlcXC8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJla29ucVxuICAgICAgICAgICAgLyhjaHJvbWl1bXxmbG9ja3xyb2NrbWVsdHxtaWRvcml8ZXBpcGhhbnl8c2lsa3xza3lmaXJlfG92aWJyb3dzZXJ8Ym9sdHxpcm9ufHZpdmFsZGl8aXJpZGl1bXxwaGFudG9tanN8Ym93c2VyfHF1YXJrKVxcLyhbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9taXVtL0Zsb2NrL1JvY2tNZWx0L01pZG9yaS9FcGlwaGFueS9TaWxrL1NreWZpcmUvQm9sdC9Jcm9uL0lyaWRpdW0vUGhhbnRvbUpTL0Jvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8odHJpZGVudCkuK3J2WzpcXHNdKFtcXHdcXC5dKykuK2xpa2VcXHNnZWNrby9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElFMTFcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0lFJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oZWRnZXxlZGdpb3N8ZWRnZWEpXFwvKChcXGQrKT9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBFZGdlXG4gICAgICAgICAgICBdLCBbW05BTUUsICdFZGdlJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oeWFicm93c2VyKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWWFuZGV4XG4gICAgICAgICAgICBdLCBbW05BTUUsICdZYW5kZXgnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhwdWZmaW4pXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQdWZmaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ1B1ZmZpbiddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKCg/OltcXHNcXC9dKXVjP1xccz9icm93c2VyfCg/Omp1Yy4rKXVjd2ViKVtcXC9cXHNdPyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVUNCcm93c2VyXG4gICAgICAgICAgICBdLCBbW05BTUUsICdVQ0Jyb3dzZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb21vZG9fZHJhZ29uKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb21vZG8gRHJhZ29uXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obWljcm9tZXNzZW5nZXIpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2VDaGF0XG4gICAgICAgICAgICBdLCBbW05BTUUsICdXZUNoYXQnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhxcWJyb3dzZXJsaXRlKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUUJyb3dzZXJMaXRlXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhRUSlcXC8oW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUSwgYWthIFNob3VRXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL20/KHFxYnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUVFCcm93c2VyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhCSURVQnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmFpZHUgQnJvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oMjM0NUV4cGxvcmVyKVtcXC9cXHNdPyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDIzNDUgQnJvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oTWV0YVNyKVtcXC9cXHNdPyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvdUdvdUJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAvKExCQlJPV1NFUikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGllQmFvIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAveGlhb21pXFwvbWl1aWJyb3dzZXJcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNSVVJIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ01JVUkgQnJvd3NlciddXSwgW1xuXG4gICAgICAgICAgICAvO2ZiYXZcXC8oW1xcd1xcLl0rKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZhY2Vib29rIEFwcCBmb3IgaU9TICYgQW5kcm9pZFxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnRmFjZWJvb2snXV0sIFtcblxuICAgICAgICAgICAgL2hlYWRsZXNzY2hyb21lKD86XFwvKFtcXHdcXC5dKyl8XFxzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lIEhlYWRsZXNzXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdDaHJvbWUgSGVhZGxlc3MnXV0sIFtcblxuICAgICAgICAgICAgL1xcc3d2XFwpLisoY2hyb21lKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9tZSBXZWJWaWV3XG4gICAgICAgICAgICBdLCBbW05BTUUsIC8oLispLywgJyQxIFdlYlZpZXcnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLygoPzpvY3VsdXN8c2Ftc3VuZylicm93c2VyKVxcLyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgLyguKyg/Omd8dXMpKSguKykvLCAnJDEgJDInXSwgVkVSU0lPTl0sIFsgICAgICAgICAgICAgICAgLy8gT2N1bHVzIC8gU2Ftc3VuZyBCcm93c2VyXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLit2ZXJzaW9uXFwvKFtcXHdcXC5dKylcXHMrKD86bW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpKi9pICAgICAgICAvLyBBbmRyb2lkIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0FuZHJvaWQgQnJvd3NlciddXSwgW1xuXG4gICAgICAgICAgICAvKGNocm9tZXxvbW5pd2VifGFyb3JhfFt0aXplbm9rYV17NX1cXHM/YnJvd3NlcilcXC92PyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lL09tbmlXZWIvQXJvcmEvVGl6ZW4vTm9raWFcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGRvbGZpbilcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvbHBoaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0RvbHBoaW4nXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLygoPzphbmRyb2lkLispY3Jtb3xjcmlvcylcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaHJvbWUgZm9yIEFuZHJvaWQvaU9TXG4gICAgICAgICAgICBdLCBbW05BTUUsICdDaHJvbWUnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb2FzdClcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPcGVyYSBDb2FzdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEgQ29hc3QnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL2Z4aW9zXFwvKFtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IGZvciBpT1NcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0ZpcmVmb3gnXV0sIFtcblxuICAgICAgICAgICAgL3ZlcnNpb25cXC8oW1xcd1xcLl0rKS4rP21vYmlsZVxcL1xcdytcXHMoc2FmYXJpKS9pICAgICAgICAgICAgICAgICAgICAgICAvLyBNb2JpbGUgU2FmYXJpXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdNb2JpbGUgU2FmYXJpJ11dLCBbXG5cbiAgICAgICAgICAgIC92ZXJzaW9uXFwvKFtcXHdcXC5dKykuKz8obW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpL2kgICAgICAgICAgICAgICAgICAgIC8vIFNhZmFyaSAmIFNhZmFyaSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXSwgW1xuXG4gICAgICAgICAgICAvd2Via2l0Lis/KGdzYSlcXC8oW1xcd1xcLl0rKS4rPyhtb2JpbGVcXHM/c2FmYXJpfHNhZmFyaSkoXFwvW1xcd1xcLl0rKS9pICAvLyBHb29nbGUgU2VhcmNoIEFwcGxpYW5jZSBvbiBpT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0dTQSddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvd2Via2l0Lis/KG1vYmlsZVxccz9zYWZhcml8c2FmYXJpKShcXC9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAvLyBTYWZhcmkgPCAzLjBcbiAgICAgICAgICAgIF0sIFtOQU1FLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5icm93c2VyLm9sZHNhZmFyaS52ZXJzaW9uXV0sIFtcblxuICAgICAgICAgICAgLyhrb25xdWVyb3IpXFwvKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLb25xdWVyb3JcbiAgICAgICAgICAgIC8od2Via2l0fGtodG1sKVxcLyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBHZWNrbyBiYXNlZFxuICAgICAgICAgICAgLyhuYXZpZ2F0b3J8bmV0c2NhcGUpXFwvKFtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOZXRzY2FwZVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnTmV0c2NhcGUnXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oc3dpZnRmb3gpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3dpZnRmb3hcbiAgICAgICAgICAgIC8oaWNlZHJhZ29ufGljZXdlYXNlbHxjYW1pbm98Y2hpbWVyYXxmZW5uZWN8bWFlbW9cXHNicm93c2VyfG1pbmltb3xjb25rZXJvcilbXFwvXFxzXT8oW1xcd1xcLlxcK10rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJY2VEcmFnb24vSWNld2Vhc2VsL0NhbWluby9DaGltZXJhL0Zlbm5lYy9NYWVtby9NaW5pbW8vQ29ua2Vyb3JcbiAgICAgICAgICAgIC8oZmlyZWZveHxzZWFtb25rZXl8ay1tZWxlb258aWNlY2F0fGljZWFwZXxmaXJlYmlyZHxwaG9lbml4fHBhbGVtb29ufGJhc2lsaXNrfHdhdGVyZm94KVxcLyhbXFx3XFwuLV0rKSQvaSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94L1NlYU1vbmtleS9LLU1lbGVvbi9JY2VDYXQvSWNlQXBlL0ZpcmViaXJkL1Bob2VuaXhcbiAgICAgICAgICAgIC8obW96aWxsYSlcXC8oW1xcd1xcLl0rKS4rcnZcXDouK2dlY2tvXFwvXFxkKy9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW96aWxsYVxuXG4gICAgICAgICAgICAvLyBPdGhlclxuICAgICAgICAgICAgLyhwb2xhcmlzfGx5bnh8ZGlsbG98aWNhYnxkb3Jpc3xhbWF5YXx3M218bmV0c3VyZnxzbGVpcG5pcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQb2xhcmlzL0x5bngvRGlsbG8vaUNhYi9Eb3Jpcy9BbWF5YS93M20vTmV0U3VyZi9TbGVpcG5pclxuICAgICAgICAgICAgLyhsaW5rcylcXHNcXCgoW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGlua3NcbiAgICAgICAgICAgIC8oZ29icm93c2VyKVxcLz8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29Ccm93c2VyXG4gICAgICAgICAgICAvKGljZVxccz9icm93c2VyKVxcL3Y/KFtcXHdcXC5fXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQ0UgQnJvd3NlclxuICAgICAgICAgICAgLyhtb3NhaWMpW1xcL1xcc10oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9zYWljXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cblxuICAgICAgICAgICAgLyogLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAgICAgICAvLyBNZWRpYSBwbGF5ZXJzIEJFR0lOXG4gICAgICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICAgICAgICAgICAgLCBbXG5cbiAgICAgICAgICAgIC8oYXBwbGUoPzpjb3JlbWVkaWF8KSlcXC8oKFxcZCspW1xcd1xcLl9dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQXBwbGUgQ29yZU1lZGlhXG4gICAgICAgICAgICAvKGNvcmVtZWRpYSkgdigoXFxkKylbXFx3XFwuX10rKS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhhcXVhbHVuZ3xseXNzbmF8YnNwbGF5ZXIpXFwvKChcXGQrKT9bXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgLy8gQXF1YWx1bmcvTHlzc25hL0JTUGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhhcmVzfG9zc3Byb3h5KVxccygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXJlcy9PU1NQcm94eVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oYXVkYWNpb3VzfGF1ZGltdXNpY3N0cmVhbXxhbWFyb2t8YmFzc3xjb3JlfGRhbHZpa3xnbm9tZW1wbGF5ZXJ8bXVzaWMgb24gY29uc29sZXxuc3BsYXllcnxwc3AtaW50ZXJuZXRyYWRpb3BsYXllcnx2aWRlb3MpXFwvKChcXGQrKVtcXHdcXC4tXSspL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF1ZGFjaW91cy9BdWRpTXVzaWNTdHJlYW0vQW1hcm9rL0JBU1MvT3BlbkNPUkUvRGFsdmlrL0dub21lTXBsYXllci9Nb0NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTlNQbGF5ZXIvUFNQLUludGVybmV0UmFkaW9QbGF5ZXIvVmlkZW9zXG4gICAgICAgICAgICAvKGNsZW1lbnRpbmV8bXVzaWMgcGxheWVyIGRhZW1vbilcXHMoKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAvLyBDbGVtZW50aW5lL01QRFxuICAgICAgICAgICAgLyhsZyBwbGF5ZXJ8bmV4cGxheWVyKVxccygoXFxkKylbXFxkXFwuXSspL2ksXG4gICAgICAgICAgICAvcGxheWVyXFwvKG5leHBsYXllcnxsZyBwbGF5ZXIpXFxzKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgLy8gTmV4UGxheWVyL0xHIFBsYXllclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKG5leHBsYXllcilcXHMoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOZXhwbGF5ZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGZscnApXFwvKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGbGlwIFBsYXllclxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnRmxpcCBQbGF5ZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhmc3RyZWFtfG5hdGl2ZWhvc3R8cXVlcnlzZWVrc3BpZGVyfGlhLWFyY2hpdmVyfGZhY2Vib29rZXh0ZXJuYWxoaXQpL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRlN0cmVhbS9OYXRpdmVIb3N0L1F1ZXJ5U2Vla1NwaWRlci9JQSBBcmNoaXZlci9mYWNlYm9va2V4dGVybmFsaGl0XG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcblxuICAgICAgICAgICAgLyhnc3RyZWFtZXIpIHNvdXBodHRwc3JjICg/OlxcKFteXFwpXStcXCkpezAsMX0gbGlic291cFxcLygoXFxkKylbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdzdHJlYW1lclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjIHN0cmVhbWluZyBwbGF5ZXIpXFxzW1xcd19dK1xcc1xcL1xccygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAvLyBIVEMgU3RyZWFtaW5nIFBsYXllclxuICAgICAgICAgICAgLyhqYXZhfHB5dGhvbi11cmxsaWJ8cHl0aG9uLXJlcXVlc3RzfHdnZXR8bGliY3VybClcXC8oKFxcZCspW1xcd1xcLi1fXSspL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEphdmEvdXJsbGliL3JlcXVlc3RzL3dnZXQvY1VSTFxuICAgICAgICAgICAgLyhsYXZmKSgoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMYXZmIChGRk1QRUcpXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhodGNfb25lX3MpXFwvKChcXGQrKVtcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFRDIE9uZSBTXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikoPzpcXHN8XFwvKSg/Oig/OnNoZXJweWEtKXswLDF9c3ZuKSg/Oi18XFxzKShyXFxkKyg/Oi1cXGQrW1xcd1xcLi1dKyl7MCwxfSkvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyIFNWTlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikoPzpcXHN8XFwvfFt1bmtvdy1dKykoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhtcGxheWVyKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyIChubyBvdGhlciBpbmZvKVxuICAgICAgICAgICAgLyh5b3VybXV6ZSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBZb3VyTXV6ZVxuICAgICAgICAgICAgLyhtZWRpYSBwbGF5ZXIgY2xhc3NpY3xuZXJvIHNob3d0aW1lKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNZWRpYSBQbGF5ZXIgQ2xhc3NpYy9OZXJvIFNob3dUaW1lXG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcblxuICAgICAgICAgICAgLyhuZXJvICg/OmhvbWV8c2NvdXQpKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmVybyBIb21lL05lcm8gU2NvdXRcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG5va2lhXFxkKylcXC8oKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvXFxzKHNvbmdiaXJkKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29uZ2JpcmQvUGhpbGlwcy1Tb25nYmlyZFxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8od2luYW1wKTMgdmVyc2lvbiAoKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luYW1wXG4gICAgICAgICAgICAvKHdpbmFtcClcXHMoKFxcZCspW1xcd1xcLi1dKykvaSxcbiAgICAgICAgICAgIC8od2luYW1wKW1wZWdcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8ob2Ntcy1ib3R8dGFwaW5yYWRpb3x0dW5laW4gcmFkaW98dW5rbm93bnx3aW5hbXB8aW5saWdodCByYWRpbykvaSAgLy8gT0NNUy1ib3QvdGFwIGluIHJhZGlvL3R1bmVpbi91bmtub3duL3dpbmFtcCAobm8gb3RoZXIgaW5mbylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5saWdodCByYWRpb1xuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG5cbiAgICAgICAgICAgIC8ocXVpY2t0aW1lfHJtYXxyYWRpb2FwcHxyYWRpb2NsaWVudGFwcGxpY2F0aW9ufHNvdW5kdGFwfHRvdGVtfHN0YWdlZnJpZ2h0fHN0cmVhbWl1bSlcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRdWlja1RpbWUvUmVhbE1lZGlhL1JhZGlvQXBwL1JhZGlvQ2xpZW50QXBwbGljYXRpb24vXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvdW5kVGFwL1RvdGVtL1N0YWdlZnJpZ2h0L1N0cmVhbWl1bVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oc21wKSgoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU01QXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyh2bGMpIG1lZGlhIHBsYXllciAtIHZlcnNpb24gKChcXGQrKVtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAvLyBWTEMgVmlkZW9sYW5cbiAgICAgICAgICAgIC8odmxjKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLFxuICAgICAgICAgICAgLyh4Ym1jfGd2ZnN8eGluZXx4bW1zfGlyYXBwKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgLy8gWEJNQy9ndmZzL1hpbmUvWE1NUy9pcmFwcFxuICAgICAgICAgICAgLyhmb29iYXIyMDAwKVxcLygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRm9vYmFyMjAwMFxuICAgICAgICAgICAgLyhpdHVuZXMpXFwvKChcXGQrKVtcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVR1bmVzXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyh3bXBsYXllcilcXC8oKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBNZWRpYSBQbGF5ZXJcbiAgICAgICAgICAgIC8od2luZG93cy1tZWRpYS1wbGF5ZXIpXFwvKChcXGQrKVtcXHdcXC4tXSspL2lcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgLy0vZywgJyAnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL3dpbmRvd3NcXC8oKFxcZCspW1xcd1xcLi1dKykgdXBucFxcL1tcXGRcXC5dKyBkbG5hZG9jXFwvW1xcZFxcLl0rIChob21lIG1lZGlhIHNlcnZlcikvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaW5kb3dzIE1lZGlhIFNlcnZlclxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnV2luZG93cyddXSwgW1xuXG4gICAgICAgICAgICAvKGNvbVxcLnJpc2V1cHJhZGlvYWxhcm0pXFwvKChcXGQrKVtcXGRcXC5dKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmlzZVVQIFJhZGlvIEFsYXJtXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhyYWQuaW8pXFxzKChcXGQrKVtcXGRcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmFkLmlvXG4gICAgICAgICAgICAvKHJhZGlvLig/OmRlfGF0fGZyKSlcXHMoKFxcZCspW1xcZFxcLl0rKS9pXG4gICAgICAgICAgICBdLCBbW05BTUUsICdyYWQuaW8nXSwgVkVSU0lPTl1cblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gTWVkaWEgcGxheWVycyBFTkRcbiAgICAgICAgICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGNwdSA6IFtbXG5cbiAgICAgICAgICAgIC8oPzooYW1kfHgoPzooPzo4Nnw2NClbXy1dKT98d293fHdpbik2NClbO1xcKV0vaSAgICAgICAgICAgICAgICAgICAgIC8vIEFNRDY0XG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2FtZDY0J11dLCBbXG5cbiAgICAgICAgICAgIC8oaWEzMig/PTspKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUEzMiAocXVpY2t0aW1lKVxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIHV0aWwubG93ZXJpemVdXSwgW1xuXG4gICAgICAgICAgICAvKCg/OmlbMzQ2XXx4KTg2KVs7XFwpXS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQTMyXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2lhMzInXV0sIFtcblxuICAgICAgICAgICAgLy8gUG9ja2V0UEMgbWlzdGFrZW5seSBpZGVudGlmaWVkIGFzIFBvd2VyUENcbiAgICAgICAgICAgIC93aW5kb3dzXFxzKGNlfG1vYmlsZSk7XFxzcHBjOy9pXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2FybSddXSwgW1xuXG4gICAgICAgICAgICAvKCg/OnBwY3xwb3dlcnBjKSg/OjY0KT8pKD86XFxzbWFjfDt8XFwpKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUG93ZXJQQ1xuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIC9vd2VyLywgJycsIHV0aWwubG93ZXJpemVdXSwgW1xuXG4gICAgICAgICAgICAvKHN1bjRcXHcpWztcXCldL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU1BBUkNcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCAnc3BhcmMnXV0sIFtcblxuICAgICAgICAgICAgLygoPzphdnIzMnxpYTY0KD89OykpfDY4ayg/PVxcKSl8YXJtKD86NjR8KD89dlxcZCs7KSl8KD89YXRtZWxcXHMpYXZyfCg/OmlyaXh8bWlwc3xzcGFyYykoPzo2NCk/KD89Oyl8cGEtcmlzYykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQTY0LCA2OEssIEFSTS82NCwgQVZSLzMyLCBJUklYLzY0LCBNSVBTLzY0LCBTUEFSQy82NCwgUEEtUklTQ1xuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIHV0aWwubG93ZXJpemVdXVxuICAgICAgICBdLFxuXG4gICAgICAgIGRldmljZSA6IFtbXG5cbiAgICAgICAgICAgIC9cXCgoaXBhZHxwbGF5Ym9vayk7W1xcd1xcc1xcKTstXSsocmltfGFwcGxlKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQYWQvUGxheUJvb2tcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgVkVORE9SLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FwcGxlY29yZW1lZGlhXFwvW1xcd1xcLl0rIFxcKChpcGFkKS8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVBhZFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQXBwbGUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oYXBwbGVcXHN7MCwxfXR2KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFwcGxlIFRWXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnQXBwbGUgVFYnXSwgW1ZFTkRPUiwgJ0FwcGxlJ11dLCBbXG5cbiAgICAgICAgICAgIC8oYXJjaG9zKVxccyhnYW1lcGFkMj8pL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFyY2hvc1xuICAgICAgICAgICAgLyhocCkuKyh0b3VjaHBhZCkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIUCBUb3VjaFBhZFxuICAgICAgICAgICAgLyhocCkuKyh0YWJsZXQpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIUCBUYWJsZXRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvXFxzKG5vb2spW1xcd1xcc10rYnVpbGRcXC8oXFx3KykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9va1xuICAgICAgICAgICAgLyhkZWxsKVxccyhzdHJlYVtrcHJcXHNcXGRdKltcXGRrb10pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVsbCBTdHJlYWtcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhrZltBLXpdKylcXHNidWlsZFxcLy4rc2lsa1xcLy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLaW5kbGUgRmlyZSBIRFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhzZHxrZilbMDM0OWhpam9yc3R1d10rXFxzYnVpbGRcXC8uK3NpbGtcXC8vaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlIFBob25lXG4gICAgICAgICAgICBdLCBbW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5hbWF6b24ubW9kZWxdLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFwoKGlwW2hvbmVkfFxcc1xcdypdKyk7LisoYXBwbGUpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQb2QvaVBob25lXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFZFTkRPUiwgW1RZUEUsIE1PQklMRV1dLCBbXG4gICAgICAgICAgICAvXFwoKGlwW2hvbmVkfFxcc1xcdypdKyk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQb2QvaVBob25lXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBcHBsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhibGFja2JlcnJ5KVtcXHMtXT8oXFx3KykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnlcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeXxiZW5xfHBhbG0oPz1cXC0pfHNvbnllcmljc3NvbnxhY2VyfGFzdXN8ZGVsbHxtZWl6dXxtb3Rvcm9sYXxwb2x5dHJvbilbXFxzXy1dPyhbXFx3LV0qKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCZW5RL1BhbG0vU29ueS1Fcmljc3Nvbi9BY2VyL0FzdXMvRGVsbC9NZWl6dS9Nb3Rvcm9sYS9Qb2x5dHJvblxuICAgICAgICAgICAgLyhocClcXHMoW1xcd1xcc10rXFx3KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgaVBBUVxuICAgICAgICAgICAgLyhhc3VzKS0/KFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXN1c1xuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL1xcKGJiMTA7XFxzKFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCbGFja0JlcnJ5IDEwXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdCbGFja0JlcnJ5J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBc3VzIFRhYmxldHNcbiAgICAgICAgICAgIC9hbmRyb2lkLisodHJhbnNmb1twcmltZVxcc117NCwxMH1cXHNcXHcrfGVlZXBjfHNsaWRlclxcc1xcdyt8bmV4dXMgN3xwYWRmb25lKS9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBc3VzJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKHNvbnkpXFxzKHRhYmxldFxcc1twc10pXFxzYnVpbGRcXC8vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueVxuICAgICAgICAgICAgLyhzb255KT8oPzpzZ3AuKylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NvbnknXSwgW01PREVMLCAnWHBlcmlhIFRhYmxldCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcbiAgICAgICAgICAgIC9hbmRyb2lkLitcXHMoW2MtZ11cXGR7NH18c29bLWxdXFx3KylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFxzKG91eWEpXFxzL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3V5YVxuICAgICAgICAgICAgLyhuaW50ZW5kbylcXHMoW3dpZHMzdV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG9cbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKHNoaWVsZClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOdmlkaWFcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ052aWRpYSddLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC8ocGxheXN0YXRpb25cXHNbMzRwb3J0YWJsZXZpXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYXlzdGF0aW9uXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBDT05TT0xFXV0sIFtcblxuICAgICAgICAgICAgLyhzcHJpbnRcXHMoXFx3KykpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNwcmludCBQaG9uZXNcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQudmVuZG9yXSwgW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQubW9kZWxdLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhsZW5vdm8pXFxzPyhTKD86NTAwMHw2MDAwKSsoPzpbLV1bXFx3K10pKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92byB0YWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjKVs7X1xccy1dKyhbXFx3XFxzXSsoPz1cXCkpfFxcdyspKi9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIVENcbiAgICAgICAgICAgIC8oenRlKS0oXFx3KikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURVxuICAgICAgICAgICAgLyhhbGNhdGVsfGdlZWtzcGhvbmV8bGVub3ZvfG5leGlhbnxwYW5hc29uaWN8KD89O1xccylzb255KVtfXFxzLV0/KFtcXHctXSopL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxjYXRlbC9HZWVrc1Bob25lL0xlbm92by9OZXhpYW4vUGFuYXNvbmljL1NvbnlcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIFtNT0RFTCwgL18vZywgJyAnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8obmV4dXNcXHM5KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhUQyBOZXh1cyA5XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdIVEMnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9kXFwvaHVhd2VpKFtcXHdcXHMtXSspWztcXCldL2ksXG4gICAgICAgICAgICAvKG5leHVzXFxzNnApL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdWF3ZWlcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0h1YXdlaSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtaWNyb3NvZnQpO1xccyhsdW1pYVtcXHNcXHddKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaWNyb3NvZnQgTHVtaWFcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL1tcXHNcXCg7XSh4Ym94KD86XFxzb25lKT8pW1xcc1xcKTtdL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBYYm94XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNaWNyb3NvZnQnXSwgW1RZUEUsIENPTlNPTEVdXSwgW1xuICAgICAgICAgICAgLyhraW5cXC5bb25ldHddezN9KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWljcm9zb2Z0IEtpblxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgL1xcLi9nLCAnICddLCBbVkVORE9SLCAnTWljcm9zb2Z0J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1vdG9yb2xhXG4gICAgICAgICAgICAvXFxzKG1pbGVzdG9uZXxkcm9pZCg/OlsyLTR4XXxcXHMoPzpiaW9uaWN8eDJ8cHJvfHJhenIpKT86PyhcXHM0Zyk/KVtcXHdcXHNdK2J1aWxkXFwvL2ksXG4gICAgICAgICAgICAvbW90W1xccy1dPyhcXHcqKS9pLFxuICAgICAgICAgICAgLyhYVFxcZHszLDR9KSBidWlsZFxcLy9pLFxuICAgICAgICAgICAgLyhuZXh1c1xcczYpL2lcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01vdG9yb2xhJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuK1xccyhtejYwXFxkfHhvb21bXFxzMl17MCwyfSlcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNb3Rvcm9sYSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2hiYnR2XFwvXFxkK1xcLlxcZCtcXC5cXGQrXFxzK1xcKFtcXHdcXHNdKjtcXHMqKFxcd1teO10qKTsoW147XSopL2kgICAgICAgICAgICAvLyBIYmJUViBkZXZpY2VzXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgdXRpbC50cmltXSwgW01PREVMLCB1dGlsLnRyaW1dLCBbVFlQRSwgU01BUlRUVl1dLCBbXG5cbiAgICAgICAgICAgIC9oYmJ0di4rbWFwbGU7KFxcZCspL2lcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIC9eLywgJ1NtYXJ0VFYnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFNNQVJUVFZdXSwgW1xuXG4gICAgICAgICAgICAvXFwoZHR2W1xcKTtdLisoYXF1b3MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2hhcnBcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1NoYXJwJ10sIFtUWVBFLCBTTUFSVFRWXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKygoc2NoLWlbODldMFxcZHxzaHctbTM4MHN8Z3QtcFxcZHs0fXxndC1uXFxkK3xzZ2gtdDhbNTZdOXxuZXh1cyAxMCkpL2ksXG4gICAgICAgICAgICAvKChTTS1UXFx3KykpL2lcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnU2Ftc3VuZyddLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZ1xuICAgICAgICAgICAgL3NtYXJ0LXR2Lisoc2Ftc3VuZykvaVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgW1RZUEUsIFNNQVJUVFZdLCBNT0RFTF0sIFtcbiAgICAgICAgICAgIC8oKHNbY2dwXWgtXFx3K3xndC1cXHcrfGdhbGF4eVxcc25leHVzfHNtLVxcd1tcXHdcXGRdKykpL2ksXG4gICAgICAgICAgICAvKHNhbVtzdW5nXSopW1xccy1dKihcXHcrLT9bXFx3LV0qKS9pLFxuICAgICAgICAgICAgL3NlYy0oKHNnaFxcdyspKS9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvc2llLShcXHcqKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaWVtZW5zXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTaWVtZW5zJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKG1hZW1vfG5va2lhKS4qKG45MDB8bHVtaWFcXHNcXGQrKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIC8obm9raWEpW1xcc18tXT8oW1xcdy1dKikvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdOb2tpYSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkXFxzM1xcLltcXHNcXHc7LV17MTB9KGFcXGR7M30pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBY2VyXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBY2VyJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKFt2bF1rXFwtP1xcZHszfSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTEcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZFxcczNcXC5bXFxzXFx3Oy1dezEwfShsZz8pLShbMDZjdjldezMsNH0pL2kgICAgICAgICAgICAgICAgICAgICAvLyBMRyBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnTEcnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhsZykgbmV0Y2FzdFxcLnR2L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTEcgU21hcnRUVlxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBTTUFSVFRWXV0sIFtcbiAgICAgICAgICAgIC8obmV4dXNcXHNbNDVdKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHXG4gICAgICAgICAgICAvbGdbZTtcXHNcXC8tXSsoXFx3KikvaSxcbiAgICAgICAgICAgIC9hbmRyb2lkLitsZyhcXC0/W1xcZFxcd10rKVxccytidWlsZC9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdMRyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKyhpZGVhdGFiW2EtejAtOVxcLVxcc10rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92b1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTGVub3ZvJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvbGludXg7LisoKGpvbGxhKSk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEpvbGxhXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8oKHBlYmJsZSkpYXBwXFwvW1xcZFxcLl0rXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBlYmJsZVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBXRUFSQUJMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKG9wcG8pXFxzPyhbXFx3XFxzXSspXFxzYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPUFBPXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9jcmtleS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIENocm9tZWNhc3RcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdDaHJvbWVjYXN0J10sIFtWRU5ET1IsICdHb29nbGUnXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMoZ2xhc3MpXFxzXFxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHb29nbGUgR2xhc3NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dvb2dsZSddLCBbVFlQRSwgV0VBUkFCTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhwaXhlbCBjKVxccy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIFBpeGVsIENcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dvb2dsZSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMocGl4ZWwgeGx8cGl4ZWwpXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdvb2dsZSBQaXhlbFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnR29vZ2xlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhcXHcrKVxccytidWlsZFxcL2htXFwxL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWGlhb21pIEhvbmdtaSAnbnVtZXJpYycgbW9kZWxzXG4gICAgICAgICAgICAvYW5kcm9pZC4rKGhtW1xcc1xcLV9dKm5vdGU/W1xcc19dKig/OlxcZFxcdyk/KVxccytidWlsZC9pLCAgICAgICAgICAgICAgIC8vIFhpYW9taSBIb25nbWlcbiAgICAgICAgICAgIC9hbmRyb2lkLisobWlbXFxzXFwtX10qKD86b25lfG9uZVtcXHNfXXBsdXN8bm90ZSBsdGUpP1tcXHNfXSooPzpcXGQ/XFx3PylbXFxzX10qKD86cGx1cyk/KVxccytidWlsZC9pLCAgICAvLyBYaWFvbWkgTWlcbiAgICAgICAgICAgIC9hbmRyb2lkLisocmVkbWlbXFxzXFwtX10qKD86bm90ZSk/KD86W1xcc19dKltcXHdcXHNdKykpXFxzK2J1aWxkL2kgICAgICAgLy8gUmVkbWkgUGhvbmVzXG4gICAgICAgICAgICBdLCBbW01PREVMLCAvXy9nLCAnICddLCBbVkVORE9SLCAnWGlhb21pJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuKyhtaVtcXHNcXC1fXSooPzpwYWQpKD86W1xcc19dKltcXHdcXHNdKykpXFxzK2J1aWxkL2kgICAgICAgICAgICAvLyBNaSBQYWQgdGFibGV0c1xuICAgICAgICAgICAgXSxbW01PREVMLCAvXy9nLCAnICddLCBbVkVORE9SLCAnWGlhb21pJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMobVsxLTVdXFxzbm90ZSlcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNZWl6dSBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01laXp1J10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rYTAwMCgxKVxccytidWlsZC9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmVQbHVzXG4gICAgICAgICAgICAvYW5kcm9pZC4rb25lcGx1c1xccyhhXFxkezR9KVxccytidWlsZC9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdPbmVQbHVzJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihSQ1RbXFxkXFx3XSspXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUkNBIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1JDQSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXFxzXSsoVmVudWVbXFxkXFxzXXsyLDd9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGwgVmVudWUgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnRGVsbCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooUVtUfE1dW1xcZFxcd10rKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFZlcml6b24gVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdWZXJpem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhCYXJuZXNbJlxcc10rTm9ibGVcXHMrfEJOW1JUXSkoVj8uKilcXHMrYnVpbGQvaSAgICAgLy8gQmFybmVzICYgTm9ibGUgVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0Jhcm5lcyAmIE5vYmxlJ10sIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccysoVE1cXGR7M30uKlxcYilcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJhcm5lcyAmIE5vYmxlIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTnVWaXNpb24nXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKGs4OClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBaVEUgSyBTZXJpZXMgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdaVEUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKGdlblxcZHszfSlcXHMrYnVpbGQuKjQ5aC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN3aXNzIEdFTiBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1N3aXNzJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKih6dXJcXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTd2lzcyBaVVIgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTd2lzcyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooKFpla2kpP1RCLipcXGIpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWmVraSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdaZWtpJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKGFuZHJvaWQpLitbO1xcL11cXHMrKFtZUl1cXGR7Mn0pXFxzK2J1aWxkL2ksXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhEcmFnb25bXFwtXFxzXStUb3VjaFxccyt8RFQpKFxcd3s1fSlcXHNidWlsZC9pICAgICAgICAvLyBEcmFnb24gVG91Y2ggVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0RyYWdvbiBUb3VjaCddLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKE5TLT9cXHd7MCw5fSlcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluc2lnbmlhIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0luc2lnbmlhJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKigoTlh8TmV4dCktP1xcd3swLDl9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAvLyBOZXh0Qm9vayBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdOZXh0Qm9vayddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooWHRyZW1lXFxfKT8oVigxWzA0NV18MlswMTVdfDMwfDQwfDYwfDdbMDVdfDkwKSlcXHMrYnVpbGQvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdWb2ljZSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbICAgICAgICAgICAgICAgICAgICAvLyBWb2ljZSBYdHJlbWUgUGhvbmVzXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKExWVEVMXFwtKT8oVjFbMTJdKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgLy8gTHZUZWwgUGhvbmVzXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0x2VGVsJ10sIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooVigxMDBNRHw3MDBOQXw3MDExfDkxN0cpLipcXGIpXFxzK2J1aWxkL2kgICAgICAgICAgLy8gRW52aXplbiBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdFbnZpemVuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihMZVtcXHNcXC1dK1BhbilbXFxzXFwtXSsoXFx3ezEsOX0pXFxzK2J1aWxkL2kgICAgICAgICAgLy8gTGUgUGFuIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooVHJpb1tcXHNcXC1dKi4qKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hY2hTcGVlZCBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNYWNoU3BlZWQnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFRyaW5pdHkpW1xcLVxcc10qKFRcXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgLy8gVHJpbml0eSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqVFVfKDE0OTEpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUm90b3IgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnUm90b3InXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLisoS1MoLispKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFtYXpvbiBLaW5kbGUgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKEdpZ2FzZXQpW1xcc1xcLV0rKFFcXHd7MSw5fSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAvLyBHaWdhc2V0IFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL1xccyh0YWJsZXR8dGFiKVs7XFwvXS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVuaWRlbnRpZmlhYmxlIFRhYmxldFxuICAgICAgICAgICAgL1xccyhtb2JpbGUpKD86WztcXC9dfFxcc3NhZmFyaSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVbmlkZW50aWZpYWJsZSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtbVFlQRSwgdXRpbC5sb3dlcml6ZV0sIFZFTkRPUiwgTU9ERUxdLCBbXG5cbiAgICAgICAgICAgIC8oYW5kcm9pZFtcXHdcXC5cXHNcXC1dezAsOX0pOy4rYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQW5kcm9pZCBEZXZpY2VcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dlbmVyaWMnXV1cblxuXG4gICAgICAgIC8qLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgICAgICAgIC8vIFRPRE86IG1vdmUgdG8gc3RyaW5nIG1hcFxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAgICAgICAvKEM2NjAzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbnkgWHBlcmlhIFogQzY2MDNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdYcGVyaWEgWiBDNjYwMyddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oQzY5MDMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueSBYcGVyaWEgWiAxXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnWHBlcmlhIFogMSddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhTTS1HOTAwW0Z8SF0pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBTNVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBTNSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzcxMDIpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgR3JhbmQgMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCAyJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1HNTMwSCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBHcmFuZCBQcmltZVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCBQcmltZSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzMxM0haKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBWJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1UODA1KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBUYWIgUyAxMC41XG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiBTIDEwLjUnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvKFNNLUc4MDBGKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhbXN1bmcgR2FsYXh5IFM1IE1pbmlcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdHYWxheHkgUzUgTWluaSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tVDMxMSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVGFiIDMgOC4wXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiAzIDguMCddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhUM0MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBUM0NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBUMUpcXCspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWR2YW4gVmFuZHJvaWQgVDFKK1xuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1ZhbmRyb2lkIFQxSisnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBTNEEpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBTNEFcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdWYW5kcm9pZCBTNEEnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKFY5NzJNKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURSBWOTcyTVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnWlRFJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKGktbW9iaWxlKVxccyhJUVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhJUTYuMykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUSBJUSA2LjNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdJUSA2LjMnXSwgW1ZFTkRPUiwgJ2ktbW9iaWxlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLW1vYmlsZSlcXHMoaS1zdHlsZVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaS1tb2JpbGUgaS1TVFlMRVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLVNUWUxFMi4xKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBpLVNUWUxFIDIuMVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ2ktU1RZTEUgMi4xJ10sIFtWRU5ET1IsICdpLW1vYmlsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1RvdWNoIExBSSA1MTInXSwgW1ZFTkRPUiwgJ21vYmlpc3RhciddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gRU5EIFRPRE9cbiAgICAgICAgICAgIC8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGVuZ2luZSA6IFtbXG5cbiAgICAgICAgICAgIC93aW5kb3dzLitcXHNlZGdlXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVkZ2VIVE1MXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdFZGdlSFRNTCddXSwgW1xuXG4gICAgICAgICAgICAvKHByZXN0bylcXC8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZXN0b1xuICAgICAgICAgICAgLyh3ZWJraXR8dHJpZGVudHxuZXRmcm9udHxuZXRzdXJmfGFtYXlhfGx5bnh8dzNtKVxcLyhbXFx3XFwuXSspL2ksICAgICAvLyBXZWJLaXQvVHJpZGVudC9OZXRGcm9udC9OZXRTdXJmL0FtYXlhL0x5bngvdzNtXG4gICAgICAgICAgICAvKGtodG1sfHRhc21hbnxsaW5rcylbXFwvXFxzXVxcKD8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS0hUTUwvVGFzbWFuL0xpbmtzXG4gICAgICAgICAgICAvKGljYWIpW1xcL1xcc10oWzIzXVxcLltcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaUNhYlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9ydlxcOihbXFx3XFwuXXsxLDl9KS4rKGdlY2tvKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2Vja29cbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXVxuICAgICAgICBdLFxuXG4gICAgICAgIG9zIDogW1tcblxuICAgICAgICAgICAgLy8gV2luZG93cyBiYXNlZFxuICAgICAgICAgICAgL21pY3Jvc29mdFxccyh3aW5kb3dzKVxccyh2aXN0YXx4cCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgKGlUdW5lcylcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyh3aW5kb3dzKVxcc250XFxzNlxcLjI7XFxzKGFybSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBSVFxuICAgICAgICAgICAgLyh3aW5kb3dzXFxzcGhvbmUoPzpcXHNvcykqKVtcXHNcXC9dPyhbXFxkXFwuXFxzXFx3XSopL2ksICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgUGhvbmVcbiAgICAgICAgICAgIC8od2luZG93c1xcc21vYmlsZXx3aW5kb3dzKVtcXHNcXC9dPyhbbnRjZVxcZFxcLlxcc10rXFx3KS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgW1ZFUlNJT04sIG1hcHBlci5zdHIsIG1hcHMub3Mud2luZG93cy52ZXJzaW9uXV0sIFtcbiAgICAgICAgICAgIC8od2luKD89M3w5fG4pfHdpblxcczl4XFxzKShbbnRcXGRcXC5dKykvaVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnV2luZG93cyddLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5vcy53aW5kb3dzLnZlcnNpb25dXSwgW1xuXG4gICAgICAgICAgICAvLyBNb2JpbGUvRW1iZWRkZWQgT1NcbiAgICAgICAgICAgIC9cXCgoYmIpKDEwKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnkgMTBcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0JsYWNrQmVycnknXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeSlcXHcqXFwvPyhbXFx3XFwuXSopL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrYmVycnlcbiAgICAgICAgICAgIC8odGl6ZW4pW1xcL1xcc10oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRpemVuXG4gICAgICAgICAgICAvKGFuZHJvaWR8d2Vib3N8cGFsbVxcc29zfHFueHxiYWRhfHJpbVxcc3RhYmxldFxcc29zfG1lZWdvfGNvbnRpa2kpW1xcL1xccy1dPyhbXFx3XFwuXSopL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFuZHJvaWQvV2ViT1MvUGFsbS9RTlgvQmFkYS9SSU0vTWVlR28vQ29udGlraVxuICAgICAgICAgICAgL2xpbnV4Oy4rKHNhaWxmaXNoKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYWlsZmlzaCBPU1xuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKHN5bWJpYW5cXHM/b3N8c3ltYm9zfHM2MCg/PTspKVtcXC9cXHMtXT8oW1xcd1xcLl0qKS9pICAgICAgICAgICAgICAgICAgLy8gU3ltYmlhblxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU3ltYmlhbiddLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgL1xcKChzZXJpZXM0MCk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2VyaWVzIDQwXG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcbiAgICAgICAgICAgIC9tb3ppbGxhLitcXChtb2JpbGU7LitnZWNrby4rZmlyZWZveC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0ZpcmVmb3ggT1MnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gQ29uc29sZVxuICAgICAgICAgICAgLyhuaW50ZW5kb3xwbGF5c3RhdGlvbilcXHMoW3dpZHMzNHBvcnRhYmxldnVdKykvaSwgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG8vUGxheXN0YXRpb25cblxuICAgICAgICAgICAgLy8gR05VL0xpbnV4IGJhc2VkXG4gICAgICAgICAgICAvKG1pbnQpW1xcL1xcc1xcKF0/KFxcdyopL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaW50XG4gICAgICAgICAgICAvKG1hZ2VpYXx2ZWN0b3JsaW51eClbO1xcc10vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWdlaWEvVmVjdG9yTGludXhcbiAgICAgICAgICAgIC8oam9saXxba3hsbl0/dWJ1bnR1fGRlYmlhbnxzdXNlfG9wZW5zdXNlfGdlbnRvb3woPz1cXHMpYXJjaHxzbGFja3dhcmV8ZmVkb3JhfG1hbmRyaXZhfGNlbnRvc3xwY2xpbnV4b3N8cmVkaGF0fHplbndhbGt8bGlucHVzKVtcXC9cXHMtXT8oPyFjaHJvbSkoW1xcd1xcLi1dKikvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSm9saS9VYnVudHUvRGViaWFuL1NVU0UvR2VudG9vL0FyY2gvU2xhY2t3YXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZlZG9yYS9NYW5kcml2YS9DZW50T1MvUENMaW51eE9TL1JlZEhhdC9aZW53YWxrL0xpbnB1c1xuICAgICAgICAgICAgLyhodXJkfGxpbnV4KVxccz8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdXJkL0xpbnV4XG4gICAgICAgICAgICAvKGdudSlcXHM/KFtcXHdcXC5dKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdOVVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oY3JvcylcXHNbXFx3XStcXHMoW1xcd1xcLl0rXFx3KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21pdW0gT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0Nocm9taXVtIE9TJ10sIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgLyhzdW5vcylcXHM/KFtcXHdcXC5cXGRdKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU29sYXJpcyddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBCU0QgYmFzZWRcbiAgICAgICAgICAgIC9cXHMoW2ZyZW50b3BjLV17MCw0fWJzZHxkcmFnb25mbHkpXFxzPyhbXFx3XFwuXSopL2kgICAgICAgICAgICAgICAgICAgIC8vIEZyZWVCU0QvTmV0QlNEL09wZW5CU0QvUEMtQlNEL0RyYWdvbkZseVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLyhoYWlrdSlcXHMoXFx3KykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhhaWt1XG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sW1xuXG4gICAgICAgICAgICAvY2ZuZXR3b3JrXFwvLitkYXJ3aW4vaSxcbiAgICAgICAgICAgIC9pcFtob25lYWRdezIsNH0oPzouKm9zXFxzKFtcXHddKylcXHNsaWtlXFxzbWFjfDtcXHNvcGVyYSkvaSAgICAgICAgICAgICAvLyBpT1NcbiAgICAgICAgICAgIF0sIFtbVkVSU0lPTiwgL18vZywgJy4nXSwgW05BTUUsICdpT1MnXV0sIFtcblxuICAgICAgICAgICAgLyhtYWNcXHNvc1xcc3gpXFxzPyhbXFx3XFxzXFwuXSopL2ksXG4gICAgICAgICAgICAvKG1hY2ludG9zaHxtYWMoPz1fcG93ZXJwYylcXHMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWMgT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ01hYyBPUyddLCBbVkVSU0lPTiwgL18vZywgJy4nXV0sIFtcblxuICAgICAgICAgICAgLy8gT3RoZXJcbiAgICAgICAgICAgIC8oKD86b3Blbik/c29sYXJpcylbXFwvXFxzLV0/KFtcXHdcXC5dKikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbGFyaXNcbiAgICAgICAgICAgIC8oYWl4KVxccygoXFxkKSg/PVxcLnxcXCl8XFxzKVtcXHdcXC5dKSovaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFJWFxuICAgICAgICAgICAgLyhwbGFuXFxzOXxtaW5peHxiZW9zfG9zXFwvMnxhbWlnYW9zfG1vcnBob3N8cmlzY1xcc29zfG9wZW52bXMpL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYW45L01pbml4L0JlT1MvT1MyL0FtaWdhT1MvTW9ycGhPUy9SSVNDT1MvT3BlblZNU1xuICAgICAgICAgICAgLyh1bml4KVxccz8oW1xcd1xcLl0qKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVTklYXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cbiAgICAgICAgXVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQ29uc3RydWN0b3JcbiAgICAvLy8vLy8vLy8vLy8vLy8vXG4gICAgLypcbiAgICB2YXIgQnJvd3NlciA9IGZ1bmN0aW9uIChuYW1lLCB2ZXJzaW9uKSB7XG4gICAgICAgIHRoaXNbTkFNRV0gPSBuYW1lO1xuICAgICAgICB0aGlzW1ZFUlNJT05dID0gdmVyc2lvbjtcbiAgICB9O1xuICAgIHZhciBDUFUgPSBmdW5jdGlvbiAoYXJjaCkge1xuICAgICAgICB0aGlzW0FSQ0hJVEVDVFVSRV0gPSBhcmNoO1xuICAgIH07XG4gICAgdmFyIERldmljZSA9IGZ1bmN0aW9uICh2ZW5kb3IsIG1vZGVsLCB0eXBlKSB7XG4gICAgICAgIHRoaXNbVkVORE9SXSA9IHZlbmRvcjtcbiAgICAgICAgdGhpc1tNT0RFTF0gPSBtb2RlbDtcbiAgICAgICAgdGhpc1tUWVBFXSA9IHR5cGU7XG4gICAgfTtcbiAgICB2YXIgRW5naW5lID0gQnJvd3NlcjtcbiAgICB2YXIgT1MgPSBCcm93c2VyO1xuICAgICovXG4gICAgdmFyIFVBUGFyc2VyID0gZnVuY3Rpb24gKHVhc3RyaW5nLCBleHRlbnNpb25zKSB7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB1YXN0cmluZyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGV4dGVuc2lvbnMgPSB1YXN0cmluZztcbiAgICAgICAgICAgIHVhc3RyaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFVBUGFyc2VyKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBVQVBhcnNlcih1YXN0cmluZywgZXh0ZW5zaW9ucykuZ2V0UmVzdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdWEgPSB1YXN0cmluZyB8fCAoKHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yICYmIHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50KSA/IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50IDogRU1QVFkpO1xuICAgICAgICB2YXIgcmd4bWFwID0gZXh0ZW5zaW9ucyA/IHV0aWwuZXh0ZW5kKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIDogcmVnZXhlcztcbiAgICAgICAgLy92YXIgYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgIC8vdmFyIGNwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgLy92YXIgZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAvL3ZhciBlbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgIC8vdmFyIG9zID0gbmV3IE9TKCk7XG5cbiAgICAgICAgdGhpcy5nZXRCcm93c2VyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGJyb3dzZXIgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoYnJvd3NlciwgdWEsIHJneG1hcC5icm93c2VyKTtcbiAgICAgICAgICAgIGJyb3dzZXIubWFqb3IgPSB1dGlsLm1ham9yKGJyb3dzZXIudmVyc2lvbik7IC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgICAgIHJldHVybiBicm93c2VyO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENQVSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjcHUgPSB7IGFyY2hpdGVjdHVyZTogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoY3B1LCB1YSwgcmd4bWFwLmNwdSk7XG4gICAgICAgICAgICByZXR1cm4gY3B1O1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldERldmljZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBkZXZpY2UgPSB7IHZlbmRvcjogdW5kZWZpbmVkLCBtb2RlbDogdW5kZWZpbmVkLCB0eXBlOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChkZXZpY2UsIHVhLCByZ3htYXAuZGV2aWNlKTtcbiAgICAgICAgICAgIHJldHVybiBkZXZpY2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0RW5naW5lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVuZ2luZSA9IHsgbmFtZTogdW5kZWZpbmVkLCB2ZXJzaW9uOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChlbmdpbmUsIHVhLCByZ3htYXAuZW5naW5lKTtcbiAgICAgICAgICAgIHJldHVybiBlbmdpbmU7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0T1MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgb3MgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwob3MsIHVhLCByZ3htYXAub3MpO1xuICAgICAgICAgICAgcmV0dXJuIG9zO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldFJlc3VsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdWEgICAgICA6IHRoaXMuZ2V0VUEoKSxcbiAgICAgICAgICAgICAgICBicm93c2VyIDogdGhpcy5nZXRCcm93c2VyKCksXG4gICAgICAgICAgICAgICAgZW5naW5lICA6IHRoaXMuZ2V0RW5naW5lKCksXG4gICAgICAgICAgICAgICAgb3MgICAgICA6IHRoaXMuZ2V0T1MoKSxcbiAgICAgICAgICAgICAgICBkZXZpY2UgIDogdGhpcy5nZXREZXZpY2UoKSxcbiAgICAgICAgICAgICAgICBjcHUgICAgIDogdGhpcy5nZXRDUFUoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRVQSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB1YTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZXRVQSA9IGZ1bmN0aW9uICh1YXN0cmluZykge1xuICAgICAgICAgICAgdWEgPSB1YXN0cmluZztcbiAgICAgICAgICAgIC8vYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgICAgICAvL2NwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgICAgIC8vZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAgICAgLy9lbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgICAgICAvL29zID0gbmV3IE9TKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIFVBUGFyc2VyLlZFUlNJT04gPSBMSUJWRVJTSU9OO1xuICAgIFVBUGFyc2VyLkJST1dTRVIgPSB7XG4gICAgICAgIE5BTUUgICAgOiBOQU1FLFxuICAgICAgICBNQUpPUiAgIDogTUFKT1IsIC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgVkVSU0lPTiA6IFZFUlNJT05cbiAgICB9O1xuICAgIFVBUGFyc2VyLkNQVSA9IHtcbiAgICAgICAgQVJDSElURUNUVVJFIDogQVJDSElURUNUVVJFXG4gICAgfTtcbiAgICBVQVBhcnNlci5ERVZJQ0UgPSB7XG4gICAgICAgIE1PREVMICAgOiBNT0RFTCxcbiAgICAgICAgVkVORE9SICA6IFZFTkRPUixcbiAgICAgICAgVFlQRSAgICA6IFRZUEUsXG4gICAgICAgIENPTlNPTEUgOiBDT05TT0xFLFxuICAgICAgICBNT0JJTEUgIDogTU9CSUxFLFxuICAgICAgICBTTUFSVFRWIDogU01BUlRUVixcbiAgICAgICAgVEFCTEVUICA6IFRBQkxFVCxcbiAgICAgICAgV0VBUkFCTEU6IFdFQVJBQkxFLFxuICAgICAgICBFTUJFRERFRDogRU1CRURERURcbiAgICB9O1xuICAgIFVBUGFyc2VyLkVOR0lORSA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICBVQVBhcnNlci5PUyA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICAvL1VBUGFyc2VyLlV0aWxzID0gdXRpbDtcblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gRXhwb3J0XG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICAvLyBjaGVjayBqcyBlbnZpcm9ubWVudFxuICAgIGlmICh0eXBlb2YoZXhwb3J0cykgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgLy8gbm9kZWpzIGVudlxuICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gVU5ERUZfVFlQRSAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogdGVzdCEhISEhISEhXG4gICAgICAgIC8qXG4gICAgICAgIGlmIChyZXF1aXJlICYmIHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlICYmIHByb2Nlc3MpIHtcbiAgICAgICAgICAgIC8vIGNsaVxuICAgICAgICAgICAgdmFyIGpzb25pemUgPSBmdW5jdGlvbiAoYXJyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gYXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wdXNoKG5ldyBVQVBhcnNlcihhcnJbaV0pLmdldFJlc3VsdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoSlNPTi5zdHJpbmdpZnkocmVzLCBudWxsLCAyKSArICdcXG4nKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAocHJvY2Vzcy5zdGRpbi5pc1RUWSkge1xuICAgICAgICAgICAgICAgIC8vIHZpYSBhcmdzXG4gICAgICAgICAgICAgICAganNvbml6ZShwcm9jZXNzLmFyZ3Yuc2xpY2UoMikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB2aWEgcGlwZVxuICAgICAgICAgICAgICAgIHZhciBzdHIgPSAnJztcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdyZWFkYWJsZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVhZCA9IHByb2Nlc3Muc3RkaW4ucmVhZCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVhZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyICs9IHJlYWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGpzb25pemUoc3RyLnJlcGxhY2UoL1xcbiQvLCAnJykuc3BsaXQoJ1xcbicpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICBleHBvcnRzLlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVxdWlyZWpzIGVudiAob3B0aW9uYWwpXG4gICAgICAgIGlmICh0eXBlb2YoZGVmaW5lKSA9PT0gRlVOQ19UWVBFICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFVBUGFyc2VyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAod2luZG93KSB7XG4gICAgICAgICAgICAvLyBicm93c2VyIGVudlxuICAgICAgICAgICAgd2luZG93LlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBqUXVlcnkvWmVwdG8gc3BlY2lmaWMgKG9wdGlvbmFsKVxuICAgIC8vIE5vdGU6XG4gICAgLy8gICBJbiBBTUQgZW52IHRoZSBnbG9iYWwgc2NvcGUgc2hvdWxkIGJlIGtlcHQgY2xlYW4sIGJ1dCBqUXVlcnkgaXMgYW4gZXhjZXB0aW9uLlxuICAgIC8vICAgalF1ZXJ5IGFsd2F5cyBleHBvcnRzIHRvIGdsb2JhbCBzY29wZSwgdW5sZXNzIGpRdWVyeS5ub0NvbmZsaWN0KHRydWUpIGlzIHVzZWQsXG4gICAgLy8gICBhbmQgd2Ugc2hvdWxkIGNhdGNoIHRoYXQuXG4gICAgdmFyICQgPSB3aW5kb3cgJiYgKHdpbmRvdy5qUXVlcnkgfHwgd2luZG93LlplcHRvKTtcbiAgICBpZiAodHlwZW9mICQgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgdmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcigpO1xuICAgICAgICAkLnVhID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAkLnVhLmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZXIuZ2V0VUEoKTtcbiAgICAgICAgfTtcbiAgICAgICAgJC51YS5zZXQgPSBmdW5jdGlvbiAodWFzdHJpbmcpIHtcbiAgICAgICAgICAgIHBhcnNlci5zZXRVQSh1YXN0cmluZyk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAkLnVhW3Byb3BdID0gcmVzdWx0W3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxufSkodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgPyB3aW5kb3cgOiB0aGlzKTtcbiIsInZhciB2MSA9IHJlcXVpcmUoJy4vdjEnKTtcbnZhciB2NCA9IHJlcXVpcmUoJy4vdjQnKTtcblxudmFyIHV1aWQgPSB2NDtcbnV1aWQudjEgPSB2MTtcbnV1aWQudjQgPSB2NDtcblxubW9kdWxlLmV4cG9ydHMgPSB1dWlkO1xuIiwiLyoqXG4gKiBDb252ZXJ0IGFycmF5IG9mIDE2IGJ5dGUgdmFsdWVzIHRvIFVVSUQgc3RyaW5nIGZvcm1hdCBvZiB0aGUgZm9ybTpcbiAqIFhYWFhYWFhYLVhYWFgtWFhYWC1YWFhYLVhYWFhYWFhYWFhYWFxuICovXG52YXIgYnl0ZVRvSGV4ID0gW107XG5mb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgKytpKSB7XG4gIGJ5dGVUb0hleFtpXSA9IChpICsgMHgxMDApLnRvU3RyaW5nKDE2KS5zdWJzdHIoMSk7XG59XG5cbmZ1bmN0aW9uIGJ5dGVzVG9VdWlkKGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gb2Zmc2V0IHx8IDA7XG4gIHZhciBidGggPSBieXRlVG9IZXg7XG4gIHJldHVybiBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxuXG4vLyBnZXRSYW5kb21WYWx1ZXMgbmVlZHMgdG8gYmUgaW52b2tlZCBpbiBhIGNvbnRleHQgd2hlcmUgXCJ0aGlzXCIgaXMgYSBDcnlwdG8gaW1wbGVtZW50YXRpb24uXG52YXIgZ2V0UmFuZG9tVmFsdWVzID0gKHR5cGVvZihjcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChjcnlwdG8pKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICh0eXBlb2YobXNDcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIG1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKG1zQ3J5cHRvKSk7XG5pZiAoZ2V0UmFuZG9tVmFsdWVzKSB7XG4gIC8vIFdIQVRXRyBjcnlwdG8gUk5HIC0gaHR0cDovL3dpa2kud2hhdHdnLm9yZy93aWtpL0NyeXB0b1xuICB2YXIgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBnZXRSYW5kb21WYWx1ZXMocm5kczgpO1xuICAgIHJldHVybiBybmRzODtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWF0aFJORygpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbi8vICoqYHYxKClgIC0gR2VuZXJhdGUgdGltZS1iYXNlZCBVVUlEKipcbi8vXG4vLyBJbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vTGlvc0svVVVJRC5qc1xuLy8gYW5kIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS91dWlkLmh0bWxcblxudmFyIF9ub2RlSWQ7XG52YXIgX2Nsb2Nrc2VxO1xuXG4vLyBQcmV2aW91cyB1dWlkIGNyZWF0aW9uIHRpbWVcbnZhciBfbGFzdE1TZWNzID0gMDtcbnZhciBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB2YXIgbm9kZSA9IG9wdGlvbnMubm9kZSB8fCBfbm9kZUlkO1xuICB2YXIgY2xvY2tzZXEgPSBvcHRpb25zLmNsb2Nrc2VxICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb2Nrc2VxIDogX2Nsb2Nrc2VxO1xuXG4gIC8vIG5vZGUgYW5kIGNsb2Nrc2VxIG5lZWQgdG8gYmUgaW5pdGlhbGl6ZWQgdG8gcmFuZG9tIHZhbHVlcyBpZiB0aGV5J3JlIG5vdFxuICAvLyBzcGVjaWZpZWQuICBXZSBkbyB0aGlzIGxhemlseSB0byBtaW5pbWl6ZSBpc3N1ZXMgcmVsYXRlZCB0byBpbnN1ZmZpY2llbnRcbiAgLy8gc3lzdGVtIGVudHJvcHkuICBTZWUgIzE4OVxuICBpZiAobm9kZSA9PSBudWxsIHx8IGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICB2YXIgc2VlZEJ5dGVzID0gcm5nKCk7XG4gICAgaWYgKG5vZGUgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuNSwgY3JlYXRlIGFuZCA0OC1iaXQgbm9kZSBpZCwgKDQ3IHJhbmRvbSBiaXRzICsgbXVsdGljYXN0IGJpdCA9IDEpXG4gICAgICBub2RlID0gX25vZGVJZCA9IFtcbiAgICAgICAgc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgICAgICAgc2VlZEJ5dGVzWzFdLCBzZWVkQnl0ZXNbMl0sIHNlZWRCeXRlc1szXSwgc2VlZEJ5dGVzWzRdLCBzZWVkQnl0ZXNbNV1cbiAgICAgIF07XG4gICAgfVxuICAgIGlmIChjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC4yLjIsIHJhbmRvbWl6ZSAoMTQgYml0KSBjbG9ja3NlcVxuICAgICAgY2xvY2tzZXEgPSBfY2xvY2tzZXEgPSAoc2VlZEJ5dGVzWzZdIDw8IDggfCBzZWVkQnl0ZXNbN10pICYgMHgzZmZmO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVVSUQgdGltZXN0YW1wcyBhcmUgMTAwIG5hbm8tc2Vjb25kIHVuaXRzIHNpbmNlIHRoZSBHcmVnb3JpYW4gZXBvY2gsXG4gIC8vICgxNTgyLTEwLTE1IDAwOjAwKS4gIEpTTnVtYmVycyBhcmVuJ3QgcHJlY2lzZSBlbm91Z2ggZm9yIHRoaXMsIHNvXG4gIC8vIHRpbWUgaXMgaGFuZGxlZCBpbnRlcm5hbGx5IGFzICdtc2VjcycgKGludGVnZXIgbWlsbGlzZWNvbmRzKSBhbmQgJ25zZWNzJ1xuICAvLyAoMTAwLW5hbm9zZWNvbmRzIG9mZnNldCBmcm9tIG1zZWNzKSBzaW5jZSB1bml4IGVwb2NoLCAxOTcwLTAxLTAxIDAwOjAwLlxuICB2YXIgbXNlY3MgPSBvcHRpb25zLm1zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1zZWNzIDogbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIHVzZSBjb3VudCBvZiB1dWlkJ3MgZ2VuZXJhdGVkIGR1cmluZyB0aGUgY3VycmVudCBjbG9ja1xuICAvLyBjeWNsZSB0byBzaW11bGF0ZSBoaWdoZXIgcmVzb2x1dGlvbiBjbG9ja1xuICB2YXIgbnNlY3MgPSBvcHRpb25zLm5zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5zZWNzIDogX2xhc3ROU2VjcyArIDE7XG5cbiAgLy8gVGltZSBzaW5jZSBsYXN0IHV1aWQgY3JlYXRpb24gKGluIG1zZWNzKVxuICB2YXIgZHQgPSAobXNlY3MgLSBfbGFzdE1TZWNzKSArIChuc2VjcyAtIF9sYXN0TlNlY3MpLzEwMDAwO1xuXG4gIC8vIFBlciA0LjIuMS4yLCBCdW1wIGNsb2Nrc2VxIG9uIGNsb2NrIHJlZ3Jlc3Npb25cbiAgaWYgKGR0IDwgMCAmJiBvcHRpb25zLmNsb2Nrc2VxID09PSB1bmRlZmluZWQpIHtcbiAgICBjbG9ja3NlcSA9IGNsb2Nrc2VxICsgMSAmIDB4M2ZmZjtcbiAgfVxuXG4gIC8vIFJlc2V0IG5zZWNzIGlmIGNsb2NrIHJlZ3Jlc3NlcyAobmV3IGNsb2Nrc2VxKSBvciB3ZSd2ZSBtb3ZlZCBvbnRvIGEgbmV3XG4gIC8vIHRpbWUgaW50ZXJ2YWxcbiAgaWYgKChkdCA8IDAgfHwgbXNlY3MgPiBfbGFzdE1TZWNzKSAmJiBvcHRpb25zLm5zZWNzID09PSB1bmRlZmluZWQpIHtcbiAgICBuc2VjcyA9IDA7XG4gIH1cblxuICAvLyBQZXIgNC4yLjEuMiBUaHJvdyBlcnJvciBpZiB0b28gbWFueSB1dWlkcyBhcmUgcmVxdWVzdGVkXG4gIGlmIChuc2VjcyA+PSAxMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXVpZC52MSgpOiBDYW5cXCd0IGNyZWF0ZSBtb3JlIHRoYW4gMTBNIHV1aWRzL3NlYycpO1xuICB9XG5cbiAgX2xhc3RNU2VjcyA9IG1zZWNzO1xuICBfbGFzdE5TZWNzID0gbnNlY3M7XG4gIF9jbG9ja3NlcSA9IGNsb2Nrc2VxO1xuXG4gIC8vIFBlciA0LjEuNCAtIENvbnZlcnQgZnJvbSB1bml4IGVwb2NoIHRvIEdyZWdvcmlhbiBlcG9jaFxuICBtc2VjcyArPSAxMjIxOTI5MjgwMDAwMDtcblxuICAvLyBgdGltZV9sb3dgXG4gIHZhciB0bCA9ICgobXNlY3MgJiAweGZmZmZmZmYpICogMTAwMDAgKyBuc2VjcykgJSAweDEwMDAwMDAwMDtcbiAgYltpKytdID0gdGwgPj4+IDI0ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDE2ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfbWlkYFxuICB2YXIgdG1oID0gKG1zZWNzIC8gMHgxMDAwMDAwMDAgKiAxMDAwMCkgJiAweGZmZmZmZmY7XG4gIGJbaSsrXSA9IHRtaCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRtaCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfaGlnaF9hbmRfdmVyc2lvbmBcbiAgYltpKytdID0gdG1oID4+PiAyNCAmIDB4ZiB8IDB4MTA7IC8vIGluY2x1ZGUgdmVyc2lvblxuICBiW2krK10gPSB0bWggPj4+IDE2ICYgMHhmZjtcblxuICAvLyBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGAgKFBlciA0LjIuMiAtIGluY2x1ZGUgdmFyaWFudClcbiAgYltpKytdID0gY2xvY2tzZXEgPj4+IDggfCAweDgwO1xuXG4gIC8vIGBjbG9ja19zZXFfbG93YFxuICBiW2krK10gPSBjbG9ja3NlcSAmIDB4ZmY7XG5cbiAgLy8gYG5vZGVgXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgNjsgKytuKSB7XG4gICAgYltpICsgbl0gPSBub2RlW25dO1xuICB9XG5cbiAgcmV0dXJuIGJ1ZiA/IGJ1ZiA6IGJ5dGVzVG9VdWlkKGIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHYxO1xuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuZnVuY3Rpb24gdjQob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG5cbiAgaWYgKHR5cGVvZihvcHRpb25zKSA9PSAnc3RyaW5nJykge1xuICAgIGJ1ZiA9IG9wdGlvbnMgPT09ICdiaW5hcnknID8gbmV3IEFycmF5KDE2KSA6IG51bGw7XG4gICAgb3B0aW9ucyA9IG51bGw7XG4gIH1cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgdmFyIHJuZHMgPSBvcHRpb25zLnJhbmRvbSB8fCAob3B0aW9ucy5ybmcgfHwgcm5nKSgpO1xuXG4gIC8vIFBlciA0LjQsIHNldCBiaXRzIGZvciB2ZXJzaW9uIGFuZCBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGBcbiAgcm5kc1s2XSA9IChybmRzWzZdICYgMHgwZikgfCAweDQwO1xuICBybmRzWzhdID0gKHJuZHNbOF0gJiAweDNmKSB8IDB4ODA7XG5cbiAgLy8gQ29weSBieXRlcyB0byBidWZmZXIsIGlmIHByb3ZpZGVkXG4gIGlmIChidWYpIHtcbiAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgMTY7ICsraWkpIHtcbiAgICAgIGJ1ZltpICsgaWldID0gcm5kc1tpaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZiB8fCBieXRlc1RvVXVpZChybmRzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2NDtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi40IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odGhpcyB8fCB7fSkpO1xuIiwiaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1L09wZW5WaWR1JztcblxuaWYgKHdpbmRvdykge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zdHJpbmctbGl0ZXJhbFxuICAgIHdpbmRvd1snT3BlblZpZHUnXSA9IE9wZW5WaWR1O1xufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0Nvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwnIDogJ1JlbW90ZScpLCAnY2FuZGlkYXRlIGZvcicsXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCwgSlNPTi5zdHJpbmdpZnkoY2FuZGlkYXRlKSk7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdvbkljZUNhbmRpZGF0ZScsIHtcbiAgICAgICAgICAgIGVuZHBvaW50TmFtZTogdGhpcy5jb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IGNhbmRpZGF0ZS5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBjYW5kaWRhdGUuc2RwTUxpbmVJbmRleFxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzZW5kaW5nIElDRSBjYW5kaWRhdGU6ICdcbiAgICAgICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdFJlbW90ZVN0cmVhbXMob3B0aW9uczogU3RyZWFtT3B0aW9uc1NlcnZlcltdKTogdm9pZCB7XG5cbiAgICAgICAgLy8gVGhpcyBpcyByZWFkeSBmb3Igc3VwcG9ydGluZyBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uIG9iamVjdC4gUmlnaHQgbm93IHRoZSBsb29wIHdpbGwgYWx3YXlzIHJ1biBqdXN0IG9uY2VcbiAgICAgICAgLy8gdGhpcy5zdHJlYW0gc2hvdWxkIGFsc28gYmUgcmVwbGFjZWQgYnkgYSBjb2xsZWN0aW9uIG9mIHN0cmVhbXMgdG8gc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uXG4gICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgZnJhbWVSYXRlOiBvcHRzLmZyYW1lUmF0ZSxcbiAgICAgICAgICAgICAgICByZWN2QXVkaW86IG9wdHMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgcmVjdlZpZGVvOiBvcHRzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiBvcHRzLnR5cGVPZlZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLnNlc3Npb24sIHN0cmVhbU9wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJSZW1vdGUgJ0Nvbm5lY3Rpb24nIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiAnLCB0aGlzLnN0cmVhbS5pbmJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFkZFN0cmVhbShzdHJlYW06IFN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uY29ubmVjdGlvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVTdHJlYW0oc3RyZWFtSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3RyZWFtKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyU3RhdGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL0xvY2FsUmVjb3JkZXJTdGF0ZSc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuXG4gKlxuICogPiBXQVJOSU5HOiBQZXJmb3JtaW5nIGJyb3dzZXIgbG9jYWwgcmVjb3JkaW5nIG9mICoqcmVtb3RlIHN0cmVhbXMqKiBtYXkgY2F1c2Ugc29tZSB0cm91Ymxlcy4gQSBsb25nIHdhaXRpbmcgdGltZSBtYXkgYmUgcmVxdWlyZWQgYWZ0ZXIgY2FsbGluZyBfTG9jYWxSZWNvcmRlci5zdG9wKClfIGluIHRoaXMgY2FzZVxuICovXG5leHBvcnQgY2xhc3MgTG9jYWxSZWNvcmRlciB7XG5cbiAgICBzdGF0ZTogTG9jYWxSZWNvcmRlclN0YXRlO1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uSWQ6IHN0cmluZztcbiAgICBwcml2YXRlIG1lZGlhUmVjb3JkZXI6IGFueTtcbiAgICBwcml2YXRlIGNodW5rczogYW55W10gPSBbXTtcbiAgICBwcml2YXRlIGJsb2I6IEJsb2I7XG4gICAgcHJpdmF0ZSBjb3VudCA9IDA7XG4gICAgcHJpdmF0ZSBpZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3U3JjOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBodG1sUGFyZW50RWxlbWVudElkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXc6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzdHJlYW06IFN0cmVhbSkge1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9ICghIXRoaXMuc3RyZWFtLmNvbm5lY3Rpb24pID8gdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgOiAnZGVmYXVsdC1jb25uZWN0aW9uJztcbiAgICAgICAgdGhpcy5pZCA9IHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnX2xvY2FscmVjb3JkJztcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFN0YXJ0cyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUFEWWAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RhcnRlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVjb3JkKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRyeSB7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZWNvcmQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUFEWVxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLmNsZWFuKClcXCcgb3IgaW5pdCBhIG5ldyBMb2NhbFJlY29yZGVyIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJTdGFydGluZyBsb2NhbCByZWNvcmRpbmcgb2Ygc3RyZWFtICdcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgXCInIG9mIGNvbm5lY3Rpb24gJ1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyBcIidcIik7XG5cblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9wdGlvbnM7XG4gICAgICAgICAgICAgICAgICAgIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA5JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA5JyB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA4JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA4JyB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdVc2luZyBtaW1lVHlwZSAnICsgb3B0aW9ucy5taW1lVHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCksIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignaXNUeXBlU3VwcG9ydGVkIGlzIG5vdCBzdXBwb3J0ZWQsIHVzaW5nIGRlZmF1bHQgY29kZWNzIGZvciBicm93c2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdGFydCgxMCk7XG5cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25kYXRhYXZhaWxhYmxlID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUuZGF0YSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25lcnJvciA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBlcnJvcjogJywgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdGFydCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdGFydGVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25wYXVzZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBwYXVzZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucmVzdW1lID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHJlc3VtZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ud2FybmluZyA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgd2FybmluZzogJyArIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBFbmRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2Agb3IgYFBBVVNFRGAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYEZJTklTSEVEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdG9wcGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBzdG9wKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyBvciBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdG9wKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFBhdXNlcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBQQVVTRURgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSBwYXVzZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHBhdXNlKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQucGF1c2UoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIG9yIFxcJ0xvY2FsUmVjb3JkZXIucmVzdW1lKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucGF1c2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzdW1lcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSByZXN1bWVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZXN1bWUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZXN1bWUoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5wYXVzZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnJlc3VtZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByZXZpZXdzIHRoZSByZWNvcmRpbmcsIGFwcGVuZGluZyBhIG5ldyBIVE1MVmlkZW9FbGVtZW50IHRvIGVsZW1lbnQgd2l0aCBpZCBgcGFyZW50SWRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgcHJldmlldyhwYXJlbnRFbGVtZW50KTogSFRNTFZpZGVvRWxlbWVudCB7XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5wcmV2aWV3KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmlkID0gdGhpcy5pZDtcbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuYXV0b3BsYXkgPSB0cnVlO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcGFyZW50RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhcmVudEVsZW1lbnREb20gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRFbGVtZW50KTtcbiAgICAgICAgICAgIGlmIChwYXJlbnRFbGVtZW50RG9tKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50RG9tLmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQuaWQ7XG4gICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuc3JjID0gdGhpcy52aWRlb1ByZXZpZXdTcmM7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9QcmV2aWV3O1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogR3JhY2VmdWxseSBzdG9wcyBhbmQgY2xlYW5zIHRoZSBjdXJyZW50IHJlY29yZGluZyAoV0FSTklORzogaXQgaXMgY29tcGxldGVseSBkaXNtaXNzZWQpLiBTZXRzIFtbc3RhdGVdXSB0byBgUkVBRFlgIHNvIHRoZSByZWNvcmRpbmcgY2FuIHN0YXJ0IGFnYWluXG4gICAgICovXG4gICAgY2xlYW4oKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGYgPSAoKSA9PiB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5ibG9iO1xuICAgICAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubWVkaWFSZWNvcmRlcjtcbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcCgpLnRoZW4oKCkgPT4gZigpKS5jYXRjaCgoKSA9PiBmKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBEb3dubG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIHRocm91Z2ggdGhlIGJyb3dzZXIuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBkb3dubG9hZCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5kb3dubG9hZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGE6IEhUTUxBbmNob3JFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICAgICAgYS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgICAgIGEuZG93bmxvYWQgPSB0aGlzLmlkICsgJy53ZWJtJztcbiAgICAgICAgICAgIGEuY2xpY2soKTtcbiAgICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSByYXcgQmxvYiBmaWxlLiBNZXRob2RzIHByZXZpZXcsIGRvd25sb2FkLCB1cGxvYWRBc0JpbmFyeSBhbmQgdXBsb2FkQXNNdWx0aXBhcnRmaWxlIHVzZSB0aGlzIHNhbWUgZmlsZSB0byBwZXJmb3JtIHRoZWlyIHNwZWNpZmljIGFjdGlvbnMuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBnZXRCbG9iKCk6IEJsb2Ige1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ0NhbGwgXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIGJlZm9yZSBnZXR0aW5nIEJsb2IgZmlsZScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJsb2I7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgYmluYXJ5IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3RcbiAgICAgKi9cbiAgICB1cGxvYWRBc0JpbmFyeShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzQmluYXJ5KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGh0dHAuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHRoaXMuYmxvYik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBsb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gYXMgYSBtdWx0aXBhcnQgZmlsZSBwZXJmb3JtaW5nIGFuIEhUVFAvUE9TVCBvcGVyYXRpb24gdG8gVVJMIGBlbmRwb2ludGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGAuIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBjYW4gYmUgcGFzc2VkIGFzIHNlY29uZCBwYXJhbWV0ZXIuIEZvciBleGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHZhciBoZWFkZXJzID0ge1xuICAgICAqICBcIkNvb2tpZVwiOiBcIiRWZXJzaW9uPTE7IFNraW49bmV3O1wiLFxuICAgICAqICBcIkF1dGhvcml6YXRpb25cIjpcIkJhc2ljIFFXeGhaR3BianB1SUhObGN0WlE9PVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB3aXRoIHRoZSBgaHR0cC5yZXNwb25zZVRleHRgIGZyb20gc2VydmVyIGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggdGhlIGZhaWxlZCBgaHR0cC5zdGF0dXNgIGlmIG5vdDpcbiAgICAgKi9cbiAgICB1cGxvYWRBc011bHRpcGFydGZpbGUoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc011bHRpcGFydGZpbGUoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3Qgc2VuZGFibGUgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgICAgICAgICBzZW5kYWJsZS5hcHBlbmQoJ2ZpbGUnLCB0aGlzLmJsb2IsIHRoaXMuaWQgKyAnLndlYm0nKTtcblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGh0dHAuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBodHRwLnNlbmQoc2VuZGFibGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBvblN0b3BEZWZhdWx0KCk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdG9wcGVkICAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG5cbiAgICAgICAgdGhpcy5ibG9iID0gbmV3IEJsb2IodGhpcy5jaHVua3MsIHsgdHlwZTogJ3ZpZGVvL3dlYm0nIH0pO1xuICAgICAgICB0aGlzLmNodW5rcyA9IFtdO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3U3JjID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEO1xuICAgIH1cblxufVxuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyIH0gZnJvbSAnLi9Mb2NhbFJlY29yZGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4vUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBScGNCdWlsZGVyIGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYyc7XG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbi8qKlxuICogRW50cnlwb2ludCBvZiBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKiBVc2UgaXQgdG8gaW5pdGlhbGl6ZSBvYmplY3RzIG9mIHR5cGUgW1tTZXNzaW9uXV0sIFtbUHVibGlzaGVyXV0gYW5kIFtbTG9jYWxSZWNvcmRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgcHJpdmF0ZSBqc29uUnBjQ2xpZW50OiBhbnk7XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlc3Npb246IFNlc3Npb247XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICB3c1VyaTogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VjcmV0ID0gJyc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByZWNvcmRlciA9IGZhbHNlO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgYWR2YW5jZWRDb25maWd1cmF0aW9uOiBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGNvbnNvbGUuaW5mbyhcIidPcGVuVmlkdScgaW5pdGlhbGl6ZWRcIik7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIG5ldyBzZXNzaW9uXG4gICAqL1xuICBpbml0U2Vzc2lvbigpOiBTZXNzaW9uIHtcbiAgICB0aGlzLnNlc3Npb24gPSBuZXcgU2Vzc2lvbih0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uO1xuICB9XG5cblxuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgcHVibGlzaGVyXG4gICAqXG4gICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0RpYWxvZ09wZW5lZGAgZXZlbnQsIG9ubHkgaWYgdGhlIHBvcC11cCBzaG93biBieSB0aGUgYnJvd3NlciB0byByZXF1ZXN0IHBlcm1pc3Npb25zIGZvciB0aGUgY2FtZXJhIGlzIG9wZW5lZC4gWW91IGNhbiB1c2UgdGhpcyBldmVudCB0byBhbGVydCB0aGUgdXNlciBhYm91dCBncmFudGluZyBwZXJtaXNzaW9uc1xuICAgKiBmb3IgeW91ciB3ZWJzaXRlLiBBbiBgYWNjZXNzRGlhbG9nQ2xvc2VkYCBldmVudCB3aWxsIGFsc28gYmUgZGlzcGF0Y2hlZCBhZnRlciB1c2VyIGNsaWNrcyBvbiBcIkFsbG93XCIgb3IgXCJCbG9ja1wiIGluIHRoZSBwb3AtdXAuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NBbGxvd2VkYCBvciBgYWNjZXNzRGVuaWVkYCBldmVudCBvbmNlIGl0IGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3QuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgYSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIGxvY2FsIHN0cmVhbXMgc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50ICBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgUHVibGlzaGVyLlxuICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1B1Ymxpc2hlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1B1Ymxpc2hlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgaW5pdFB1Ymxpc2hlcmAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgYGNvbXBsZXRpb25IYW5kbGVyYCBmdW5jdGlvbiBpcyBjYWxsZWQgYmVmb3JlIHRoZSBQdWJsaXNoZXIgZGlzcGF0Y2hlcyBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYW4gYGFjY2Vzc0RlbmllZGAgZXZlbnRcbiAgICovXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMj8sIHBhcmFtMz8pOiBQdWJsaXNoZXIge1xuXG4gICAgbGV0IHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXM7XG5cbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgIT09ICdmdW5jdGlvbicpKSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9ICg8UHVibGlzaGVyUHJvcGVydGllcz5wYXJhbTIpO1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBhdWRpb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlIDogdW5kZWZpbmVkLFxuICAgICAgICBmcmFtZVJhdGU6IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5mcmFtZVJhdGUgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuZnJhbWVSYXRlIDogdW5kZWZpbmVkKSxcbiAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3Byb3BlcnRpZXMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiAodHlwZW9mIHByb3BlcnRpZXMubWlycm9yICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLm1pcnJvciA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaFZpZGVvIDogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogdGhpcy5pc01lZGlhU3RyZWFtVHJhY2socHJvcGVydGllcy52aWRlb1NvdXJjZSkgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLnJlc29sdXRpb24gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucmVzb2x1dGlvbiA6ICc2NDB4NDgwJyksXG4gICAgICAgIHZpZGVvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgOiB1bmRlZmluZWRcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50KScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiAnNjQweDQ4MCdcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgcHVibGlzaGVyOiBQdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIHRoaXMpO1xuXG4gICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0yO1xuICAgIH0gZWxzZSBpZiAoISFwYXJhbTMpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgIH1cblxuICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgfSk7XG5cbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lICE9PSAnRmlyZWZveCcpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVELCAnWW91IGNhbiBvbmx5IHNjcmVlbiBzaGFyZSBpbiBkZXNrdG9wIENocm9tZSBhbmQgRmlyZWZveC4gRGV0ZWN0ZWQgYnJvd3NlcjogJyArIHBsYXRmb3JtLm5hbWUpO1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24pIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbi5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbklkLCAoc3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWVuYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0U2NyZWVuQ29uc3RyYWludHMoKGVycm9yLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yICYmIGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICg8c3RyaW5nPnRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uKSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9zY3JlZW4tY2FwdHVyaW5nL2FqaGlmZGRpbWthcGdjaWZnY29kbW1mZGxrbmFoZmZrJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQsICdZb3UgbXVzdCBhbGxvdyBhY2Nlc3MgdG8gb25lIHdpbmRvdyBvZiB5b3VyIGRlc2t0b3AnKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHMudmlkZW87XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID0gJ3NjcmVlbic7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLXN0cmluZy1saXRlcmFsXG4gICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvWydkZXZpY2VJZCddID0geyBleGFjdDogcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSB9O1xuICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzdGFydFdzKG9uQ29ubmVjdFN1Y2NlczogKGVycm9yOiBFcnJvcikgPT4gdm9pZCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIGhlYXJ0YmVhdDogNTAwMCxcbiAgICAgIHNlbmRDbG9zZU1lc3NhZ2U6IGZhbHNlLFxuICAgICAgd3M6IHtcbiAgICAgICAgdXJpOiB0aGlzLndzVXJpLFxuICAgICAgICB1c2VTb2NrSlM6IGZhbHNlLFxuICAgICAgICBvbmNvbm5lY3RlZDogb25Db25uZWN0U3VjY2VzLFxuICAgICAgICBvbmRpc2Nvbm5lY3Q6IHRoaXMuZGlzY29ubmVjdENhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0aW5nOiB0aGlzLnJlY29ubmVjdGluZ0NhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0ZWQ6IHRoaXMucmVjb25uZWN0ZWRDYWxsYmFjay5iaW5kKHRoaXMpXG4gICAgICB9LFxuICAgICAgcnBjOiB7XG4gICAgICAgIHJlcXVlc3RUaW1lb3V0OiAxNTAwMCxcbiAgICAgICAgcGFydGljaXBhbnRKb2luZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50Sm9pbmVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRQdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50UHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRVbnB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50TGVmdDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRMZWZ0LmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRFdmljdGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEV2aWN0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdGFydGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdGFydGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RvcHBlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RvcHBlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHNlbmRNZXNzYWdlOiB0aGlzLnNlc3Npb24ub25OZXdNZXNzYWdlLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgaWNlQ2FuZGlkYXRlOiB0aGlzLnNlc3Npb24ucmVjdkljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIG1lZGlhRXJyb3I6IHRoaXMuc2Vzc2lvbi5vbk1lZGlhRXJyb3IuYmluZCh0aGlzLnNlc3Npb24pXG4gICAgICB9XG4gICAgfTtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQgPSBuZXcgUnBjQnVpbGRlci5jbGllbnRzLkpzb25ScGNDbGllbnQoY29uZmlnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBjbG9zZVdzKCk6IHZvaWQge1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5jbG9zZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlbmRSZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCBwYXJhbXM6IGFueSwgY2FsbGJhY2s/KTogdm9pZCB7XG4gICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgY2FsbGJhY2sgPSBwYXJhbXM7XG4gICAgICBwYXJhbXMgPSB7fTtcbiAgICB9XG4gICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyByZXF1ZXN0OiB7bWV0aG9kOlwiJyArIG1ldGhvZCArICdcIiwgcGFyYW1zOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSArICd9Jyk7XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50LnNlbmQobWV0aG9kLCBwYXJhbXMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpc01lZGlhU3RyZWFtVHJhY2sobWVkaWFTb3VyY2U6IGFueSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGlzID0gKCEhbWVkaWFTb3VyY2UgJiZcbiAgICAgIG1lZGlhU291cmNlLmVuYWJsZWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuZW5hYmxlZCA9PT0gJ2Jvb2xlYW4nICYmXG4gICAgICBtZWRpYVNvdXJjZS5pZCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5pZCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLmtpbmQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2Uua2luZCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLmxhYmVsICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmxhYmVsID09PSAnc3RyaW5nJyAmJlxuICAgICAgbWVkaWFTb3VyY2UubXV0ZWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UubXV0ZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5yZWFkeVN0YXRlID09PSAnc3RyaW5nJyk7XG4gICAgcmV0dXJuIGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFdzVXJpKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMud3NVcmk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2V0U2VjcmV0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc2VjcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFJlY29yZGVyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnJlY29yZGVyO1xuICB9XG5cblxuICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICBwcml2YXRlIGRpc2Nvbm5lY3RDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGluZ0NhbGxiYWNrKCk6IHZvaWQge1xuICAgIGNvbnNvbGUud2FybignV2Vic29ja2V0IGNvbm5lY3Rpb24gbG9zdCAocmVjb25uZWN0aW5nKScpO1xuICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICB0aGlzLnNlc3Npb24ub25Mb3N0Q29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVjb25uZWN0ZWRDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCByZWNvbm5lY3RlZCcpO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1Jvb21BdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuc2Vzc2lvbiAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc2Vzc2lvbiBpbnN0YW5jZW9mIFNlc3Npb24pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gaW5zdGFuY2Ugbm90IGZvdW5kJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgRXZlbnREaXNwYXRjaGVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9FdmVudERpc3BhdGNoZXInO1xuaW1wb3J0IHsgUHVibGlzaGVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvUHVibGlzaGVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbUV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBwcml2YXRlIG9wZW52aWR1OiBPcGVuVmlkdSkge1xuICAgICAgICBzdXBlcihuZXcgU3RyZWFtKCghIW9wZW52aWR1LnNlc3Npb24pID8gb3BlbnZpZHUuc2Vzc2lvbiA6IG5ldyBTZXNzaW9uKG9wZW52aWR1KSwgeyBwdWJsaXNoZXJQcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLCBtZWRpYUNvbnN0cmFpbnRzOiB7fSB9KSwgdGFyZ0VsKTtcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZC1ieS1kaXNjb25uZWN0JywgKHJlYXNvbjogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgdGhpcy5zdHJlYW0sIHJlYXNvbik7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIGF1ZGlvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoQXVkaW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmF1ZGlvRW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBoYXMgXCIgKyAodmFsdWUgPyAncHVibGlzaGVkJyA6ICd1bnB1Ymxpc2hlZCcpICsgJyBpdHMgYXVkaW8gc3RyZWFtJyk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaFZpZGVvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS52aWRlb0VuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogQ2FsbCB0aGlzIG1ldGhvZCBiZWZvcmUgW1tTZXNzaW9uLnB1Ymxpc2hdXSB0byBzdWJzY3JpYmUgdG8geW91ciBQdWJsaXNoZXIncyByZW1vdGUgc3RyZWFtIGluc3RlYWQgb2YgdXNpbmcgdGhlIGxvY2FsIHN0cmVhbSwgYXMgYW55IG90aGVyIHVzZXIgd291bGQgZG8uXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9SZW1vdGUodmFsdWU/OiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHZhbHVlID0gKHZhbHVlICE9PSB1bmRlZmluZWQpID8gdmFsdWUgOiB0cnVlO1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlZFRvUmVtb3RlID0gdmFsdWU7XG4gICAgICAgIHRoaXMuc3RyZWFtLnN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWUpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICBzdXBlci5vbih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1DcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLm9uKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBlcnJvckNhbGxiYWNrID0gKG9wZW5WaWR1RXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc0NhbGxiYWNrID0gKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmlzTWVkaWFTdHJlYW1UcmFjayh0aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjaygoPE1lZGlhU3RyZWFtVHJhY2s+dGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBBcHBseSBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyBhbmQgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW9cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZW5hYmxlZCA9ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuXG4gICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5maXJzdFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZVZpZGVvRWxlbWVudCh0aGlzLmZpcnN0VmlkZW9FbGVtZW50LnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+dGhpcy5wcm9wZXJ0aWVzLmluc2VydE1vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbjogU2Vzc2lvbik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lZS5nZXRMaXN0ZW5lcnMoJ3N0cmVhbVBsYXlpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ09wZW5lZCcsIFtdKTtcbiAgICAgICAgfSwgd2FpdFRpbWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lOiBudW1iZXIsIHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQpO1xuICAgICAgICBpZiAoKERhdGUubm93KCkgLSBzdGFydFRpbWUpID4gd2FpdFRpbWUpIHtcbiAgICAgICAgICAgIC8vIFBlcm1pc3Npb24gZGlhbG9nIHdhcyBzaG93biBhbmQgbm93IGlzIGNsb3NlZFxuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ0Nsb3NlZCcsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgT2JqTWFwIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT2JqTWFwJztcbmltcG9ydCB7IFNlc3Npb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU2Vzc2lvbk9wdGlvbnMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbkV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvbkV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFJlY29yZGluZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFNpZ25hbEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSB2aWRlbyBjYWxsLiBJdCBjYW4gYWxzbyBiZSBzZWVuIGFzIGEgdmlkZW9jb25mZXJlbmNlIHJvb20gd2hlcmUgbXVsdGlwbGUgdXNlcnMgY2FuIGNvbm5lY3QuXG4gKiBQYXJ0aWNpcGFudHMgd2hvIHB1Ymxpc2ggdGhlaXIgdmlkZW9zIHRvIGEgc2Vzc2lvbiBjYW4gYmUgc2VlbiBieSB0aGUgcmVzdCBvZiB1c2VycyBjb25uZWN0ZWQgdG8gdGhhdCBzcGVjaWZpYyBzZXNzaW9uLlxuICogSW5pdGlhbGl6ZWQgd2l0aCBbW09wZW5WaWR1LmluaXRTZXNzaW9uXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXNzaW9uIGltcGxlbWVudHMgRXZlbnREaXNwYXRjaGVyIHtcblxuICAgIC8qKlxuICAgICAqIExvY2FsIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24uIFRoaXMgb2JqZWN0IGlzIGRlZmluZWQgb25seSBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBleGVjdXRlZCwgYW5kIGNhbiBiZSByZXRyaWV2ZWQgc3Vic2NyaWJpbmcgdG8gYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgU2Vzc2lvblxuICAgICAqL1xuICAgIHNlc3Npb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ29sbGVjdGlvbiBvZiBhbGwgU3RyZWFtTWFuYWdlcnMgb2YgdGhpcyBTZXNzaW9uIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSlcbiAgICAgKi9cbiAgICBzdHJlYW1NYW5hZ2VyczogU3RyZWFtTWFuYWdlcltdID0gW107XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBPYmpNYXA8Ym9vbGVhbj4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVDb25uZWN0aW9uczogT2JqTWFwPENvbm5lY3Rpb24+ID0ge307XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PjtcbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnkpOiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0cyB0byB0aGUgc2Vzc2lvbiB1c2luZyBgdG9rZW5gLiBQYXJhbWV0ZXIgYG1ldGFkYXRhYCBhbGxvd3MgeW91IHRvIHBhc3MgZXh0cmEgZGF0YSB0byBzaGFyZSB3aXRoIG90aGVyIHVzZXJzIHdoZW5cbiAgICAgKiB0aGV5IHJlY2VpdmUgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LiBUaGUgc3RydWN0dXJlIG9mIGBtZXRhZGF0YWAgc3RyaW5nIGlzIHVwIHRvIHlvdSAobWF5YmUgc29tZSBzdGFuZGFyaXplZCBmb3JtYXRcbiAgICAgKiBhcyBKU09OIG9yIFhNTCBpcyBhIGdvb2QgaWRlYSksIHRoZSBvbmx5IHJlc3RyaWN0aW9uIGlzIGEgbWF4aW11bSBsZW5ndGggb2YgMTAwMDAgY2hhcnMuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGFkYXRhIGlzIG5vdCBjb25zaWRlcmVkIHNlY3VyZSwgYXMgaXQgaXMgZ2VuZXJhdGVkIGluIHRoZSBjbGllbnQgc2lkZS4gVG8gcGFzcyBzZWN1cml6ZWQgZGF0YSwgYWRkIGl0IGFzIGEgcGFyYW1ldGVyIGluIHRoZVxuICAgICAqIHRva2VuIGdlbmVyYXRpb24gb3BlcmF0aW9uICh0aHJvdWdoIHRoZSBBUEkgUkVTVCwgb3BlbnZpZHUtamF2YS1jbGllbnQgb3Igb3BlbnZpZHUtbm9kZS1jbGllbnQpLlxuICAgICAqXG4gICAgICogT25seSBhZnRlciB0aGUgcmV0dXJuZWQgUHJvbWlzZSBpcyBzdWNjZXNzZnVsbHkgcmVzb2x2ZWQgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBvYmplY3Qgd2lsbCBiZSBhdmFpbGFibGUgYW5kIHByb3Blcmx5IGRlZmluZWQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGZpcnN0IGRpc3BhdGNoIG9uZSBvciBtb3JlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzIHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZDpcbiAgICAgKiAtIEZpcnN0IG9uZSBmb3IgeW91ciBvd24gbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QsIHNvIHlvdSBjYW4gcmV0cmlldmUgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBwcm9wZXJ0eS5cbiAgICAgKiAtIFRoZW4gb25lIGZvciBlYWNoIHJlbW90ZSBDb25uZWN0aW9uIHByZXZpb3VzbHkgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uLCBpZiBhbnkuIEFueSBvdGhlciByZW1vdGUgdXNlciBjb25uZWN0aW5nIHRvIHRoZSBTZXNzaW9uIGFmdGVyIHlvdSBoYXZlXG4gICAgICogc3VjY2Vzc2Z1bGx5IGNvbm5lY3RlZCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50IHdoZW4gdGhleSBkbyBzby5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBmb3IgZWFjaCByZW1vdGUgYWN0aXZlIFtbUHVibGlzaGVyXV0gdGhhdCB3YXMgYWxyZWFkeSBzdHJlYW1pbmdcbiAgICAgKiB3aGVuIGNvbm5lY3RpbmcsIGp1c3QgYWZ0ZXIgZGlzcGF0Y2hpbmcgYWxsIHJlbW90ZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gYW5kIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIHRvIHdoaWNoIHlvdSBtdXN0IHN1YnNjcmliZSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSB0aGUgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICpcbiAgICAgKi9cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIW1ldGFkYXRhID8gdGhpcy5zdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YSkgOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0QXV4KHRva2VuKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIHBsYXRmb3JtLm5hbWUgKyAnICcgKyBwbGF0Zm9ybS52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCB0byBhdm9pZCB0aGlzIGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgYWxsIHRoZSBTdWJzY3JpYmVyIG9iamVjdHMgeW91cnNlbGYuXG4gICAgICogU2VlIFtbU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGVyZSBpcyBhIFtbUHVibGlzaGVyXV0gb2JqZWN0IHB1Ymxpc2hpbmcgdG8gdGhlIHNlc3Npb24uXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgc3RvcCBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIGlmIHlvdSB3YW50IHRvIGNsZWFuIHRoZSBQdWJsaXNoZXIgb2JqZWN0IG9uIHlvdXIgb3duIG9yIHJlLXB1Ymxpc2ggaXQgaW4gYSBkaWZmZXJlbnQgU2Vzc2lvbiAodG8gZG8gc28gaXQgaXMgYSBtYW5kYXRvcnkgcmVxdWlyZW1lbnQgdG8gY2FsbCBgU2Vzc2lvbi51bnB1Ymxpc2goKWBcbiAgICAgKiBvci9hbmQgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBpbiB0aGUgcHJldmlvdXMgc2Vzc2lvbikuIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBkaXNjb25uZWN0ZWQgcGFydGljaXBhbnQgd2FzIHB1Ymxpc2hpbmcuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBpbiBhbnkgY2FzZS4gU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKi9cbiAgICBkaXNjb25uZWN0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxlYXZlKGZhbHNlLCAnZGlzY29ubmVjdCcpO1xuICAgIH1cblxuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZXMgdG8gYSBgc3RyZWFtYCwgYWRkaW5nIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCB0byBET00gd2l0aCBgc3Vic2NyaWJlclByb3BlcnRpZXNgIHNldHRpbmdzLiBUaGlzIG1ldGhvZCBpcyB1c3VhbGx5IGNhbGxlZCBpbiB0aGUgY2FsbGJhY2sgb2YgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIHJlbW90ZSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc3RyZWFtIFN0cmVhbSBvYmplY3QgdG8gc3Vic2NyaWJlIHRvXG4gICAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tTdWJzY3JpYmVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgU3Vic2NyaWJlci5cbiAgICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1N1YnNjcmliZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24pXG4gICAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYHN1YnNjcmliZWAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgICAqL1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMz86ICgoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSB8IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBwYXJhbTQ/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkpOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgbGV0IHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzID0ge307XG4gICAgICAgIGlmICghIXBhcmFtMyAmJiB0eXBlb2YgcGFyYW0zICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcGFyYW0zLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlID09PSAnc3RyaW5nJykgPyBWaWRlb0luc2VydE1vZGVbcGFyYW0zLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogKHR5cGVvZiBwYXJhbTMuc3Vic2NyaWJlVG9BdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gOiB0cnVlLFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvVmlkZW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvIDogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb0F1ZGlvOiB0cnVlLFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvVmlkZW86IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gICAgICAgIGlmICghIXBhcmFtMyAmJiAodHlwZW9mIHBhcmFtMyA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgICAgICB9IGVsc2UgaWYgKCEhcGFyYW00KSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtNDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJpbmcgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgc3RyZWFtLnN1YnNjcmliZSgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdTdWJzY3JpYmVkIGNvcnJlY3RseSB0byAnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgc3Vic2NyaWJlciA9IG5ldyBTdWJzY3JpYmVyKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyk7XG4gICAgICAgIGlmICghIXN1YnNjcmliZXIudGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgc3RyZWFtLnN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KHN1YnNjcmliZXIudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT5wcm9wZXJ0aWVzLmluc2VydE1vZGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdWJzY3JpYmVyO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW1Nlc3Npb24uc3Vic2NyaWJlXV1cbiAgICAgKi9cbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFN1YnNjcmliZXI+O1xuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBQcm9taXNlPFN1YnNjcmliZXI+O1xuXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzPzogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBQcm9taXNlPFN1YnNjcmliZXI+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPFN1YnNjcmliZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgbGV0IHN1YnNjcmliZXI6IFN1YnNjcmliZXI7XG5cbiAgICAgICAgICAgIGNvbnN0IGNhbGxiYWNrID0gKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShzdWJzY3JpYmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAoISFwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyID0gdGhpcy5zdWJzY3JpYmUoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVbnN1YnNjcmliZXMgZnJvbSBgc3Vic2NyaWJlcmAsIGF1dG9tYXRpY2FsbHkgcmVtb3ZpbmcgaXRzIGFzc29jaWF0ZWQgSFRNTCB2aWRlbyBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50IGZvciBlYWNoIHZpZGVvIGFzc29jaWF0ZWQgdG8gaXQgdGhhdCB3YXMgcmVtb3ZlZCBmcm9tIERPTS5cbiAgICAgKiBPbmx5IHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IHJlbW92ZWRcbiAgICAgKlxuICAgICAqIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZVxuICAgICAqL1xuICAgIHVuc3Vic2NyaWJlKHN1YnNjcmliZXI6IFN1YnNjcmliZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbklkID0gc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQ7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliaW5nIGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICd1bnN1YnNjcmliZUZyb21WaWRlbycsXG4gICAgICAgICAgICB7IHNlbmRlcjogc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgfSxcbiAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgdW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1Vuc3Vic2NyaWJlZCBjb3JyZWN0bHkgZnJvbSAnICsgY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2hlcyB0byB0aGUgU2Vzc2lvbiB0aGUgUHVibGlzaGVyIG9iamVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgdXBvbiBzdWNjZXNzZnVsIHRlcm1pbmF0aW9uIG9mIHRoaXMgbWV0aG9kLiBTZWUgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgbG9jYWwgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBvbmNlIHRoZSBtZWRpYSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHNvIHRoZXkgY2FuIHN1YnNjcmliZSB0byBpdC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHB1Ymxpc2hlciB3YXMgc3VjY2Vzc2Z1bGx5IHB1Ymxpc2hlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcik6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBwdWJsaXNoZXIuc2Vzc2lvbiA9IHRoaXM7XG4gICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnNlc3Npb24gPSB0aGlzO1xuXG4gICAgICAgICAgICBpZiAoIXB1Ymxpc2hlci5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgTk9UIGJlZW4gY2FsbGVkXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZFN0cmVhbShwdWJsaXNoZXIuc3RyZWFtKTtcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gJ1Nlc3Npb24udW5wdWJsaXNoKFB1Ymxpc2hlciknIGhhcyBiZWVuIGNhbGxlZC4gTXVzdCBpbml0aWFsaXplIGFnYWluIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZFN0cmVhbShwdWJsaXNoZXIuc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5yZWVzdGFibGlzaFN0cmVhbVBsYXlpbmdFdmVudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5wdWJsaXNoZXMgZnJvbSB0aGUgU2Vzc2lvbiB0aGUgUHVibGlzaGVyIG9iamVjdC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGlzIFB1Ymxpc2hlclxuICAgICAqIChvbmx5IHRob3NlIHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3VyIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyB0aGUgU3Vic2NyaWJlciBvYmplY3Qgb24geW91ciBvd24uXG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKi9cbiAgICB1bnB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzdHJlYW0gPSBwdWJsaXNoZXIuc3RyZWFtO1xuXG4gICAgICAgIGlmICghc3RyZWFtLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG51bGwnLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHN0cmVhbS5jb25uZWN0aW9uICE9PSB0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG5vdCB5b3VyIGxvY2FsIENvbm5lY3Rpb24uJyArXG4gICAgICAgICAgICAgICAgXCJPbmx5IG1vZGVyYXRvcnMgY2FuIGZvcmNlIHVucHVibGlzaCBvbiByZW1vdGUgU3RyZWFtcyB2aWEgJ2ZvcmNlVW5wdWJsaXNoJyBtZXRob2RcIiwgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnB1Ymxpc2hpbmcgbG9jYWwgbWVkaWEgKCcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgKyAnKScpO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCd1bnB1Ymxpc2hWaWRlbycsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdNZWRpYSB1bnB1Ymxpc2hlZCBjb3JyZWN0bHknKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBkZWxldGUgc3RyZWFtLmNvbm5lY3Rpb24uc3RyZWFtO1xuXG4gICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCBwdWJsaXNoZXIsICdzdHJlYW1EZXN0cm95ZWQnLCBwdWJsaXNoZXIuc3RyZWFtLCAndW5wdWJsaXNoJyk7XG4gICAgICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlbmRzIG9uZSBzaWduYWwuIGBzaWduYWxgIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBvcHRpb25hbCBwcm9wZXJ0aWVzOlxuICAgICAqIGBgYGpzb25cbiAgICAgKiB7ZGF0YTpzdHJpbmcsIHRvOkNvbm5lY3Rpb25bXSwgdHlwZTpzdHJpbmd9XG4gICAgICogYGBgXG4gICAgICogQWxsIHVzZXJzIHN1YnNjcmliZWQgdG8gdGhhdCBzaWduYWwgKGBzZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIC4uLilgIG9yIGBzZXNzaW9uLm9uKCdzaWduYWwnLCAuLi4pYCBmb3IgYWxsIHNpZ25hbHMpIGFuZCB3aG9zZSBDb25uZWN0aW9uIG9iamVjdHMgYXJlIGluIGB0b2AgYXJyYXkgd2lsbCByZWNlaXZlIGl0LiBUaGVpciBsb2NhbFxuICAgICAqIFNlc3Npb24gb2JqZWN0cyB3aWxsIGRpc3BhdGNoIGEgYHNpZ25hbGAgb3IgYHNpZ25hbDp0eXBlYCBldmVudC4gU2VlIFtbU2lnbmFsRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSBtZXNzYWdlIHN1Y2Nlc3NmdWxseSByZWFjaGVkIG9wZW52aWR1LXNlcnZlciBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90LiBfVGhpcyBkb2Vzbid0XG4gICAgICogbWVhbiB0aGF0IG9wZW52aWR1LXNlcnZlciBjb3VsZCByZXNlbmQgdGhlIG1lc3NhZ2UgdG8gYWxsIHRoZSBsaXN0ZWQgcmVjZWl2ZXJzLl9cbiAgICAgKi9cbiAgICAvKiB0c2xpbnQ6ZGlzYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuICAgIHNpZ25hbChzaWduYWw6IFNpZ25hbE9wdGlvbnMpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBzaWduYWxNZXNzYWdlID0ge307XG5cbiAgICAgICAgICAgIGlmIChzaWduYWwudG8gJiYgc2lnbmFsLnRvLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uSWRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgICAgICAgICAgc2lnbmFsLnRvLmZvckVhY2goY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25JZHMucHVzaChjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IGNvbm5lY3Rpb25JZHM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsnZGF0YSddID0gc2lnbmFsLmRhdGEgPyBzaWduYWwuZGF0YSA6ICcnO1xuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndHlwZSddID0gc2lnbmFsLnR5cGUgPyBzaWduYWwudHlwZSA6ICcnO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdzZW5kTWVzc2FnZScsIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBKU09OLnN0cmluZ2lmeShzaWduYWxNZXNzYWdlKVxuICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyogdHNsaW50OmVuYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcblxuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGVuYWJsZSBoYXJrICdzcGVha2luZycgZXZlbnQgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhc3RyLnNwZWVjaEV2ZW50ICYmIHN0ci5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZW5hYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGVuYWJsZSBoYXJrIGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuXG4gICAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnModHlwZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVlLm9mZih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZGlzYWJsYWUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICEhc3RyLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRKb2luZWQocmVzcG9uc2U6IENvbm5lY3Rpb25PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIC8vIENvbm5lY3Rpb24gc2hvdWxkbid0IGV4aXN0XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihyZXNwb25zZS5pZCwgJycpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQ29ubmVjdGlvbiAnICsgcmVzcG9uc2UuaWQgKyAnIGFscmVhZHkgZXhpc3RzIGluIGNvbm5lY3Rpb25zIGxpc3QnKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW3Jlc3BvbnNlLmlkXSA9IGNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRMZWZ0KG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLm5hbWUgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW0uc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBjb25uZWN0aW9uLCBtc2cucmVhc29uKV0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRQdWJsaXNoZWQocmVzcG9uc2U6IENvbm5lY3Rpb25PcHRpb25zKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgYWZ0ZXJDb25uZWN0aW9uRm91bmQgPSAoY29ubmVjdGlvbikgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdKSB7XG4gICAgICAgICAgICAgICAgLy8gQXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiBzdHJlYW0uc3Vic2NyaWJlKCkgaW4gXCJvblBhcnRpY2lwYW50UHVibGlzaGVkXCIgYW5kIGluIFwiam9pblJvb21cIiBycGMgY2FsbGJhY2tcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGNvbmRpdGlvbiBpcyBmYWxzZSBpZiBvcGVudmlkdS1zZXJ2ZXIgc2VuZHMgXCJwYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGV2ZW50IHRvIGEgc3Vic2NyaWJlciBwYXJ0aWNpcGFudCB0aGF0IGhhc1xuICAgICAgICAgICAgICAgIC8vIGFscmVhZHkgc3Vic2NyaWJlZCB0byBjZXJ0YWluIHN0cmVhbSBpbiB0aGUgY2FsbGJhY2sgb2YgXCJqb2luUm9vbVwiIG1ldGhvZFxuXG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIGNvbm5lY3Rpb24uc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEdldCB0aGUgZXhpc3RpbmcgQ29ubmVjdGlvbiBjcmVhdGVkIG9uICdvblBhcnRpY2lwYW50Sm9pbmVkJyBmb3JcbiAgICAgICAgLy8gZXhpc3RpbmcgcGFydGljaXBhbnRzIG9yIGNyZWF0ZSBhIG5ldyBvbmUgZm9yIG5ldyBwYXJ0aWNpcGFudHNcbiAgICAgICAgbGV0IGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG4gICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihyZXNwb25zZS5pZCwgXCJSZW1vdGUgY29ubmVjdGlvbiAnXCIgKyByZXNwb25zZS5pZCArIFwiJyB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb24gPT4ge1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBleGlzdGluZyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IGNvbjtcbiAgICAgICAgICAgICAgICByZXNwb25zZS5tZXRhZGF0YSA9IGNvbi5kYXRhO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ub3B0aW9ucyA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uaW5pdFJlbW90ZVN0cmVhbXMocmVzcG9uc2Uuc3RyZWFtcyk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBuZXcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFVucHVibGlzaGVkKG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgbXNnLm5hbWUgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oc3RyZWFtSWQpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZyk6IHZvaWQge1xuICAgICAgICAvKnRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cubmFtZSwgJ1JlbW90ZSBjb25uZWN0aW9uICcgKyBtc2cubmFtZSArIFwiIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudExlZnQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgc3RyZWFtLCAnZm9yY2VEaXNjb25uZWN0Jyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW0uc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBjb25uZWN0aW9uLCAnZm9yY2VEaXNjb25uZWN0JyldKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pOyovXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTmV3TWVzc2FnZShtc2cpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmZyb20sIFwiQ29ubmVjdGlvbiAnXCIgKyBtc2cuZnJvbSArIFwiJyB1bmtub3cgd2hlbiAnb25OZXdNZXNzYWdlJy4gRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiBcIlxuICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkgKyAnLiBFeGlzdGluZyBsb2NhbCBjb25uZWN0aW9uOiAnICsgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZClcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbCcsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmVuZHBvaW50TmFtZSwgJ0Nvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICcuIEljZSBjYW5kaWRhdGUgd2lsbCBiZSBpZ25vcmVkOiAnICsgY2FuZGlkYXRlKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGFkZGluZyBjYW5kaWRhdGUgZm9yICcgKyBzdHJlYW0uc3RyZWFtSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU2Vzc2lvbkNsb3NlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5pbmZvKCdTZXNzaW9uIGNsb3NlZDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuICAgICAgICBjb25zdCBzID0gbXNnLnJvb207XG4gICAgICAgIGlmIChzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uLWNsb3NlZCcsIFt7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbjogc1xuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIHVuZGVmaW5lZCBvbiBzZXNzaW9uIGNsb3NlZCcsIG1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25Mb3N0Q29ubmVjdGlvbigpOiB2b2lkIHtcblxuICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKHBhcmFtcyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIGNvbnN0IGVyciA9IHBhcmFtcy5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOicsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsZWF2ZShmb3JjZWQ6IGJvb2xlYW4sIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgZm9yY2VkID0gISFmb3JjZWQ7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnTGVhdmluZyBTZXNzaW9uIChmb3JjZWQ9JyArIGZvcmNlZCArICcpJyk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnbGVhdmVSb29tJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgIC8vIERpc3Bvc2UgUHVibGlzaGVyJ3MgIGxvY2FsIHN0cmVhbVxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgUHVibGlzaGVyIG9iamVjdCBkaXNwYXRjaCAnc3RyZWFtRGVzdHJveWVkJyBldmVudCBpZiB0aGUgU3RyZWFtIHdhcyBwdWJsaXNoZWRcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQtYnktZGlzY29ubmVjdCcsIFtyZWFzb25dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBTZXNzaW9uIG9iamVjdCBkaXNwYXRjaCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcgZXZlbnQgKGlmIGl0IGlzIG5vdCBhbHJlYWR5IGRpc3Bvc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMsIHJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICAgICAgICAgIHNlc3Npb25EaXNjb25uZWN0RXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IHdlcmUgbm90IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc3RhcnRXcygoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgam9pblBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiAoISF0b2tlbikgPyB0b2tlbiA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISF0aGlzLm9wdGlvbnMubWV0YWRhdGEgPyB0aGlzLm9wdGlvbnMubWV0YWRhdGEgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVudmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZGVyOiB0aGlzLm9wZW52aWR1LmdldFJlY29yZGVyKCksXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnam9pblJvb20nLCBqb2luUGFyYW1zLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSBsb2NhbCBDb25uZWN0aW9uIG9iamVjdCB3aXRoIHZhbHVlcyByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmRhdGEgPSByZXNwb25zZS5tZXRhZGF0YTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgcmVtb3RlIENvbm5lY3Rpb25zIHdpdGggdmFsdWUgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXZlbnRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uczogbmV3IEFycmF5PENvbm5lY3Rpb24+KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbXM6IG5ldyBBcnJheTxTdHJlYW0+KClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nUGFydGljaXBhbnRzOiBDb25uZWN0aW9uT3B0aW9uc1tdID0gcmVzcG9uc2UudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdQYXJ0aWNpcGFudHMuZm9yRWFjaChwYXJ0aWNpcGFudCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCBwYXJ0aWNpcGFudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLnB1c2goY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5wdXNoKGNvbm5lY3Rpb24uc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3duICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgdGhpcy5jb25uZWN0aW9uLCAnJyldKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGV4aXN0aW5nIGNvbm5lY3Rpb24gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMuZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdzdHJlYW1DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBhY3RpdmUgc3RyZWFtIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMuZm9yRWFjaChzdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGE6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0YWRhdGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPT09IGNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGxvY2FsIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmVtb3RlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZywgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbm5lY3Rpb24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSByZW1vdGUgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgIHJlc29sdmUoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBjb25uZWN0aW9uIG5vdCBmb3VuZC4gUmVqZWN0IHdpdGggT3BlblZpZHVFcnJvclxuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHRva2VuKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSA8c3RyaW5nPnVybC5zZWFyY2hQYXJhbXMuZ2V0KCdzZXNzaW9uSWQnKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0ID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3NlY3JldCcpO1xuICAgICAgICBjb25zdCByZWNvcmRlciA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyZWNvcmRlcicpO1xuXG4gICAgICAgIGlmICghIXNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcmVjb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucmVjb3JkZXIgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS53c1VyaSA9ICd3c3M6Ly8nICsgdXJsLmhvc3QgKyAnL29wZW52aWR1JztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFdlYlJ0Y1N0YXRzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cyc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5pbXBvcnQgKiBhcyBrdXJlbnRvVXRpbHMgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcyc7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBzdHJlYW1cbiAgICAgKi9cbiAgICBzdHJlYW1JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogYFwiQ0FNRVJBXCJgIG9yIGBcIlNDUkVFTlwiYC4gKnVuZGVmaW5lZCogaWYgc3RyZWFtIGlzIGF1ZGlvLW9ubHlcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbU1hbmFnZXIgb2JqZWN0IChbW1B1Ymxpc2hlcl1dIG9yIFtbU3Vic2NyaWJlcl1dKSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGlzIHN0cmVhbSBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcjogU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIHByaXZhdGUgd2ViUnRjUGVlcjogYW55O1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5ib3VuZFN0cmVhbU9wdHM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3BlZWNoRXZlbnQ6IGFueTtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlc3Npb246IFNlc3Npb24sIG9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zIHwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIHwge30pIHtcblxuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCdpZCcpKSB7XG4gICAgICAgICAgICAvLyBJbmJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBTdWJzY3JpYmVyXG4gICAgICAgICAgICB0aGlzLmluYm91bmRTdHJlYW1PcHRzID0gPEluYm91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9ICdTQ1JFRU4nO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ1NDUkVFTic7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NBTUVSQSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSAnTUlDUk8nO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnR5cGVPZlZpZGVvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaXNTZW5kQXVkaW8oKTtcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmlzU2VuZFZpZGVvKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVlLm9uKCdtZWRpYXN0cmVhbS11cGRhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnVwZGF0ZU1lZGlhU3RyZWFtKHRoaXMubWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnVmlkZW8gc3JjT2JqZWN0IFsnICsgdGhpcy5tZWRpYVN0cmVhbSArICddIHVwZGF0ZWQgaW4gc3RyZWFtIFsnICsgdGhpcy5zdHJlYW1JZCArICddJyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRNZWRpYVN0cmVhbSgpOiBNZWRpYVN0cmVhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRXZWJSdGNQZWVyKCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wZWVyQ29ubmVjdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLmhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1BlZXJTZW5kKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgb3B0aW9uczogYW55ID0ge1xuICAgICAgICAgICAgICAgIHZpZGVvU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoZXJyb3IsIHNkcE9mZmVyUGFyYW0sIHdwKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhwdWJsaXNoKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTZW5kaW5nIFNEUCBvZmZlciB0byBwdWJsaXNoIGFzICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncHVibGlzaFZpZGVvJywge1xuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbSxcbiAgICAgICAgICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHRoaXMuaXNTZW5kVmlkZW8oKSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86ICgodGhpcy5pc1NlbmRWaWRlbygpKSA/ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJykgOiAnJyksXG4gICAgICAgICAgICAgICAgICAgIGZyYW1lUmF0ZTogISF0aGlzLmZyYW1lUmF0ZSA/IHRoaXMuZnJhbWVSYXRlIDogLTFcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdFcnJvciBvbiBwdWJsaXNoVmlkZW86ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzU2RwQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiByZW1vdGUgbm93IHdlIGNhbiBzZXQgdGhlIHNyY09iamVjdCB2YWx1ZSBvZiB2aWRlbyBlbGVtZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gJ3N0cmVhbVBsYXlpbmcnIGV2ZW50IHdpbGwgYmUgdHJpZ2dlcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0ga3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIuV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGVyciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKHN1Y2Nlc3NDYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLldlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zLCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcihzdWNjZXNzQ2FsbGJhY2spO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5yZWN2VmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiJ1Nlc3Npb24uc3Vic2NyaWJlKFN0cmVhbSknIGNhbGxlZC4gQ29uc3RyYWludHMgb2YgZ2VuZXJhdGUgU0RQIG9mZmVyXCIsXG4gICAgICAgICAgICAgICAgb2ZmZXJDb25zdHJhaW50cyk7XG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogb2ZmZXJDb25zdHJhaW50c1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc0NhbGxiYWNrID0gKGVycm9yLCBzZHBPZmZlclBhcmFtLCB3cCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTZW5kaW5nIFNEUCBvZmZlciB0byBzdWJzY3JpYmUgdG8gJ1xuICAgICAgICAgICAgICAgICAgICArIHRoaXMuc3RyZWFtSWQsIHNkcE9mZmVyUGFyYW0pO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncmVjZWl2ZVZpZGVvRnJvbScsIHtcbiAgICAgICAgICAgICAgICAgICAgc2VuZGVyOiB0aGlzLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbVxuICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdFcnJvciBvbiByZWN2VmlkZW9Gcm9tOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NTZHBBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBrdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5XZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcihzdWNjZXNzQ2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcHJvY2Vzc1NkcEFuc3dlcihzZHBBbnN3ZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXIsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1Zyh0aGlzLnN0cmVhbUlkICsgJzogc2V0IHBlZXIgY29ubmVjdGlvbiB3aXRoIHJlY3ZkIFNEUCBhbnN3ZXInLCBzZHBBbnN3ZXIpO1xuXG4gICAgICAgICAgICBjb25zdCBzdHJlYW1JZCA9IHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgICAgICBjb25zdCBwZWVyQ29ubmVjdGlvbiA9IHRoaXMud2ViUnRjUGVlci5wZWVyQ29ubmVjdGlvbjtcbiAgICAgICAgICAgIHBlZXJDb25uZWN0aW9uLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlciwgKCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHJlbW90ZSBNZWRpYVN0cmVhbSBvYmplY3QgZXhjZXB0IHdoZW4gbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzTG9jYWwoKSB8fCB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBwZWVyQ29ubmVjdGlvbi5nZXRSZW1vdGVTdHJlYW1zKClbMF07XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1BlZXIgcmVtb3RlIHN0cmVhbScsIHRoaXMubWVkaWFTdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghIXRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0gJiYgdGhpcy5zZXNzaW9uLnNwZWFraW5nRXZlbnRzRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgICAgICB9LCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcih0aGlzLnN0cmVhbUlkICsgJzogRXJyb3Igc2V0dGluZyBTRFAgdG8gdGhlIHBlZXIgY29ubmVjdGlvbjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzID0gbmV3IFdlYlJ0Y1N0YXRzKHRoaXMpO1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RvcFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLndlYlJ0Y1N0YXRzICYmIHRoaXMud2ViUnRjU3RhdHMuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbCgpOiBib29sZWFuIHtcbiAgICAgICAgLy8gaW5ib3VuZCBvcHRpb25zIHVuZGVmaW5lZCBhbmQgb3V0Ym91bmQgb3B0aW9ucyBkZWZpbmVkXG4gICAgICAgIHJldHVybiAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgJiYgISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGB2aWRlb2AgZWxlbWVudCBwYXJhbWV0ZXIgZGlzcGxheSB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IGFyZVxuICAgICAqIFttYW5hZ2luZyB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd25dKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpXG4gICAgICpcbiAgICAgKiBDYWxsaW5nIHRoaXMgbWV0aG9kIHdpdGggYSB2aWRlbyBhbHJlYWR5IGFkZGVkIHRvIG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgY2F1c2UgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYmVcbiAgICAgKiBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBwcmV2aW91cyBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgdG8gYmUgYXNzb2NpYXRlZCB0byB0aGlzIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIDEgaWYgdGhlIHZpZGVvIHdhc24ndCBhc3NvY2lhdGVkIHRvIGFueSBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqIDAgaWYgdGhlIHZpZGVvIHdhcyBhbHJlYWR5IGFkZGVkIHRvIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXIuIC0xIGlmIHRoZSB2aWRlbyB3YXMgcHJldmlvdXNseSBhc3NvY2lhdGVkIHRvIGFueSBvdGhlclxuICAgICAqIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgb25lIGFuZCBwcm9wZXJseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKi9cbiAgICBhZGRWaWRlb0VsZW1lbnQodmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgLy8gSWYgdGhlIHZpZGVvIGVsZW1lbnQgaXMgYWxyZWFkeSBwYXJ0IG9mIHRoaXMgU3RyZWFtTWFuYWdlciBkbyBub3RoaW5nXG4gICAgICAgIGZvciAoY29uc3QgdiBvZiB0aGlzLnZpZGVvcykge1xuICAgICAgICAgICAgaWYgKHYudmlkZW8gPT09IHZpZGVvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmV0dXJuTnVtYmVyID0gMTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3Muc2xpY2UoKS5yZXZlcnNlKCkuZm9yRWFjaCgoc3RyZWFtTWFuYWdlclZpZGVvLCBpbmRleCwgdmlkZW9zKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgb25jYW5wbGF5IGV2ZW50IGxpc3RlbmVyIChvbmx5IE9wZW5WaWR1IGJyb3dzZXIgb25lLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICAgICAgaWYgKCEhc3RyZWFtTWFuYWdlclZpZGVvLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbW92ZSB2aWRlb3MgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyICh0aG9zZSBnZW5lcmF0ZWQgYnkgcGFzc2luZyBhIHZhbGlkIHRhcmdldEVsZW1lbnQgaW4gT3BlblZpZHUuaW5pdFB1Ymxpc2hlciBhbmQgU2Vzc2lvbi5zdWJzY3JpYmVcbiAgICAgICAgICAgICAgICAvLyBvciB0aG9zZSBjcmVhdGVkIGJ5IFN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KS4gVGhlc2UgYXJlIGFsc28gdGhlIHZpZGVvcyB0aGF0IHRyaWdnZXJlZCBhIHZpZGVvRWxlbWVudENyZWF0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucGFyZW50Tm9kZSEucmVtb3ZlQ2hpbGQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50RGVzdHJveWVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZSh2aWRlb3MubGVuZ3RoIC0gMSAtIGluZGV4LCAxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHNyY09iamVjdCBpbiBhbGwgdmlkZW9zIG1hbmFnZWQgYnkgdGhlIHVzZXJcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwcG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gY2FwdHVyZSBzb21lIGRlc2t0b3Agc2NyZWVuIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBoYXMgYmVlbiBjYWxsZWQgd2l0aCBwcm9wZXJ0aWVzIGB2aWRlb1NvdXJjZWAgYW5kIGBhdWRpb1NvdXJjZWAgb2ZcbiAgICAgKiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBwYXJhbWV0ZXIgYm90aCBzZXQgdG8gKmZhbHNlKiBvciAqbnVsbCpcbiAgICAgKi9cbiAgICBOT19JTlBVVF9TT1VSQ0VfU0VUID0gJ05PX0lOUFVUX1NPVVJDRV9TRVQnLFxuXG4gICAgLyoqXG4gICAgICogU29tZSBtZWRpYSBwcm9wZXJ0eSBvZiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBzdWNoIGFzIGBmcmFtZVJhdGVgIG9yIGByZXNvbHV0aW9uYCBpcyBub3Qgc3VwcG9ydGVkXG4gICAgICogYnkgdGhlIGlucHV0IGRldmljZXMgKHdoZW5ldmVyIGl0IGlzIHBvc3NpYmxlIHRoZXkgYXJlIGF1dG9tYXRpY2FsbHkgYWRqdXN0ZWQgdG8gdGhlIG1vc3Qgc2ltaWxhciB2YWx1ZSkuXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEID0gJ09QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuLyoqXG4gKiBTaW1wbGUgb2JqZWN0IHRvIGlkZW50aWZ5IHJ1bnRpbWUgZXJyb3JzIG9uIHRoZSBjbGllbnQgc2lkZVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHVFcnJvciB7XG5cbiAgICBuYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBIb3cgdGhlIHZpZGVvIHdpbGwgYmUgaW5zZXJ0ZWQgaW4gdGhlIERPTSBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuIFNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dIGFuZCBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXVxuICovXG5leHBvcnQgZW51bSBWaWRlb0luc2VydE1vZGUge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHRhcmdldCBlbGVtZW50IChhcyBuZXh0IHNpYmxpbmcpXG4gICAgICovXG4gICAgQUZURVIgPSAnQUZURVInLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGxhc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgQVBQRU5EID0gJ0FQUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYmVmb3JlIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgcHJldmlvdXMgc2libGluZylcbiAgICAgKi9cbiAgICBCRUZPUkUgPSAnQkVGT1JFJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBmaXJzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBQUkVQRU5EID0gJ1BSRVBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIHJlcGxhY2VzIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUkVQTEFDRSA9ICdSRVBMQUNFJ1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYGNvbm5lY3Rpb25DcmVhdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgY29ubmVjdGlvbkRlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgd2FzIGNyZWF0ZWQgb3IgZGVzdHJveWVkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZvciAnY29ubmVjdGlvbkRlc3Ryb3llZCcgZXZlbnQ6XG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3VyIHRoYXQgbWF5IGJlIHByZXZlbnRlZCBieSBjYWxsaW5nIFtbRXZlbnQucHJldmVudERlZmF1bHRdXVxuICAgICAqL1xuICAgIGNhbmNlbGFibGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0IHRoYXQgZGlzcGF0Y2hlZCB0aGUgZXZlbnRcbiAgICAgKi9cbiAgICB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHR5cGUgb2YgZXZlbnQuIFRoaXMgaXMgdGhlIHNhbWUgc3RyaW5nIHlvdSBwYXNzIGFzIGZpcnN0IHBhcmFtZXRlciB3aGVuIGNhbGxpbmcgbWV0aG9kIGBvbigpYCBvZiBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBbW0V2ZW50RGlzcGF0Y2hlcl1dIGludGVyZmFjZVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIHByaXZhdGUgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvdXI6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvdXIgPSAoKSA9PiB7IH07XG4gICAgICAgIHRoaXMuaGFzQmVlblByZXZlbnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHJlY29yZGluZ1N0YXJ0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGByZWNvcmRpbmdTdG9wcGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIElEIGdlbmVyYXRlZCBpbiBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlY29yZGluZyBuYW1lIHlvdSBzdXBwbGllZCB0byBvcGVudmlkdS1zZXJ2ZXIuIEZvciBleGFtcGxlLCB0byBuYW1lIHlvdXIgcmVjb3JkaW5nIGZpbGUgTVlfUkVDT1JESU5HOlxuICAgICAqIC0gV2l0aCAqKkFQSSBSRVNUKio6IFBPU1QgdG8gYC9hcGkvcmVjb3JkaW5ncy9zdGFydGAgcGFzc2luZyBKU09OIGJvZHkgYHtcInNlc3Npb25cIjpcInNlc3Npb25JZFwiLFwibmFtZVwiOlwiTVlfUkVDT1JESU5HXCJ9YFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LWphdmEtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIE1ZX1JFQ09SRElORylgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKE1ZX1JFQ09SRElORykuYnVpbGQoKSlgXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtbm9kZS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgTVlfUkVDT1JESU5HKWAgb3IgYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgbmV3IFJlY29yZGluZ1Byb3BlcnRpZXMuQnVpbGRlcigpLm5hbWUoTVlfUkVDT1JESU5HKS5idWlsZCgpKWBcbiAgICAgKlxuICAgICAqIElmIG5vIG5hbWUgaXMgc3VwcGxpZWQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSB1bmRlZmluZWQgYW5kIHRoZSByZWNvcmRlZCBmaWxlIHdpbGwgYmUgbmFtZWQgYWZ0ZXIgcHJvcGVydHkgW1tpZF1dXG4gICAgICovXG4gICAgbmFtZT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIGlmIChuYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogeW91IGhhdmUgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogeW91ciBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHRydWUsIHRhcmdldCwgJ3Nlc3Npb25EaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkNhbGxpbmcgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvdXIoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEZvciAnc3RyZWFtRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwidW5wdWJsaXNoXCI6IG1ldGhvZCBgU2Vzc2lvbi51bnB1Ymxpc2goKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogbWV0aG9kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcIm5ldHdvcmtEaXNjb25uZWN0XCI6IHRoZSB1c2VyJ3MgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ3N0cmVhbUNyZWF0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFB1Ymxpc2hlciwgdHlwZTogc3RyaW5nLCBzdHJlYW06IFN0cmVhbSwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgUHVibGlzaGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9jYWwgU3RyZWFtXG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW91ciB1cG9uICdcIiArIHRoaXMudHlwZSArIFwiJyBldmVudCBkaXNwYXRjaGVkIGJ5ICdQdWJsaXNoZXInXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHZpZGVvRWxlbWVudENyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuIFNlZVxuICogW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uLlxuICogLSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSB3aGVuZXZlciBhbiBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWRlb0VsZW1lbnRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGVsZW1lbnQgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBlbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQsIHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiZnVuY3Rpb24gTWFwcGVyKClcbntcbiAgdmFyIHNvdXJjZXMgPSB7fTtcblxuXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKVxuICB7XG4gICAgZm9yKHZhciBrZXkgaW4gc291cmNlcylcbiAgICB7XG4gICAgICB2YXIgc291cmNlID0gc291cmNlc1trZXldO1xuXG4gICAgICBmb3IodmFyIGtleTIgaW4gc291cmNlKVxuICAgICAgICBjYWxsYmFjayhzb3VyY2Vba2V5Ml0pO1xuICAgIH07XG4gIH07XG5cbiAgdGhpcy5nZXQgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBpZHNbaWRdO1xuICB9O1xuXG4gIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcblxuICAgIGRlbGV0ZSBpZHNbaWRdO1xuXG4gICAgLy8gQ2hlY2sgaXQncyBlbXB0eVxuICAgIGZvcih2YXIgaSBpbiBpZHMpe3JldHVybiBmYWxzZX1cblxuICAgIGRlbGV0ZSBzb3VyY2VzW3NvdXJjZV07XG4gIH07XG5cbiAgdGhpcy5zZXQgPSBmdW5jdGlvbih2YWx1ZSwgaWQsIHNvdXJjZSlcbiAge1xuICAgIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHNvdXJjZXNbc291cmNlXSA9IGlkcyA9IHt9O1xuXG4gICAgaWRzW2lkXSA9IHZhbHVlO1xuICB9O1xufTtcblxuXG5NYXBwZXIucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG57XG4gIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGlkLCBzb3VyY2UpO1xuICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICByZXR1cm4gdmFsdWU7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gTWFwcGVyO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBKc29uUnBjQ2xpZW50ICA9IHJlcXVpcmUoJy4vanNvbnJwY2NsaWVudCcpO1xuXG5cbmV4cG9ydHMuSnNvblJwY0NsaWVudCAgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uLycpO1xudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5EYXRlLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiArbmV3IERhdGU7XG59O1xuXG52YXIgUElOR19JTlRFUlZBTCA9IDUwMDA7XG5cbnZhciBSRUNPTk5FQ1RJTkcgPSAnUkVDT05ORUNUSU5HJztcbnZhciBDT05ORUNURUQgPSAnQ09OTkVDVEVEJztcbnZhciBESVNDT05ORUNURUQgPSAnRElTQ09OTkVDVEVEJztcblxudmFyIExvZ2dlciA9IGNvbnNvbGU7XG5cbi8qKlxuICpcbiAqIGhlYXJ0YmVhdDogaW50ZXJ2YWwgaW4gbXMgZm9yIGVhY2ggaGVhcnRiZWF0IG1lc3NhZ2UsXG4gKiBzZW5kQ2xvc2VNZXNzYWdlIDogdHJ1ZSAvIGZhbHNlLCBiZWZvcmUgY2xvc2luZyB0aGUgY29ubmVjdGlvbiwgaXQgc2VuZHMgYSBjbG9zZVNlc3Npb24gbWVzc2FnZVxuICogPHByZT5cbiAqIHdzIDoge1xuICogXHR1cmkgOiBVUkkgdG8gY29ubnRlY3QgdG8sXG4gKiAgdXNlU29ja0pTIDogdHJ1ZSAodXNlIFNvY2tKUykgLyBmYWxzZSAodXNlIFdlYlNvY2tldCkgYnkgZGVmYXVsdCxcbiAqIFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuICogXHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcbiAqIFx0b25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG4gKiBcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbiAqIFx0b25lcnJvciA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGVyZSBpcyBhbiBlcnJvclxuICogfSxcbiAqIHJwYyA6IHtcbiAqIFx0cmVxdWVzdFRpbWVvdXQgOiB0aW1lb3V0IGZvciBhIHJlcXVlc3QsXG4gKiBcdHNlc3Npb25TdGF0dXNDaGFuZ2VkOiBjYWxsYmFjayBtZXRob2QgZm9yIGNoYW5nZXMgaW4gc2Vzc2lvbiBzdGF0dXMsXG4gKiBcdG1lZGlhUmVuZWdvdGlhdGlvbjogbWVkaWFSZW5lZ290aWF0aW9uXG4gKiB9XG4gKiA8L3ByZT5cbiAqL1xuZnVuY3Rpb24gSnNvblJwY0NsaWVudChjb25maWd1cmF0aW9uKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgd3NDb25maWcgPSBjb25maWd1cmF0aW9uLndzO1xuXG4gICAgdmFyIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSAtMTtcblxuICAgIHZhciBwaW5nTmV4dE51bSA9IDA7XG4gICAgdmFyIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgdmFyIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgIHZhciBwaW5nSW50ZXJ2YWw7XG5cbiAgICB2YXIgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgdmFyIG9ucmVjb25uZWN0aW5nID0gd3NDb25maWcub25yZWNvbm5lY3Rpbmc7XG4gICAgdmFyIG9ucmVjb25uZWN0ZWQgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGVkO1xuICAgIHZhciBvbmNvbm5lY3RlZCA9IHdzQ29uZmlnLm9uY29ubmVjdGVkO1xuICAgIHZhciBvbmVycm9yID0gd3NDb25maWcub25lcnJvcjtcblxuICAgIGNvbmZpZ3VyYXRpb24ucnBjLnB1bGwgPSBmdW5jdGlvbihwYXJhbXMsIHJlcXVlc3QpIHtcbiAgICAgICAgcmVxdWVzdC5yZXBseShudWxsLCBcInB1c2hcIik7XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNUSU5HIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBSRUNPTk5FQ1RJTkcpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIFJFQ09OTkVDVElORyBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVElORyBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXR1cyA9IFJFQ09OTkVDVElORztcbiAgICAgICAgaWYgKG9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9ucmVjb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uY29ubmVjdGVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05DT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVzZVBpbmcoKTtcblxuICAgICAgICBpZiAob25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9ORVJST1IgLS0tLS0tLS0tLS1cIik7XG5cbiAgICAgICAgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgICAgIGlmIChvbmVycm9yKSB7XG4gICAgICAgICAgICBvbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKHdzQ29uZmlnKTtcblxuICAgIExvZ2dlci5kZWJ1ZygnQ29ubmVjdGluZyB3ZWJzb2NrZXQgdG8gVVJJOiAnICsgd3NDb25maWcudXJpKTtcblxuICAgIHZhciBycGNCdWlsZGVyT3B0aW9ucyA9IHtcbiAgICAgICAgcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5yZXF1ZXN0VGltZW91dCxcbiAgICAgICAgcGluZ19yZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLmhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0XG4gICAgfTtcblxuICAgIHZhciBycGMgPSBuZXcgUnBjQnVpbGRlcihScGNCdWlsZGVyLnBhY2tlcnMuSnNvblJQQywgcnBjQnVpbGRlck9wdGlvbnMsIHdzLFxuICAgICAgICBmdW5jdGlvbihyZXF1ZXN0KSB7XG5cbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVjZWl2ZWQgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IGNvbmZpZ3VyYXRpb24ucnBjW3JlcXVlc3QubWV0aG9kXTtcblxuICAgICAgICAgICAgICAgIGlmIChmdW5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWV0aG9kIFwiICsgcmVxdWVzdC5tZXRob2QgKyBcIiBub3QgcmVnaXN0ZXJlZCBpbiBjbGllbnRcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyhyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKCdFeGNlcHRpb24gcHJvY2Vzc2luZyByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAobWV0aG9kICE9PSAncGluZycpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVxdWVzdDogbWV0aG9kOicgKyBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgcnBjLmVuY29kZShtZXRob2QsIHBhcmFtcywgZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1I6XCIgKyBlcnJvci5tZXNzYWdlICsgXCIgaW4gUmVxdWVzdDogbWV0aG9kOlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyBcIiByZXF1ZXN0OlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1IgREFUQTpcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yLmRhdGEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdFRpbWUgPSByZXF1ZXN0VGltZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT0gdW5kZWZpbmVkICYmIHJlc3VsdC52YWx1ZSAhPT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVzcG9uc2U6ICcgKyBKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIm5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBcIiArIHBpbmdOZXh0TnVtICsgJyAob2xkPScgK1xuICAgICAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiArICcpJyk7XG4gICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBwaW5nTmV4dE51bTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZW5kUGluZygpIHtcbiAgICAgICAgaWYgKGVuYWJsZWRQaW5ncykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG51bGw7XG4gICAgICAgICAgICBpZiAocGluZ05leHROdW0gPT0gMCB8fCBwaW5nTmV4dE51bSA9PSBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbDogY29uZmlndXJhdGlvbi5oZWFydGJlYXQgfHwgUElOR19JTlRFUlZBTFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwaW5nTmV4dE51bSsrO1xuXG4gICAgICAgICAgICBzZWxmLnNlbmQoJ3BpbmcnLCBwYXJhbXMsIChmdW5jdGlvbihwaW5nTnVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJFcnJvciBpbiBwaW5nIHJlcXVlc3QgI1wiICsgcGluZ051bSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubWVzc2FnZSArIFwiKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaW5nTnVtID4gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZXJ2ZXIgZGlkIG5vdCByZXNwb25kIHRvIHBpbmcgbWVzc2FnZSAjXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5nTnVtICsgXCIuIFJlY29ubmVjdGluZy4uLiBcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKHBpbmdOZXh0TnVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUcnlpbmcgdG8gc2VuZCBwaW5nLCBidXQgcGluZyBpcyBub3QgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgKiBJZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0IGhhcyBhbnkgdmFsdWUsIHRoZSBwaW5nLXBvbmcgd2lsbCB3b3JrIHdpdGggdGhlIGludGVydmFsXG4gICAgKiBvZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0XG4gICAgKi9cbiAgICBmdW5jdGlvbiB1c2VQaW5nKCkge1xuICAgICAgICBpZiAoIXBpbmdQb25nU3RhcnRlZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgcGluZyAoaWYgY29uZmlndXJlZClcIilcbiAgICAgICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwaW5nSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzZW5kUGluZywgY29uZmlndXJhdGlvbi5oZWFydGJlYXQpO1xuICAgICAgICAgICAgICAgIHNlbmRQaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NpbmcganNvblJwY0NsaWVudCBleHBsaWNpdGx5IGJ5IGNsaWVudFwiKTtcblxuICAgICAgICBpZiAocGluZ0ludGVydmFsICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xlYXJpbmcgcGluZyBpbnRlcnZhbFwiKTtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGNvbmZpZ3VyYXRpb24uc2VuZENsb3NlTWVzc2FnZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VuZGluZyBjbG9zZSBtZXNzYWdlXCIpXG4gICAgICAgICAgICB0aGlzLnNlbmQoJ2Nsb3NlU2Vzc2lvbicsIG51bGwsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyBjbG9zZSBtZXNzYWdlOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcblx0XHRcdHdzLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIHdzLmZvcmNlQ2xvc2UobWlsbGlzKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlY29ubmVjdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpzb25ScGNDbGllbnQ7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gID0gcmVxdWlyZSgnLi93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cblxuZXhwb3J0cy5XZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb247IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxMy0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIEJyb3dzZXJXZWJTb2NrZXQgPSBnbG9iYWwuV2ViU29ja2V0IHx8IGdsb2JhbC5Nb3pXZWJTb2NrZXQ7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqIEdldCBlaXRoZXIgdGhlIGBXZWJTb2NrZXRgIG9yIGBNb3pXZWJTb2NrZXRgIGdsb2JhbHNcbiAqIGluIHRoZSBicm93c2VyIG9yIHRyeSB0byByZXNvbHZlIFdlYlNvY2tldC1jb21wYXRpYmxlXG4gKiBpbnRlcmZhY2UgZXhwb3NlZCBieSBgd3NgIGZvciBOb2RlLWxpa2UgZW52aXJvbm1lbnQuXG4gKi9cblxuLyp2YXIgV2ViU29ja2V0ID0gQnJvd3NlcldlYlNvY2tldDtcbmlmICghV2ViU29ja2V0ICYmIHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgV2ViU29ja2V0ID0gcmVxdWlyZSgnd3MnKTtcbiAgICB9IGNhdGNoIChlKSB7IH1cbn0qL1xuXG4vL3ZhciBTb2NrSlMgPSByZXF1aXJlKCdzb2NranMtY2xpZW50Jyk7XG5cbnZhciBNQVhfUkVUUklFUyA9IDIwMDA7IC8vIEZvcmV2ZXIuLi5cbnZhciBSRVRSWV9USU1FX01TID0gMzAwMDsgLy8gRklYTUU6IEltcGxlbWVudCBleHBvbmVudGlhbCB3YWl0IHRpbWVzLi4uXG5cbnZhciBDT05ORUNUSU5HID0gMDtcbnZhciBPUEVOID0gMTtcbnZhciBDTE9TSU5HID0gMjtcbnZhciBDTE9TRUQgPSAzO1xuXG4vKlxuY29uZmlnID0ge1xuXHRcdHVyaSA6IHdzVXJpLFxuXHRcdHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG5cdFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuXHRcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuXHRcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuXHRcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNC0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKVxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIFVBUGFyc2VyID0gcmVxdWlyZSgndWEtcGFyc2VyLWpzJylcbnZhciB1dWlkID0gcmVxdWlyZSgndXVpZCcpXG52YXIgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKVxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyXG52YXIgcmVjdXJzaXZlID0gcmVxdWlyZSgnbWVyZ2UnKS5yZWN1cnNpdmUuYmluZCh1bmRlZmluZWQsIHRydWUpXG52YXIgc2RwVHJhbnNsYXRvciA9IHJlcXVpcmUoJ3NkcC10cmFuc2xhdG9yJylcbnZhciBsb2dnZXIgPSB3aW5kb3cuTG9nZ2VyIHx8IGNvbnNvbGVcblxuLy8gdmFyIGdVTSA9IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhIHx8IGZ1bmN0aW9uIChjb25zdHJhaW50cykge1xuLy8gICByZXR1cm4gbmV3IFByb21pc2UobmF2aWdhdG9yLmdldFVzZXJNZWRpYShjb25zdHJhaW50cywgZnVuY3Rpb24gKHN0cmVhbSkge1xuLy8gICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4vLyAgICAgc3RhcnQoKVxuLy8gICB9KS5lcm9yKGNhbGxiYWNrKSk7XG4vLyB9XG5cbi8qdHJ5IHtcbiAgcmVxdWlyZSgna3VyZW50by1icm93c2VyLWV4dGVuc2lvbnMnKVxufSBjYXRjaCAoZXJyb3IpIHtcbiAgaWYgKHR5cGVvZiBnZXRTY3JlZW5Db25zdHJhaW50cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBsb2dnZXIud2Fybignc2NyZWVuIHNoYXJpbmcgaXMgbm90IGF2YWlsYWJsZScpXG5cbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyA9IGZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKHNlbmRTb3VyY2UsIGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoXCJUaGlzIGxpYnJhcnkgaXMgbm90IGVuYWJsZWQgZm9yIHNjcmVlbiBzaGFyaW5nXCIpKVxuICAgIH1cbiAgfVxufSovXG5cbnZhciBNRURJQV9DT05TVFJBSU5UUyA9IHtcbiAgYXVkaW86IHRydWUsXG4gIHZpZGVvOiB7XG4gICAgd2lkdGg6IDY0MCxcbiAgICBmcmFtZXJhdGU6IDE1XG4gIH1cbn1cblxuLy8gU29tZWhvdywgdGhlIFVBUGFyc2VyIGNvbnN0cnVjdG9yIGdldHMgYW4gZW1wdHkgd2luZG93IG9iamVjdC5cbi8vIFdlIG5lZWQgdG8gcGFzcyB0aGUgdXNlciBhZ2VudCBzdHJpbmcgaW4gb3JkZXIgdG8gZ2V0IGluZm9ybWF0aW9uXG52YXIgdWEgPSAod2luZG93ICYmIHdpbmRvdy5uYXZpZ2F0b3IpID8gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQgOiAnJ1xudmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcih1YSlcbnZhciBicm93c2VyID0gcGFyc2VyLmdldEJyb3dzZXIoKVxuXG52YXIgdXNlUGxhbkIgPSBmYWxzZVxuaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gIGxvZ2dlci5kZWJ1Zyhicm93c2VyLm5hbWUgKyBcIjogdXNpbmcgU0RQIFBsYW5CXCIpXG4gIHVzZVBsYW5CID0gdHJ1ZVxufVxuXG5mdW5jdGlvbiBub29wKGVycm9yKSB7XG4gIGlmIChlcnJvcikgbG9nZ2VyLmVycm9yKGVycm9yKVxufVxuXG5mdW5jdGlvbiB0cmFja1N0b3AodHJhY2spIHtcbiAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbn1cblxuZnVuY3Rpb24gc3RyZWFtU3RvcChzdHJlYW0pIHtcbiAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2godHJhY2tTdG9wKVxufVxuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBTZXNzaW9uRGVzY3JpcHRpb24gb2JqZWN0LlxuICovXG52YXIgZHVtcFNEUCA9IGZ1bmN0aW9uIChkZXNjcmlwdGlvbikge1xuICBpZiAodHlwZW9mIGRlc2NyaXB0aW9uID09PSAndW5kZWZpbmVkJyB8fCBkZXNjcmlwdGlvbiA9PT0gbnVsbCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgcmV0dXJuICd0eXBlOiAnICsgZGVzY3JpcHRpb24udHlwZSArICdcXHJcXG4nICsgZGVzY3JpcHRpb24uc2RwXG59XG5cbmZ1bmN0aW9uIGJ1ZmZlcml6ZUNhbmRpZGF0ZXMocGMsIG9uZXJyb3IpIHtcbiAgdmFyIGNhbmRpZGF0ZXNRdWV1ZSA9IFtdXG5cbiAgcGMuYWRkRXZlbnRMaXN0ZW5lcignc2lnbmFsaW5nc3RhdGVjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlLmxlbmd0aCkge1xuICAgICAgICB2YXIgZW50cnkgPSBjYW5kaWRhdGVzUXVldWUuc2hpZnQoKVxuICAgICAgICBwYy5hZGRJY2VDYW5kaWRhdGUoZW50cnkuY2FuZGlkYXRlLCBlbnRyeS5jYWxsYmFjaywgZW50cnkuY2FsbGJhY2spXG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4gIHJldHVybiBmdW5jdGlvbiAoY2FuZGlkYXRlLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgb25lcnJvclxuXG4gICAgc3dpdGNoIChwYy5zaWduYWxpbmdTdGF0ZSkge1xuICAgIGNhc2UgJ2Nsb3NlZCc6XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoJ1BlZXJDb25uZWN0aW9uIG9iamVjdCBpcyBjbG9zZWQnKSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdzdGFibGUnOlxuICAgICAgaWYgKHBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgIHBjLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIGNhbGxiYWNrLCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgY2FuZGlkYXRlc1F1ZXVlLnB1c2goe1xuICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZSxcbiAgICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG4vKiBTaW11bGNhc3QgdXRpbGl0aWVzICovXG5cbmZ1bmN0aW9uIHJlbW92ZUZJREZyb21PZmZlcihzZHApIHtcbiAgdmFyIG4gPSBzZHAuaW5kZXhPZihcImE9c3NyYy1ncm91cDpGSURcIik7XG5cbiAgaWYgKG4gPiAwKSB7XG4gICAgcmV0dXJuIHNkcC5zbGljZSgwLCBuKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc2RwO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFNpbXVsY2FzdEluZm8odmlkZW9TdHJlYW0pIHtcbiAgdmFyIHZpZGVvVHJhY2tzID0gdmlkZW9TdHJlYW0uZ2V0VmlkZW9UcmFja3MoKTtcbiAgaWYgKCF2aWRlb1RyYWNrcy5sZW5ndGgpIHtcbiAgICBsb2dnZXIud2FybignTm8gdmlkZW8gdHJhY2tzIGF2YWlsYWJsZSBpbiB0aGUgdmlkZW8gc3RyZWFtJylcbiAgICByZXR1cm4gJydcbiAgfVxuICB2YXIgbGluZXMgPSBbXG4gICAgJ2E9eC1nb29nbGUtZmxhZzpjb25mZXJlbmNlJyxcbiAgICAnYT1zc3JjLWdyb3VwOlNJTSAxIDIgMycsXG4gICAgJ2E9c3NyYzoxIGNuYW1lOmxvY2FsVmlkZW8nLFxuICAgICdhPXNzcmM6MSBtc2lkOicgKyB2aWRlb1N0cmVhbS5pZCArICcgJyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MSBtc2xhYmVsOicgKyB2aWRlb1N0cmVhbS5pZCxcbiAgICAnYT1zc3JjOjEgbGFiZWw6JyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MiBjbmFtZTpsb2NhbFZpZGVvJyxcbiAgICAnYT1zc3JjOjIgbXNpZDonICsgdmlkZW9TdHJlYW0uaWQgKyAnICcgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjIgbXNsYWJlbDonICsgdmlkZW9TdHJlYW0uaWQsXG4gICAgJ2E9c3NyYzoyIGxhYmVsOicgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjMgY25hbWU6bG9jYWxWaWRlbycsXG4gICAgJ2E9c3NyYzozIG1zaWQ6JyArIHZpZGVvU3RyZWFtLmlkICsgJyAnICsgdmlkZW9UcmFja3NbMF0uaWQsXG4gICAgJ2E9c3NyYzozIG1zbGFiZWw6JyArIHZpZGVvU3RyZWFtLmlkLFxuICAgICdhPXNzcmM6MyBsYWJlbDonICsgdmlkZW9UcmFja3NbMF0uaWRcbiAgXTtcblxuICBsaW5lcy5wdXNoKCcnKTtcblxuICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG59XG5cbi8qKlxuICogV3JhcHBlciBvYmplY3Qgb2YgYW4gUlRDUGVlckNvbm5lY3Rpb24uIFRoaXMgb2JqZWN0IGlzIGFpbWVkIHRvIHNpbXBsaWZ5IHRoZVxuICogZGV2ZWxvcG1lbnQgb2YgV2ViUlRDLWJhc2VkIGFwcGxpY2F0aW9ucy5cbiAqXG4gKiBAY29uc3RydWN0b3IgbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1vZGUgTW9kZSBpbiB3aGljaCB0aGUgUGVlckNvbm5lY3Rpb24gd2lsbCBiZSBjb25maWd1cmVkLlxuICogIFZhbGlkIHZhbHVlcyBhcmU6ICdyZWN2JywgJ3NlbmQnLCBhbmQgJ3NlbmRSZWN2J1xuICogQHBhcmFtIGxvY2FsVmlkZW8gVmlkZW8gdGFnIGZvciB0aGUgbG9jYWwgc3RyZWFtXG4gKiBAcGFyYW0gcmVtb3RlVmlkZW8gVmlkZW8gdGFnIGZvciB0aGUgcmVtb3RlIHN0cmVhbVxuICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gdmlkZW9TdHJlYW0gU3RyZWFtIHRvIGJlIHVzZWQgYXMgcHJpbWFyeSBzb3VyY2VcbiAqICAodHlwaWNhbGx5IHZpZGVvIGFuZCBhdWRpbywgb3Igb25seSB2aWRlbyBpZiBjb21iaW5lZCB3aXRoIGF1ZGlvU3RyZWFtKSBmb3JcbiAqICBsb2NhbFZpZGVvIGFuZCB0byBiZSBhZGRlZCBhcyBzdHJlYW0gdG8gdGhlIFJUQ1BlZXJDb25uZWN0aW9uXG4gKiBAcGFyYW0ge01lZGlhU3RyZWFtfSBhdWRpb1N0cmVhbSBTdHJlYW0gdG8gYmUgdXNlZCBhcyBzZWNvbmQgc291cmNlXG4gKiAgKHR5cGljYWxseSBmb3IgYXVkaW8pIGZvciBsb2NhbFZpZGVvIGFuZCB0byBiZSBhZGRlZCBhcyBzdHJlYW0gdG8gdGhlXG4gKiAgUlRDUGVlckNvbm5lY3Rpb25cbiAqL1xuZnVuY3Rpb24gV2ViUnRjUGVlcihtb2RlLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlcikpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXIobW9kZSwgb3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyLnN1cGVyXy5jYWxsKHRoaXMpXG5cbiAgaWYgKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIGNhbGxiYWNrID0gb3B0aW9uc1xuICAgIG9wdGlvbnMgPSB1bmRlZmluZWRcbiAgfVxuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gIGNhbGxiYWNrID0gKGNhbGxiYWNrIHx8IG5vb3ApLmJpbmQodGhpcylcblxuICB2YXIgc2VsZiA9IHRoaXNcbiAgdmFyIGxvY2FsVmlkZW8gPSBvcHRpb25zLmxvY2FsVmlkZW9cbiAgdmFyIHJlbW90ZVZpZGVvID0gb3B0aW9ucy5yZW1vdGVWaWRlb1xuICB2YXIgdmlkZW9TdHJlYW0gPSBvcHRpb25zLnZpZGVvU3RyZWFtXG4gIHZhciBhdWRpb1N0cmVhbSA9IG9wdGlvbnMuYXVkaW9TdHJlYW1cbiAgdmFyIG1lZGlhQ29uc3RyYWludHMgPSBvcHRpb25zLm1lZGlhQ29uc3RyYWludHNcblxuICB2YXIgY29ubmVjdGlvbkNvbnN0cmFpbnRzID0gb3B0aW9ucy5jb25uZWN0aW9uQ29uc3RyYWludHNcbiAgdmFyIHBjID0gb3B0aW9ucy5wZWVyQ29ubmVjdGlvblxuICB2YXIgc2VuZFNvdXJjZSA9IG9wdGlvbnMuc2VuZFNvdXJjZSB8fCAnd2ViY2FtJ1xuXG4gIC8qdmFyIGRhdGFDaGFubmVsQ29uZmlnID0gb3B0aW9ucy5kYXRhQ2hhbm5lbENvbmZpZ1xuICB2YXIgdXNlRGF0YUNoYW5uZWxzID0gb3B0aW9ucy5kYXRhQ2hhbm5lbHMgfHwgZmFsc2VcbiAgdmFyIGRhdGFDaGFubmVsKi9cblxuICB2YXIgZ3VpZCA9IHV1aWQudjQoKVxuICB2YXIgY29uZmlndXJhdGlvbiA9IHJlY3Vyc2l2ZSh7XG4gICAgICBpY2VTZXJ2ZXJzOiAoISFvcHRpb25zLmljZVNlcnZlcnMgJiYgb3B0aW9ucy5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDApID8gb3B0aW9ucy5pY2VTZXJ2ZXJzIDogZnJlZWljZSgpXG4gICAgfSxcbiAgICBvcHRpb25zLmNvbmZpZ3VyYXRpb24pXG5cbiAgdmFyIG9uaWNlY2FuZGlkYXRlID0gb3B0aW9ucy5vbmljZWNhbmRpZGF0ZVxuICBpZiAob25pY2VjYW5kaWRhdGUpIHRoaXMub24oJ2ljZWNhbmRpZGF0ZScsIG9uaWNlY2FuZGlkYXRlKVxuXG4gIHZhciBvbmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBvcHRpb25zLm9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZVxuICBpZiAob25jYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgdGhpcy5vbignY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScsIG9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSlcbiAgfVxuXG4gIHZhciBzaW11bGNhc3QgPSBvcHRpb25zLnNpbXVsY2FzdFxuICB2YXIgbXVsdGlzdHJlYW0gPSBvcHRpb25zLm11bHRpc3RyZWFtXG4gIHZhciBpbnRlcm9wID0gbmV3IHNkcFRyYW5zbGF0b3IuSW50ZXJvcCgpXG4gIHZhciBjYW5kaWRhdGVzUXVldWVPdXQgPSBbXVxuICB2YXIgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGhpcywge1xuICAgICdwZWVyQ29ubmVjdGlvbic6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcGNcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2lkJzoge1xuICAgICAgdmFsdWU6IG9wdGlvbnMuaWQgfHwgZ3VpZCxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZVxuICAgIH0sXG5cbiAgICAncmVtb3RlVmlkZW8nOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHJlbW90ZVZpZGVvXG4gICAgICB9XG4gICAgfSxcblxuICAgICdsb2NhbFZpZGVvJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBsb2NhbFZpZGVvXG4gICAgICB9XG4gICAgfSxcblxuICAgIC8qJ2RhdGFDaGFubmVsJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkYXRhQ2hhbm5lbFxuICAgICAgfVxuICAgIH0sKi9cblxuICAgIC8qKlxuICAgICAqIEBtZW1iZXIgeyhleHRlcm5hbDpJbWFnZURhdGF8dW5kZWZpbmVkKX0gY3VycmVudEZyYW1lXG4gICAgICovXG4gICAgJ2N1cnJlbnRGcmFtZSc6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBbVG9Eb10gRmluZCBzb2x1dGlvbiB3aGVuIHdlIGhhdmUgYSByZW1vdGUgc3RyZWFtIGJ1dCB3ZSBkaWRuJ3Qgc2V0XG4gICAgICAgIC8vIGEgcmVtb3RlVmlkZW8gdGFnXG4gICAgICAgIGlmICghcmVtb3RlVmlkZW8pIHJldHVybjtcblxuICAgICAgICBpZiAocmVtb3RlVmlkZW8ucmVhZHlTdGF0ZSA8IHJlbW90ZVZpZGVvLkhBVkVfQ1VSUkVOVF9EQVRBKVxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gdmlkZW8gc3RyZWFtIGRhdGEgYXZhaWxhYmxlJylcblxuICAgICAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcbiAgICAgICAgY2FudmFzLndpZHRoID0gcmVtb3RlVmlkZW8udmlkZW9XaWR0aFxuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gcmVtb3RlVmlkZW8udmlkZW9IZWlnaHRcblxuICAgICAgICBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKS5kcmF3SW1hZ2UocmVtb3RlVmlkZW8sIDAsIDApXG5cbiAgICAgICAgcmV0dXJuIGNhbnZhc1xuICAgICAgfVxuICAgIH1cbiAgfSlcblxuICAvLyBJbml0IFBlZXJDb25uZWN0aW9uXG4gIGlmICghcGMpIHtcbiAgICBwYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbihjb25maWd1cmF0aW9uKTtcbiAgICAvKmlmICh1c2VEYXRhQ2hhbm5lbHMgJiYgIWRhdGFDaGFubmVsKSB7XG4gICAgICB2YXIgZGNJZCA9ICdXZWJSdGNQZWVyLScgKyBzZWxmLmlkXG4gICAgICB2YXIgZGNPcHRpb25zID0gdW5kZWZpbmVkXG4gICAgICBpZiAoZGF0YUNoYW5uZWxDb25maWcpIHtcbiAgICAgICAgZGNJZCA9IGRhdGFDaGFubmVsQ29uZmlnLmlkIHx8IGRjSWRcbiAgICAgICAgZGNPcHRpb25zID0gZGF0YUNoYW5uZWxDb25maWcub3B0aW9uc1xuICAgICAgfVxuICAgICAgZGF0YUNoYW5uZWwgPSBwYy5jcmVhdGVEYXRhQ2hhbm5lbChkY0lkLCBkY09wdGlvbnMpO1xuICAgICAgaWYgKGRhdGFDaGFubmVsQ29uZmlnKSB7XG4gICAgICAgIGRhdGFDaGFubmVsLm9ub3BlbiA9IGRhdGFDaGFubmVsQ29uZmlnLm9ub3BlbjtcbiAgICAgICAgZGF0YUNoYW5uZWwub25jbG9zZSA9IGRhdGFDaGFubmVsQ29uZmlnLm9uY2xvc2U7XG4gICAgICAgIGRhdGFDaGFubmVsLm9ubWVzc2FnZSA9IGRhdGFDaGFubmVsQ29uZmlnLm9ubWVzc2FnZTtcbiAgICAgICAgZGF0YUNoYW5uZWwub25idWZmZXJlZGFtb3VudGxvdyA9IGRhdGFDaGFubmVsQ29uZmlnLm9uYnVmZmVyZWRhbW91bnRsb3c7XG4gICAgICAgIGRhdGFDaGFubmVsLm9uZXJyb3IgPSBkYXRhQ2hhbm5lbENvbmZpZy5vbmVycm9yIHx8IG5vb3A7XG4gICAgICB9XG4gICAgfSovXG4gIH1cblxuICBwYy5hZGRFdmVudExpc3RlbmVyKCdpY2VjYW5kaWRhdGUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgY2FuZGlkYXRlID0gZXZlbnQuY2FuZGlkYXRlXG5cbiAgICBpZiAoRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQoc2VsZiwgJ2ljZWNhbmRpZGF0ZScpIHx8XG4gICAgICBFdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudChcbiAgICAgICAgc2VsZiwgJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSkge1xuICAgICAgaWYgKGNhbmRpZGF0ZSkge1xuICAgICAgICB2YXIgY2FuZFxuXG4gICAgICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgICAgIGNhbmQgPSBpbnRlcm9wLmNhbmRpZGF0ZVRvVW5pZmllZFBsYW4oY2FuZGlkYXRlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbmQgPSBjYW5kaWRhdGVcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYuZW1pdCgnaWNlY2FuZGlkYXRlJywgY2FuZClcbiAgICAgICAgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG4gICAgICB9IGVsc2UgaWYgKCFjYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgICAgIHNlbGYuZW1pdCgnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpXG4gICAgICAgIGNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgLy8gTm90IGxpc3RlbmluZyB0byAnaWNlY2FuZGlkYXRlJyBvciAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScgZXZlbnRzLCBxdWV1ZVxuICAgICAgLy8gdGhlIGNhbmRpZGF0ZSB1bnRpbCBvbmUgb2YgdGhlbSBpcyBsaXN0ZW5lZFxuICAgICAgY2FuZGlkYXRlc1F1ZXVlT3V0LnB1c2goY2FuZGlkYXRlKVxuXG4gICAgICBpZiAoIWNhbmRpZGF0ZSkgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWVcbiAgICB9XG4gIH0pXG5cbiAgcGMub25hZGRzdHJlYW0gPSBvcHRpb25zLm9uYWRkc3RyZWFtXG4gIHBjLm9ubmVnb3RpYXRpb25uZWVkZWQgPSBvcHRpb25zLm9ubmVnb3RpYXRpb25uZWVkZWRcbiAgdGhpcy5vbignbmV3TGlzdGVuZXInLCBmdW5jdGlvbiAoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgaWYgKGV2ZW50ID09PSAnaWNlY2FuZGlkYXRlJyB8fCBldmVudCA9PT0gJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlT3V0Lmxlbmd0aCkge1xuICAgICAgICB2YXIgY2FuZGlkYXRlID0gY2FuZGlkYXRlc1F1ZXVlT3V0LnNoaWZ0KClcblxuICAgICAgICBpZiAoIWNhbmRpZGF0ZSA9PT0gKGV2ZW50ID09PSAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpKSB7XG4gICAgICAgICAgbGlzdGVuZXIoY2FuZGlkYXRlKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4gIHZhciBhZGRJY2VDYW5kaWRhdGUgPSBidWZmZXJpemVDYW5kaWRhdGVzKHBjKVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYW4gSUNFIGNhbmRpZGF0ZSBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUuYWRkSWNlQ2FuZGlkYXRlXG4gICAqXG4gICAqIEBwYXJhbSBpY2VDYW5kaWRhdGUgLSBMaXRlcmFsIG9iamVjdCB3aXRoIHRoZSBJQ0UgY2FuZGlkYXRlIGRlc2NyaXB0aW9uXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtIENhbGxlZCB3aGVuIHRoZSBJQ0UgY2FuZGlkYXRlIGhhcyBiZWVuIGFkZGVkLlxuICAgKi9cbiAgdGhpcy5hZGRJY2VDYW5kaWRhdGUgPSBmdW5jdGlvbiAoaWNlQ2FuZGlkYXRlLCBjYWxsYmFjaykge1xuICAgIHZhciBjYW5kaWRhdGVcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgY2FuZGlkYXRlID0gaW50ZXJvcC5jYW5kaWRhdGVUb1BsYW5CKGljZUNhbmRpZGF0ZSlcbiAgICB9IGVsc2Uge1xuICAgICAgY2FuZGlkYXRlID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpXG4gICAgfVxuXG4gICAgbG9nZ2VyLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSlcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSwgY2FsbGJhY2spXG4gIH1cblxuICB0aGlzLmdlbmVyYXRlT2ZmZXIgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrLmJpbmQodGhpcylcblxuICAgIHZhciBvZmZlckF1ZGlvID0gdHJ1ZVxuICAgIHZhciBvZmZlclZpZGVvID0gdHJ1ZVxuICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgIGlmIChtZWRpYUNvbnN0cmFpbnRzKSB7XG4gICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvID09PSAnYm9vbGVhbicpID9cbiAgICAgICAgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA6IHRydWVcbiAgICAgIG9mZmVyVmlkZW8gPSAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZVxuICAgIH1cblxuICAgIHZhciBicm93c2VyRGVwZW5kYW50Q29uc3RyYWludHMgPSB7XG4gICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiAobW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgIG9mZmVyVG9SZWNlaXZlVmlkZW86IChtb2RlICE9PSAnc2VuZG9ubHknICYmIG9mZmVyVmlkZW8pXG4gICAgfVxuXG4gICAgLy9GSVhNRTogY2xhcmlmeSBwb3NzaWJsZSBjb25zdHJhaW50cyBwYXNzZWQgdG8gY3JlYXRlT2ZmZXIoKVxuICAgIC8qdmFyIGNvbnN0cmFpbnRzID0gcmVjdXJzaXZlKGJyb3dzZXJEZXBlbmRhbnRDb25zdHJhaW50cyxcbiAgICAgIGNvbm5lY3Rpb25Db25zdHJhaW50cykqL1xuXG4gICAgdmFyIGNvbnN0cmFpbnRzID0gYnJvd3NlckRlcGVuZGFudENvbnN0cmFpbnRzO1xuXG4gICAgbG9nZ2VyLmRlYnVnKCdjb25zdHJhaW50czogJyArIEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSlcblxuICAgIHBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKGZ1bmN0aW9uIChvZmZlcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpXG4gICAgICBvZmZlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KG9mZmVyKVxuICAgICAgcmV0dXJuIHBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgbG9jYWxEZXNjcmlwdGlvbiA9IHBjLmxvY2FsRGVzY3JpcHRpb25cbiAgICAgIGxvZ2dlci5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApXG4gICAgICBpZiAobXVsdGlzdHJlYW0gJiYgdXNlUGxhbkIpIHtcbiAgICAgICAgbG9jYWxEZXNjcmlwdGlvbiA9IGludGVyb3AudG9VbmlmaWVkUGxhbihsb2NhbERlc2NyaXB0aW9uKVxuICAgICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpvcmlnUGxhbkItPlVuaWZpZWRQbGFuJywgZHVtcFNEUChcbiAgICAgICAgICBsb2NhbERlc2NyaXB0aW9uKSlcbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwLCBzZWxmLnByb2Nlc3NBbnN3ZXIuYmluZChcbiAgICAgICAgc2VsZikpXG4gICAgfSkuY2F0Y2goY2FsbGJhY2spXG4gIH1cblxuICB0aGlzLmdldExvY2FsU2Vzc2lvbkRlc2NyaXB0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHBjLmxvY2FsRGVzY3JpcHRpb25cbiAgfVxuXG4gIHRoaXMuZ2V0UmVtb3RlU2Vzc2lvbkRlc2NyaXB0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHBjLnJlbW90ZURlc2NyaXB0aW9uXG4gIH1cblxuICBmdW5jdGlvbiBzZXRSZW1vdGVWaWRlbygpIHtcbiAgICBpZiAocmVtb3RlVmlkZW8pIHtcbiAgICAgIHJlbW90ZVZpZGVvLnBhdXNlKClcblxuICAgICAgdmFyIHN0cmVhbSA9IHBjLmdldFJlbW90ZVN0cmVhbXMoKVswXVxuICAgICAgcmVtb3RlVmlkZW8uc3JjT2JqZWN0ID0gc3RyZWFtXG4gICAgICBsb2dnZXIuZGVidWcoJ1JlbW90ZSBzdHJlYW06Jywgc3RyZWFtKVxuXG4gICAgICByZW1vdGVWaWRlby5sb2FkKClcbiAgICB9XG4gIH1cblxuICB0aGlzLnNob3dMb2NhbFZpZGVvID0gZnVuY3Rpb24gKCkge1xuICAgIGxvY2FsVmlkZW8uc3JjT2JqZWN0ID0gdmlkZW9TdHJlYW1cbiAgICBsb2NhbFZpZGVvLm11dGVkID0gdHJ1ZVxuICB9XG5cbiAgLyp0aGlzLnNlbmQgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIGlmIChkYXRhQ2hhbm5lbCAmJiBkYXRhQ2hhbm5lbC5yZWFkeVN0YXRlID09PSAnb3BlbicpIHtcbiAgICAgIGRhdGFDaGFubmVsLnNlbmQoZGF0YSlcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICdUcnlpbmcgdG8gc2VuZCBkYXRhIG92ZXIgYSBub24tZXhpc3Rpbmcgb3IgY2xvc2VkIGRhdGEgY2hhbm5lbCcpXG4gICAgfVxuICB9Ki9cblxuICAvKipcbiAgICogQ2FsbGJhY2sgZnVuY3Rpb24gaW52b2tlZCB3aGVuIGEgU0RQIGFuc3dlciBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUucHJvY2Vzc0Fuc3dlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwQW5zd2VyIC0gRGVzY3JpcHRpb24gb2Ygc2RwQW5zd2VyXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtXG4gICAqICAgICAgICAgICAgSW52b2tlZCBhZnRlciB0aGUgU0RQIGFuc3dlciBpcyBwcm9jZXNzZWQsIG9yIHRoZXJlIGlzIGFuIGVycm9yLlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzQW5zd2VyID0gZnVuY3Rpb24gKHNkcEFuc3dlciwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG5cbiAgICB2YXIgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICB0eXBlOiAnYW5zd2VyJyxcbiAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CQW5zd2VyID0gaW50ZXJvcC50b1BsYW5CKGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnYXNud2VyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJBbnN3ZXIpKVxuICAgICAgYW5zd2VyID0gcGxhbkJBbnN3ZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJylcblxuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjaygnUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJylcbiAgICB9XG5cbiAgICBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2V0UmVtb3RlVmlkZW8oKVxuXG4gICAgICAgIGNhbGxiYWNrKClcbiAgICAgIH0sXG4gICAgICBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgb2ZmZXIgaXMgcmVjZWl2ZWQuIERldmVsb3BlcnMgYXJlXG4gICAqIGV4cGVjdGVkIHRvIGludm9rZSB0aGlzIGZ1bmN0aW9uIGluIG9yZGVyIHRvIGNvbXBsZXRlIHRoZSBTRFAgbmVnb3RpYXRpb24uXG4gICAqXG4gICAqIEBmdW5jdGlvbiBtb2R1bGU6a3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIucHJvdG90eXBlLnByb2Nlc3NPZmZlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwT2ZmZXIgLSBEZXNjcmlwdGlvbiBvZiBzZHBPZmZlclxuICAgKiBAcGFyYW0gY2FsbGJhY2sgLSBDYWxsZWQgd2hlbiB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIGhhcyBiZWVuIHNldFxuICAgKiAgc3VjY2Vzc2Z1bGx5LlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzT2ZmZXIgPSBmdW5jdGlvbiAoc2RwT2ZmZXIsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjay5iaW5kKHRoaXMpXG5cbiAgICB2YXIgb2ZmZXIgPSBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICBzZHA6IHNkcE9mZmVyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CT2ZmZXIgPSBpbnRlcm9wLnRvUGxhbkIob2ZmZXIpXG4gICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJPZmZlcikpXG4gICAgICBvZmZlciA9IHBsYW5CT2ZmZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKVxuXG4gICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKVxuICAgIH1cblxuICAgIHBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBzZXRSZW1vdGVWaWRlbygpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcGMuY3JlYXRlQW5zd2VyKClcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChhbnN3ZXIpIHtcbiAgICAgIGFuc3dlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJylcbiAgICAgIHJldHVybiBwYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcilcbiAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBsb2NhbERlc2NyaXB0aW9uID0gcGMubG9jYWxEZXNjcmlwdGlvblxuICAgICAgaWYgKG11bHRpc3RyZWFtICYmIHVzZVBsYW5CKSB7XG4gICAgICAgIGxvY2FsRGVzY3JpcHRpb24gPSBpbnRlcm9wLnRvVW5pZmllZFBsYW4obG9jYWxEZXNjcmlwdGlvbilcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdhbnN3ZXI6Om9yaWdQbGFuQi0+VW5pZmllZFBsYW4nLCBkdW1wU0RQKFxuICAgICAgICAgIGxvY2FsRGVzY3JpcHRpb24pKVxuICAgICAgfVxuICAgICAgbG9nZ2VyLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcClcbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwKVxuICAgIH0pLmNhdGNoKGNhbGxiYWNrKVxuICB9XG5cbiAgZnVuY3Rpb24gbWFuZ2xlU2RwVG9BZGRTaW11bGNhc3QoYW5zd2VyKSB7XG4gICAgaWYgKHNpbXVsY2FzdCkge1xuICAgICAgaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnQWRkaW5nIG11bHRpY2FzdCBpbmZvJylcbiAgICAgICAgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgJ3R5cGUnOiBhbnN3ZXIudHlwZSxcbiAgICAgICAgICAnc2RwJzogcmVtb3ZlRklERnJvbU9mZmVyKGFuc3dlci5zZHApICsgZ2V0U2ltdWxjYXN0SW5mbyhcbiAgICAgICAgICAgIHZpZGVvU3RyZWFtKVxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1NpbXVsY2FzdCBpcyBvbmx5IGF2YWlsYWJsZSBpbiBDaHJvbWUgYnJvd3Nlci4nKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhbnN3ZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdCB0YWtpbmcgaW50byBhY2NvdW50IHRoZVxuICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICogY2FsbGJhY2sgaXMgZXhwZWN0ZWQgdG8gc2VuZCB0aGUgU0RQIG9mZmVyLCBpbiBvcmRlciB0byBvYnRhaW4gYW4gU0RQXG4gICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICovXG4gIGZ1bmN0aW9uIHN0YXJ0KCkge1xuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIGNhbGxiYWNrKFxuICAgICAgICAnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnXG4gICAgICApXG4gICAgfVxuXG4gICAgaWYgKHZpZGVvU3RyZWFtICYmIGxvY2FsVmlkZW8pIHtcbiAgICAgIHNlbGYuc2hvd0xvY2FsVmlkZW8oKVxuICAgIH1cblxuICAgIGlmICh2aWRlb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKHZpZGVvU3RyZWFtKVxuICAgIH1cblxuICAgIGlmIChhdWRpb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKGF1ZGlvU3RyZWFtKVxuICAgIH1cblxuICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgdmFyIGJyb3dzZXIgPSBwYXJzZXIuZ2V0QnJvd3NlcigpXG4gICAgaWYgKG1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgIChicm93c2VyLm5hbWUgPT09ICdDaHJvbWUnIHx8IGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9taXVtJykgJiZcbiAgICAgIGJyb3dzZXIubWFqb3IgPT09IDM5KSB7XG4gICAgICBtb2RlID0gJ3NlbmRyZWN2J1xuICAgIH1cblxuICAgIGNhbGxiYWNrKClcbiAgfVxuXG4gIGlmIChtb2RlICE9PSAncmVjdm9ubHknICYmICF2aWRlb1N0cmVhbSAmJiAhYXVkaW9TdHJlYW0pIHtcbiAgICBmdW5jdGlvbiBnZXRNZWRpYShjb25zdHJhaW50cykge1xuICAgICAgaWYgKGNvbnN0cmFpbnRzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3RyYWludHMgPSBNRURJQV9DT05TVFJBSU5UU1xuICAgICAgfVxuXG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cykudGhlbihmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4gICAgICAgIHN0YXJ0KClcbiAgICAgIH0pLmNhdGNoKGNhbGxiYWNrKTtcbiAgICB9XG4gICAgaWYgKHNlbmRTb3VyY2UgPT09ICd3ZWJjYW0nKSB7XG4gICAgICBnZXRNZWRpYShtZWRpYUNvbnN0cmFpbnRzKVxuICAgIH0gZWxzZSB7XG4gICAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhzZW5kU291cmNlLCBmdW5jdGlvbiAoZXJyb3IsIGNvbnN0cmFpbnRzXykge1xuICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycm9yKVxuXG4gICAgICAgIGNvbnN0cmFpbnRzID0gW21lZGlhQ29uc3RyYWludHNdXG4gICAgICAgIGNvbnN0cmFpbnRzLnVuc2hpZnQoY29uc3RyYWludHNfKVxuICAgICAgICBnZXRNZWRpYShyZWN1cnNpdmUuYXBwbHkodW5kZWZpbmVkLCBjb25zdHJhaW50cykpXG4gICAgICB9LCBndWlkKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBzZXRUaW1lb3V0KHN0YXJ0LCAwKVxuICB9XG5cbiAgdGhpcy5vbignX2Rpc3Bvc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGxvY2FsVmlkZW8pIHtcbiAgICAgIGxvY2FsVmlkZW8ucGF1c2UoKVxuICAgICAgbG9jYWxWaWRlby5zcmNPYmplY3QgPSBudWxsXG4gICAgICBsb2NhbFZpZGVvLmxvYWQoKVxuICAgICAgLy9Vbm11dGUgbG9jYWwgdmlkZW8gaW4gY2FzZSB0aGUgdmlkZW8gdGFnIGlzIGxhdGVyIHVzZWQgZm9yIHJlbW90ZSB2aWRlb1xuICAgICAgbG9jYWxWaWRlby5tdXRlZCA9IGZhbHNlXG4gICAgfVxuICAgIGlmIChyZW1vdGVWaWRlbykge1xuICAgICAgcmVtb3RlVmlkZW8ucGF1c2UoKVxuICAgICAgcmVtb3RlVmlkZW8uc3JjT2JqZWN0ID0gbnVsbFxuICAgICAgcmVtb3RlVmlkZW8ubG9hZCgpXG4gICAgfVxuICAgIHNlbGYucmVtb3ZlQWxsTGlzdGVuZXJzKClcblxuICAgIGlmICh3aW5kb3cuY2FuY2VsQ2hvb3NlRGVza3RvcE1lZGlhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHdpbmRvdy5jYW5jZWxDaG9vc2VEZXNrdG9wTWVkaWEoZ3VpZClcbiAgICB9XG4gIH0pXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyLCBFdmVudEVtaXR0ZXIpXG5cbmZ1bmN0aW9uIGNyZWF0ZUVuYWJsZURlc2NyaXB0b3IodHlwZSkge1xuICB2YXIgbWV0aG9kID0gJ2dldCcgKyB0eXBlICsgJ1RyYWNrcydcblxuICByZXR1cm4ge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBbVG9Eb10gU2hvdWxkIHJldHVybiB1bmRlZmluZWQgaWYgbm90IGFsbCB0cmFja3MgaGF2ZSB0aGUgc2FtZSB2YWx1ZT9cblxuICAgICAgaWYgKCF0aGlzLnBlZXJDb25uZWN0aW9uKSByZXR1cm5cblxuICAgICAgdmFyIHN0cmVhbXMgPSB0aGlzLnBlZXJDb25uZWN0aW9uLmdldExvY2FsU3RyZWFtcygpXG4gICAgICBpZiAoIXN0cmVhbXMubGVuZ3RoKSByZXR1cm5cblxuICAgICAgZm9yICh2YXIgaSA9IDAsIHN0cmVhbTsgc3RyZWFtID0gc3RyZWFtc1tpXTsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFja3MgPSBzdHJlYW1bbWV0aG9kXSgpXG4gICAgICAgIGZvciAodmFyIGogPSAwLCB0cmFjazsgdHJhY2sgPSB0cmFja3Nbal07IGorKylcbiAgICAgICAgICBpZiAoIXRyYWNrLmVuYWJsZWQpIHJldHVybiBmYWxzZVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgIGZ1bmN0aW9uIHRyYWNrU2V0RW5hYmxlKHRyYWNrKSB7XG4gICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZVxuICAgICAgfVxuXG4gICAgICB0aGlzLnBlZXJDb25uZWN0aW9uLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goZnVuY3Rpb24gKHN0cmVhbSkge1xuICAgICAgICBzdHJlYW1bbWV0aG9kXSgpLmZvckVhY2godHJhY2tTZXRFbmFibGUpXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydGllcyhXZWJSdGNQZWVyLnByb3RvdHlwZSwge1xuICAnZW5hYmxlZCc6IHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuYXVkaW9FbmFibGVkICYmIHRoaXMudmlkZW9FbmFibGVkXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgdGhpcy5hdWRpb0VuYWJsZWQgPSB0aGlzLnZpZGVvRW5hYmxlZCA9IHZhbHVlXG4gICAgfVxuICB9LFxuICAnYXVkaW9FbmFibGVkJzogY3JlYXRlRW5hYmxlRGVzY3JpcHRvcignQXVkaW8nKSxcbiAgJ3ZpZGVvRW5hYmxlZCc6IGNyZWF0ZUVuYWJsZURlc2NyaXB0b3IoJ1ZpZGVvJylcbn0pXG5cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmdldExvY2FsU3RyZWFtID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gIGlmICh0aGlzLnBlZXJDb25uZWN0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMucGVlckNvbm5lY3Rpb24uZ2V0TG9jYWxTdHJlYW1zKClbaW5kZXggfHwgMF1cbiAgfVxufVxuXG5XZWJSdGNQZWVyLnByb3RvdHlwZS5nZXRSZW1vdGVTdHJlYW0gPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgaWYgKHRoaXMucGVlckNvbm5lY3Rpb24pIHtcbiAgICByZXR1cm4gdGhpcy5wZWVyQ29ubmVjdGlvbi5nZXRSZW1vdGVTdHJlYW1zKClbaW5kZXggfHwgMF1cbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUaGlzIG1ldGhvZCBmcmVlcyB0aGUgcmVzb3VyY2VzIHVzZWQgYnkgV2ViUnRjUGVlci5cbiAqXG4gKiBAZnVuY3Rpb24gbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyLnByb3RvdHlwZS5kaXNwb3NlXG4gKi9cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmRpc3Bvc2UgPSBmdW5jdGlvbiAoKSB7XG4gIGxvZ2dlci5kZWJ1ZygnRGlzcG9zaW5nIFdlYlJ0Y1BlZXInKVxuXG4gIHZhciBwYyA9IHRoaXMucGVlckNvbm5lY3Rpb25cbiAgLy92YXIgZGMgPSB0aGlzLmRhdGFDaGFubmVsXG4gIHRyeSB7XG4gICAgLyppZiAoZGMpIHtcbiAgICAgIGlmIChkYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHJldHVyblxuXG4gICAgICBkYy5jbG9zZSgpXG4gICAgfSovXG5cbiAgICBpZiAocGMpIHtcbiAgICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHJldHVyblxuXG4gICAgICBwYy5nZXRMb2NhbFN0cmVhbXMoKS5mb3JFYWNoKHN0cmVhbVN0b3ApXG5cbiAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAvLyBpZih2aWRlb1N0cmVhbSkgcGMucmVtb3ZlU3RyZWFtKHZpZGVvU3RyZWFtKTtcbiAgICAgIC8vIGlmKGF1ZGlvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0oYXVkaW9TdHJlYW0pO1xuXG4gICAgICBwYy5jbG9zZSgpXG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIud2FybignRXhjZXB0aW9uIGRpc3Bvc2luZyB3ZWJydGMgcGVlciAnICsgZXJyKVxuICB9XG5cbiAgdGhpcy5lbWl0KCdfZGlzcG9zZScpXG59XG5cbi8vXG4vLyBTcGVjaWFsaXplZCBjaGlsZCBjbGFzc2VzXG4vL1xuXG5mdW5jdGlvbiBXZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgY2FsbGJhY2spIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFdlYlJ0Y1BlZXJSZWN2b25seSkpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zLCBjYWxsYmFjaylcbiAgfVxuXG4gIFdlYlJ0Y1BlZXJSZWN2b25seS5zdXBlcl8uY2FsbCh0aGlzLCAncmVjdm9ubHknLCBvcHRpb25zLCBjYWxsYmFjaylcbn1cbmluaGVyaXRzKFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlcilcblxuZnVuY3Rpb24gV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBXZWJSdGNQZWVyU2VuZG9ubHkpKSB7XG4gICAgcmV0dXJuIG5ldyBXZWJSdGNQZWVyU2VuZG9ubHkob3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyU2VuZG9ubHkuc3VwZXJfLmNhbGwodGhpcywgJ3NlbmRvbmx5Jywgb3B0aW9ucywgY2FsbGJhY2spXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXIpXG5cbmZ1bmN0aW9uIFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlclNlbmRyZWN2KSkge1xuICAgIHJldHVybiBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGNhbGxiYWNrKVxuICB9XG5cbiAgV2ViUnRjUGVlclNlbmRyZWN2LnN1cGVyXy5jYWxsKHRoaXMsICdzZW5kcmVjdicsIG9wdGlvbnMsIGNhbGxiYWNrKVxufVxuaW5oZXJpdHMoV2ViUnRjUGVlclNlbmRyZWN2LCBXZWJSdGNQZWVyKVxuXG5mdW5jdGlvbiBoYXJrVXRpbHMoc3RyZWFtLCBvcHRpb25zKSB7XG4gIHJldHVybiBoYXJrKHN0cmVhbSwgb3B0aW9ucyk7XG59XG5cbmV4cG9ydHMuYnVmZmVyaXplQ2FuZGlkYXRlcyA9IGJ1ZmZlcml6ZUNhbmRpZGF0ZXNcblxuZXhwb3J0cy5XZWJSdGNQZWVyUmVjdm9ubHkgPSBXZWJSdGNQZWVyUmVjdm9ubHlcbmV4cG9ydHMuV2ViUnRjUGVlclNlbmRvbmx5ID0gV2ViUnRjUGVlclNlbmRvbmx5XG5leHBvcnRzLldlYlJ0Y1BlZXJTZW5kcmVjdiA9IFdlYlJ0Y1BlZXJTZW5kcmVjdlxuZXhwb3J0cy5oYXJrID0gaGFya1V0aWxzXG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBUaGlzIG1vZHVsZSBjb250YWlucyBhIHNldCBvZiByZXVzYWJsZSBjb21wb25lbnRzIHRoYXQgaGF2ZSBiZWVuIGZvdW5kIHVzZWZ1bFxuICogZHVyaW5nIHRoZSBkZXZlbG9wbWVudCBvZiB0aGUgV2ViUlRDIGFwcGxpY2F0aW9ucyB3aXRoIEt1cmVudG8uXG4gKiBcbiAqIEBtb2R1bGUga3VyZW50b1V0aWxzXG4gKiBcbiAqIEBjb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICogQGxpY2Vuc2UgQUx2MlxuICovXG5cbnZhciBXZWJSdGNQZWVyID0gcmVxdWlyZSgnLi9XZWJSdGNQZWVyJyk7XG5cbmV4cG9ydHMuV2ViUnRjUGVlciA9IFdlYlJ0Y1BlZXI7XG4iLCIvLyBMYXN0IHRpbWUgdXBkYXRlZCBvbiBEZWNlbWJlciAxMywgMjAxN1xuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYoc291cmNlSWQgPT0gJ2ZpcmVmb3gnKSB7XG4gICAgICAgIG5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzLCBvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2UgbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMsIG9uU3VjY2Vzcywgb25GYWlsdXJlKTtcbn0pO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhlcnJvciwgc291cmNlSWQpIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmIChzb3VyY2VJZCkge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMudmlkZW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2NyZWVuX2NvbnN0cmFpbnRzO1xufVxuXG52YXIgaWZyYW1lO1xuXG5mdW5jdGlvbiBwb3N0R2V0U291cmNlSWRNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldFNvdXJjZUlkTWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGNhcHR1cmVTb3VyY2VJZDogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmZ1bmN0aW9uIGxvYWRJRnJhbWUobG9hZENhbGxiYWNrKSB7XG4gICAgaWYgKGlmcmFtZSkge1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO1xuICAgIGlmcmFtZS5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmcmFtZS5pc0xvYWRlZCA9IHRydWU7XG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgIH07XG4gICAgaWZyYW1lLnNyYyA9ICdodHRwczovL3d3dy53ZWJydGMtZXhwZXJpbWVudC5jb20vZ2V0U291cmNlSWQvJztcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbn07XG5cbmZ1bmN0aW9uIHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzOiB0cnVlXG4gICAgfSwgJyonKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5JZCA9IGdldFNjcmVlbklkOyIsIi8vIGdsb2JhbCB2YXJpYWJsZXNcbnZhciBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xudmFyIHNjcmVlbkNhbGxiYWNrO1xudmFyIGlzRmlyZWZveCA9IHR5cGVvZiB3aW5kb3cuSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnO1xudmFyIGlzT3BlcmEgPSAhIXdpbmRvdy5vcGVyYSB8fCBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJyBPUFIvJykgPj0gMDtcbnZhciBpc0Nocm9tZSA9ICEhd2luZG93LmNocm9tZSAmJiAhaXNPcGVyYTtcblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBpZiAoZXZlbnQub3JpZ2luICE9IHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBvbk1lc3NhZ2VDYWxsYmFjayhldmVudC5kYXRhKTtcbn0pO1xuXG4vLyBhbmQgdGhlIGZ1bmN0aW9uIHRoYXQgaGFuZGxlcyByZWNlaXZlZCBtZXNzYWdlc1xuZnVuY3Rpb24gb25NZXNzYWdlQ2FsbGJhY2soZGF0YSkge1xuICAgIC8vIFwiY2FuY2VsXCIgYnV0dG9uIGlzIGNsaWNrZWRcbiAgICBpZiAoZGF0YSA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJykge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InO1xuICAgICAgICBpZiAoc2NyZWVuQ2FsbGJhY2spXG4gICAgICAgICAgICByZXR1cm4gc2NyZWVuQ2FsbGJhY2soJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gbm90aWZpZWQgaGlzIHByZXNlbmNlXG4gICAgaWYgKGRhdGEgPT0gJ3J0Y211bHRpY29ubmVjdGlvbi1leHRlbnNpb24tbG9hZGVkJykge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdkZXNrdG9wJztcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIHNoYXJlZCB0ZW1wIHNvdXJjZUlkXG4gICAgaWYgKGRhdGEuc291cmNlSWQgJiYgc2NyZWVuQ2FsbGJhY2spIHtcbiAgICAgICAgc2NyZWVuQ2FsbGJhY2soc291cmNlSWQgPSBkYXRhLnNvdXJjZUlkKTtcbiAgICB9XG59XG5cbi8vIHRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGNoZWNrIGlmIGNocm9tZSBleHRlbnNpb24gaXMgaW5zdGFsbGVkICYgZW5hYmxlZC5cbmZ1bmN0aW9uIGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlKGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGZhbHNlKTtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKVxuICAgICAgICByZXR1cm4gY2FsbGJhY2soJ2lzRmlyZWZveCcpO1xuICAgIC8vIGFzayBleHRlbnNpb24gaWYgaXQgaXMgYXZhaWxhYmxlXG4gICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICBjYWxsYmFjaygndW5hdmFpbGFibGUnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBjYWxsYmFjaygnYXZhaWxhYmxlJyk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnYWpoaWZkZGlta2FwZ2NpZmdjb2RtbWZkbGtuYWhmZmsnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhleHRlbnNpb25pZCA9PSBleHRlbnNpb25pZCA/ICdpbnN0YWxsZWQtZW5hYmxlZCcgOiAnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIH0sIDIwMDApO1xuICAgIH07XG4gICAgaW1hZ2Uub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2FsbGJhY2soJ25vdC1pbnN0YWxsZWQnKTtcbiAgICB9O1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaykge1xuICAgIHNvdXJjZUlkID0gJyc7XG4gICAgdmFyIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyA9IHtcbiAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICBtZWRpYVNvdXJjZTogJ3dpbmRvdydcbiAgICB9O1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMpO1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IGRlZmluZXMgZ2V0VXNlck1lZGlhIGNvbnN0cmFpbnRzXG4gICAgLy8gdGhhdCB3aWxsIGJlIHVzZWQgdG8gY2FwdHVyZSBjb250ZW50IG9mIHNjcmVlblxuICAgIHZhciBzY3JlZW5fY29uc3RyYWludHMgPSB7XG4gICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGNocm9tZU1lZGlhU291cmNlLFxuICAgICAgICAgICAgbWF4V2lkdGg6IHNjcmVlbi53aWR0aCA+IDE5MjAgPyBzY3JlZW4ud2lkdGggOiAxOTIwLFxuICAgICAgICAgICAgbWF4SGVpZ2h0OiBzY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHNjcmVlbi5oZWlnaHQgOiAxMDgwXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbmFsOiBbXVxuICAgIH07XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgdmVyaWZpZXMgY2hyb21lIGV4dGVuc2lvbiBhdmFpbGFiaWxpdHlcbiAgICAvLyBpZiBpbnN0YWxsZWQgYW5kIGF2YWlsYWJsZSB0aGVuIGl0IHdpbGwgaW52b2tlIGV4dGVuc2lvbiBBUElcbiAgICAvLyBvdGhlcndpc2UgaXQgd2lsbCBmYWxsYmFjayB0byBjb21tYW5kLWxpbmUgYmFzZWQgc2NyZWVuIGNhcHR1cmluZyBBUElcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnICYmICFzb3VyY2VJZCkge1xuICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG4gICAgLy8gbm93IGludm9raW5nIG5hdGl2ZSBnZXRVc2VyTWVkaWEgQVBJXG4gICAgY2FsbGJhY2sobnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50cyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzO1xuZXhwb3J0cy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSA9IGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG5leHBvcnRzLmdldFNvdXJjZUlkID0gZ2V0U291cmNlSWQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vLyB0c2xpbnQ6ZGlzYWJsZTpuby1zdHJpbmctbGl0ZXJhbFxuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0ICogYXMgYWRhcHRlciBmcm9tICd3ZWJydGMtYWRhcHRlcic7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5leHBvcnQgY2xhc3MgV2ViUnRjU3RhdHMge1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0VuYWJsZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzSW50ZXJ2YWxJZDogTm9kZUpTLlRpbWVyO1xuICAgIHByaXZhdGUgc3RhdHNJbnRlcnZhbCA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBpbmJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvdXRib3VuZDoge1xuICAgICAgICAgICAgYXVkaW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogMCxcbiAgICAgICAgICAgICAgICBuYWNrQ291bnQ6IDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7IH1cblxuICAgIHB1YmxpYyBpc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2VsYXN0ZXN0LWluc3RydW1lbnRhdGlvbicpO1xuXG4gICAgICAgIGlmIChlbGFzdGVzdEluc3RydW1lbnRhdGlvbikge1xuICAgICAgICAgICAgLy8gRWxhc1Rlc3QgaW5zdHJ1bWVudGF0aW9uIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnN0cnVtZW50YXRpb24gPSBKU09OLnBhcnNlKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHNJbnRlcnZhbCA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaW50ZXJ2YWw7ICAvLyBJbnRlcnZhbCBpbiBzZWNvbmRzXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignbG9jYWxTdG9yYWdlIGl0ZW06ICcgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1dlYlJ0YyBzdGF0cyBub3QgZW5hYmxlZCcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wV2ViUnRjU3RhdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHNlbmRQb3N0ID0gKGpzb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGh0dHA6IFhNTEh0dHBSZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICBjb25zdCB1cmw6IHN0cmluZyA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaHR0cEVuZHBvaW50O1xuICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgdXJsLCB0cnVlKTtcblxuICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKCdDb250ZW50LXR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuXG4gICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHsgLy8gQ2FsbCBhIGZ1bmN0aW9uIHdoZW4gdGhlIHN0YXRlIGNoYW5nZXMuXG4gICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCAmJiBodHRwLnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdXZWJSdGMgc3RhdHMgc3VjY2Vzc2Z1bGx5IHNlbnQgdG8gJyArIHVybCArICcgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaHR0cC5zZW5kKGpzb24pO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGYgPSAoc3RhdHMpID0+IHtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBzdGF0cy5mb3JFYWNoKChzdGF0KSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGpzb24gPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoKHN0YXQudHlwZSA9PT0gJ2luYm91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IG91dGJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5uYWNrQ291bnQgIT09IG51bGwgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5yZW1vdGVJZC5zdGFydHNXaXRoKCdpbmJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgaml0ID0gc3RhdC5qaXR0ZXIgKiAxMDAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IChzdGF0LmJ5dGVzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogaml0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6ICdtcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snbmFja0NvdW50J10gPSAoc3RhdC5uYWNrQ291bnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ25hY2tDb3VudCddID0gJ3BhY2tldHMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQubmFja0NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCA9IHN0YXQucGFja2V0c1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKHN0YXQudHlwZSA9PT0gJ291dGJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBpbmJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ291dGJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX291dGJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IChzdGF0LnBhY2tldHNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQgPSBzdGF0LmZyYW1lc0VuY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQgPSBzdGF0LnBhY2tldHNTZW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhzdGF0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogc3RhdC5nb29nSml0dGVyQnVmZmVyTXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lmdvb2dOYWNrc1NlbnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lmdvb2dOYWNrc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCdieXRlc1NlbnQnIGluIHN0YXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdXRib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5nZXRTdGF0c0Fnbm9zdGljKHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCksIGYsIChlcnJvcikgPT4geyBjb25zb2xlLmxvZyhlcnJvcik7IH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2goKHJlcG9ydCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RhbmRhcmRTdGF0cyA9IHtcbiAgICAgICAgICAgICAgICBpZDogcmVwb3J0LmlkLFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogcmVwb3J0LnRpbWVzdGFtcCxcbiAgICAgICAgICAgICAgICB0eXBlOiByZXBvcnQudHlwZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcG9ydC5uYW1lcygpLmZvckVhY2goKG5hbWUpID0+IHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFN0YXRzW25hbWVdID0gcmVwb3J0LnN0YXQobmFtZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHN0YW5kYXJkUmVwb3J0W3N0YW5kYXJkU3RhdHMuaWRdID0gc3RhbmRhcmRTdGF0cztcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHN0YW5kYXJkUmVwb3J0O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0U3RhdHNBZ25vc3RpYyhwYywgc3VjY2Vzc0NiLCBmYWlsdXJlQ2IpIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIGdldFN0YXRzIHRha2VzIGFyZ3MgaW4gZGlmZmVyZW50IG9yZGVyIGluIENocm9tZSBhbmQgRmlyZWZveFxuICAgICAgICAgICAgcmV0dXJuIHBjLmdldFN0YXRzKG51bGwsIChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcG9ydCA9IHRoaXMuc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYihyZXBvcnQpO1xuICAgICAgICAgICAgfSwgZmFpbHVyZUNiKTtcbiAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIEluIENocm9tZSwgdGhlIGZpcnN0IHR3byBhcmd1bWVudHMgYXJlIHJldmVyc2VkXG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBudWxsLCBmYWlsdXJlQ2IpO1xuICAgICAgICB9XG4gICAgfVxuXG59Il19 diff --git a/openvidu-hello-world/web/openvidu-browser-2.2.0.js b/openvidu-hello-world/web/openvidu-browser-2.2.0.js new file mode 100644 index 00000000..e57248f3 --- /dev/null +++ b/openvidu-hello-world/web/openvidu-browser-2.2.0.js @@ -0,0 +1,7371 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Unhandled "error" event. (' + er + ')'); + err.context = er; + throw err; + } + return false; + } + + handler = events[type]; + + if (!handler) + return false; + + var isFn = typeof handler === 'function'; + len = arguments.length; + switch (len) { + // fast cases + case 1: + emitNone(handler, isFn, this); + break; + case 2: + emitOne(handler, isFn, this, arguments[1]); + break; + case 3: + emitTwo(handler, isFn, this, arguments[1], arguments[2]); + break; + case 4: + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + emitMany(handler, isFn, this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = target._events; + if (!events) { + events = target._events = objectCreate(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (!existing) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + } else { + // If we've already got an array, just append. + if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + } + + // Check for listener leak + if (!existing.warned) { + m = $getMaxListeners(target); + if (m && m > 0 && existing.length > m) { + existing.warned = true; + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' "' + String(type) + '" listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit.'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + if (typeof console === 'object' && console.warn) { + console.warn('%s: %s', w.name, w.message); + } + } + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + switch (arguments.length) { + case 0: + return this.listener.call(this.target); + case 1: + return this.listener.call(this.target, arguments[0]); + case 2: + return this.listener.call(this.target, arguments[0], arguments[1]); + case 3: + return this.listener.call(this.target, arguments[0], arguments[1], + arguments[2]); + default: + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) + args[i] = arguments[i]; + this.listener.apply(this.target, args); + } + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = bind.call(onceWrapper, state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = this._events; + if (!events) + return this; + + list = events[type]; + if (!list) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else + spliceOne(list, position); + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (!events) + return this; + + // not listening for removeListener, no need to emit + if (!events.removeListener) { + if (arguments.length === 0) { + this._events = objectCreate(null); + this._eventsCount = 0; + } else if (events[type]) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = objectKeys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = objectCreate(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (!events) + return []; + + var evlistener = events[type]; + if (!evlistener) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function objectCreatePolyfill(proto) { + var F = function() {}; + F.prototype = proto; + return new F; +} +function objectKeysPolyfill(obj) { + var keys = []; + for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { + keys.push(k); + } + return k; +} +function functionBindPolyfill(context) { + var fn = this; + return function () { + return fn.apply(context, arguments); + }; +} + +},{}],2:[function(require,module,exports){ +/* jshint node: true */ +'use strict'; + +var normalice = require('normalice'); + +/** + # freeice + + The `freeice` module is a simple way of getting random STUN or TURN server + for your WebRTC application. The list of servers (just STUN at this stage) + were sourced from this [gist](https://gist.github.com/zziuni/3741933). + + ## Example Use + + The following demonstrates how you can use `freeice` with + [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): + + <<< examples/quickconnect.js + + As the `freeice` module generates ice servers in a list compliant with the + WebRTC spec you will be able to use it with raw `RTCPeerConnection` + constructors and other WebRTC libraries. + + ## Hey, don't use my STUN/TURN server! + + If for some reason your free STUN or TURN server ends up in the + list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or + [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) + that is used in this module, you can feel + free to open an issue on this repository and those servers will be removed + within 24 hours (or sooner). This is the quickest and probably the most + polite way to have something removed (and provides us some visibility + if someone opens a pull request requesting that a server is added). + + ## Please add my server! + + If you have a server that you wish to add to the list, that's awesome! I'm + sure I speak on behalf of a whole pile of WebRTC developers who say thanks. + To get it into the list, feel free to either open a pull request or if you + find that process a bit daunting then just create an issue requesting + the addition of the server (make sure you provide all the details, and if + you have a Terms of Service then including that in the PR/issue would be + awesome). + + ## I know of a free server, can I add it? + + Sure, if you do your homework and make sure it is ok to use (I'm currently + in the process of reviewing the terms of those STUN servers included from + the original list). If it's ok to go, then please see the previous entry + for how to add it. + + ## Current List of Servers + + * current as at the time of last `README.md` file generation + + ### STUN + + <<< stun.json + + ### TURN + + <<< turn.json + +**/ + +var freeice = module.exports = function(opts) { + // if a list of servers has been provided, then use it instead of defaults + var servers = { + stun: (opts || {}).stun || require('./stun.json'), + turn: (opts || {}).turn || require('./turn.json') + }; + + var stunCount = (opts || {}).stunCount || 2; + var turnCount = (opts || {}).turnCount || 0; + var selected; + + function getServers(type, count) { + var out = []; + var input = [].concat(servers[type]); + var idx; + + while (input.length && out.length < count) { + idx = (Math.random() * input.length) | 0; + out = out.concat(input.splice(idx, 1)); + } + + return out.map(function(url) { + //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up + if ((typeof url !== 'string') && (! (url instanceof String))) { + return url; + } else { + return normalice(type + ':' + url); + } + }); + } + + // add stun servers + selected = [].concat(getServers('stun', stunCount)); + + if (turnCount) { + selected = selected.concat(getServers('turn', turnCount)); + } + + return selected; +}; + +},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){ +module.exports=[ + "stun.l.google.com:19302", + "stun1.l.google.com:19302", + "stun2.l.google.com:19302", + "stun3.l.google.com:19302", + "stun4.l.google.com:19302", + "stun.ekiga.net", + "stun.ideasip.com", + "stun.schlund.de", + "stun.stunprotocol.org:3478", + "stun.voiparound.com", + "stun.voipbuster.com", + "stun.voipstunt.com", + "stun.voxgratia.org", + "stun.services.mozilla.com" +] + +},{}],4:[function(require,module,exports){ +module.exports=[] + +},{}],5:[function(require,module,exports){ +var WildEmitter = require('wildemitter'); + +function getMaxVolume (analyser, fftBins) { + var maxVolume = -Infinity; + analyser.getFloatFrequencyData(fftBins); + + for(var i=4, ii=fftBins.length; i < ii; i++) { + if (fftBins[i] > maxVolume && fftBins[i] < 0) { + maxVolume = fftBins[i]; + } + }; + + return maxVolume; +} + + +var audioContextType; +if (typeof window !== 'undefined') { + audioContextType = window.AudioContext || window.webkitAudioContext; +} +// use a single audio context due to hardware limits +var audioContext = null; +module.exports = function(stream, options) { + var harker = new WildEmitter(); + + + // make it not break in non-supported browsers + if (!audioContextType) return harker; + + //Config + var options = options || {}, + smoothing = (options.smoothing || 0.1), + interval = (options.interval || 50), + threshold = options.threshold, + play = options.play, + history = options.history || 10, + running = true; + + //Setup Audio Context + if (!audioContext) { + audioContext = new audioContextType(); + } + var sourceNode, fftBins, analyser; + + analyser = audioContext.createAnalyser(); + analyser.fftSize = 512; + analyser.smoothingTimeConstant = smoothing; + fftBins = new Float32Array(analyser.frequencyBinCount); + + if (stream.jquery) stream = stream[0]; + if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { + //Audio Tag + sourceNode = audioContext.createMediaElementSource(stream); + if (typeof play === 'undefined') play = true; + threshold = threshold || -50; + } else { + //WebRTC Stream + sourceNode = audioContext.createMediaStreamSource(stream); + threshold = threshold || -50; + } + + sourceNode.connect(analyser); + if (play) analyser.connect(audioContext.destination); + + harker.speaking = false; + + harker.suspend = function() { + audioContext.suspend(); + } + harker.resume = function() { + audioContext.resume(); + } + Object.defineProperty(harker, 'state', { get: function() { + return audioContext.state; + }}); + audioContext.onstatechange = function() { + harker.emit('state_change', audioContext.state); + } + + harker.setThreshold = function(t) { + threshold = t; + }; + + harker.setInterval = function(i) { + interval = i; + }; + + harker.stop = function() { + running = false; + harker.emit('volume_change', -100, threshold); + if (harker.speaking) { + harker.speaking = false; + harker.emit('stopped_speaking'); + } + analyser.disconnect(); + sourceNode.disconnect(); + }; + harker.speakingHistory = []; + for (var i = 0; i < history; i++) { + harker.speakingHistory.push(0); + } + + // Poll the analyser node to determine if speaking + // and emit events if changed + var looper = function() { + setTimeout(function() { + + //check if stop has been called + if(!running) { + return; + } + + var currentVolume = getMaxVolume(analyser, fftBins); + + harker.emit('volume_change', currentVolume, threshold); + + var history = 0; + if (currentVolume > threshold && !harker.speaking) { + // trigger quickly, short history + for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { + history += harker.speakingHistory[i]; + } + if (history >= 2) { + harker.speaking = true; + harker.emit('speaking'); + } + } else if (currentVolume < threshold && harker.speaking) { + for (var i = 0; i < harker.speakingHistory.length; i++) { + history += harker.speakingHistory[i]; + } + if (history == 0) { + harker.speaking = false; + harker.emit('stopped_speaking'); + } + } + harker.speakingHistory.shift(); + harker.speakingHistory.push(0 + (currentVolume > threshold)); + + looper(); + }, interval); + }; + looper(); + + + return harker; +} + +},{"wildemitter":14}],6:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],7:[function(require,module,exports){ +/** + # normalice + + Normalize an ice server configuration object (or plain old string) into a format + that is usable in all browsers supporting WebRTC. Primarily this module is designed + to help with the transition of the `url` attribute of the configuration object to + the `urls` attribute. + + ## Example Usage + + <<< examples/simple.js + +**/ + +var protocols = [ + 'stun:', + 'turn:' +]; + +module.exports = function(input) { + var url = (input || {}).url || input; + var protocol; + var parts; + var output = {}; + + // if we don't have a string url, then allow the input to passthrough + if (typeof url != 'string' && (! (url instanceof String))) { + return input; + } + + // trim the url string, and convert to an array + url = url.trim(); + + // if the protocol is not known, then passthrough + protocol = protocols[protocols.indexOf(url.slice(0, 5))]; + if (! protocol) { + return input; + } + + // now let's attack the remaining url parts + url = url.slice(5); + parts = url.split('@'); + + output.username = input.username; + output.credential = input.credential; + // if we have an authentication part, then set the credentials + if (parts.length > 1) { + url = parts[1]; + parts = parts[0].split(':'); + + // add the output credential and username + output.username = parts[0]; + output.credential = (input || {}).credential || parts[1] || ''; + } + + output.url = protocol + url; + output.urls = [ output.url ]; + + return output; +}; + +},{}],8:[function(require,module,exports){ +(function (global){ +/*! + * Platform.js + * Copyright 2014-2018 Benjamin Tan + * Copyright 2011-2013 John-David Dalton + * Available under MIT license + */ +;(function() { + 'use strict'; + + /** Used to determine if values are of the language type `Object`. */ + var objectTypes = { + 'function': true, + 'object': true + }; + + /** Used as a reference to the global object. */ + var root = (objectTypes[typeof window] && window) || this; + + /** Backup possible global object. */ + var oldRoot = root; + + /** Detect free variable `exports`. */ + var freeExports = objectTypes[typeof exports] && exports; + + /** Detect free variable `module`. */ + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + + /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ + var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; + if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { + root = freeGlobal; + } + + /** + * Used as the maximum length of an array-like object. + * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) + * for more details. + */ + var maxSafeInteger = Math.pow(2, 53) - 1; + + /** Regular expression to detect Opera. */ + var reOpera = /\bOpera/; + + /** Possible global object. */ + var thisBinding = this; + + /** Used for native method references. */ + var objectProto = Object.prototype; + + /** Used to check for own properties of an object. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to resolve the internal `[[Class]]` of values. */ + var toString = objectProto.toString; + + /*--------------------------------------------------------------------------*/ + + /** + * Capitalizes a string value. + * + * @private + * @param {string} string The string to capitalize. + * @returns {string} The capitalized string. + */ + function capitalize(string) { + string = String(string); + return string.charAt(0).toUpperCase() + string.slice(1); + } + + /** + * A utility function to clean up the OS name. + * + * @private + * @param {string} os The OS name to clean up. + * @param {string} [pattern] A `RegExp` pattern matching the OS name. + * @param {string} [label] A label for the OS. + */ + function cleanupOS(os, pattern, label) { + // Platform tokens are defined at: + // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + var data = { + '10.0': '10', + '6.4': '10 Technical Preview', + '6.3': '8.1', + '6.2': '8', + '6.1': 'Server 2008 R2 / 7', + '6.0': 'Server 2008 / Vista', + '5.2': 'Server 2003 / XP 64-bit', + '5.1': 'XP', + '5.01': '2000 SP1', + '5.0': '2000', + '4.0': 'NT', + '4.90': 'ME' + }; + // Detect Windows version from platform tokens. + if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && + (data = data[/[\d.]+$/.exec(os)])) { + os = 'Windows ' + data; + } + // Correct character case and cleanup string. + os = String(os); + + if (pattern && label) { + os = os.replace(RegExp(pattern, 'i'), label); + } + + os = format( + os.replace(/ ce$/i, ' CE') + .replace(/\bhpw/i, 'web') + .replace(/\bMacintosh\b/, 'Mac OS') + .replace(/_PowerPC\b/i, ' OS') + .replace(/\b(OS X) [^ \d]+/i, '$1') + .replace(/\bMac (OS X)\b/, '$1') + .replace(/\/(\d)/, ' $1') + .replace(/_/g, '.') + .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') + .replace(/\bx86\.64\b/gi, 'x86_64') + .replace(/\b(Windows Phone) OS\b/, '$1') + .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') + .split(' on ')[0] + ); + + return os; + } + + /** + * An iteration utility for arrays and objects. + * + * @private + * @param {Array|Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + */ + function each(object, callback) { + var index = -1, + length = object ? object.length : 0; + + if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { + while (++index < length) { + callback(object[index], index, object); + } + } else { + forOwn(object, callback); + } + } + + /** + * Trim and conditionally capitalize string values. + * + * @private + * @param {string} string The string to format. + * @returns {string} The formatted string. + */ + function format(string) { + string = trim(string); + return /^(?:webOS|i(?:OS|P))/.test(string) + ? string + : capitalize(string); + } + + /** + * Iterates over an object's own properties, executing the `callback` for each. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function executed per own property. + */ + function forOwn(object, callback) { + for (var key in object) { + if (hasOwnProperty.call(object, key)) { + callback(object[key], key, object); + } + } + } + + /** + * Gets the internal `[[Class]]` of a value. + * + * @private + * @param {*} value The value. + * @returns {string} The `[[Class]]`. + */ + function getClassOf(value) { + return value == null + ? capitalize(value) + : toString.call(value).slice(8, -1); + } + + /** + * Host objects can return type values that are different from their actual + * data type. The objects we are concerned with usually return non-primitive + * types of "object", "function", or "unknown". + * + * @private + * @param {*} object The owner of the property. + * @param {string} property The property to check. + * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. + */ + function isHostType(object, property) { + var type = object != null ? typeof object[property] : 'number'; + return !/^(?:boolean|number|string|undefined)$/.test(type) && + (type == 'object' ? !!object[property] : true); + } + + /** + * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. + * + * @private + * @param {string} string The string to qualify. + * @returns {string} The qualified string. + */ + function qualify(string) { + return String(string).replace(/([ -])(?!$)/g, '$1?'); + } + + /** + * A bare-bones `Array#reduce` like utility function. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {*} The accumulated result. + */ + function reduce(array, callback) { + var accumulator = null; + each(array, function(value, index) { + accumulator = callback(accumulator, value, index, array); + }); + return accumulator; + } + + /** + * Removes leading and trailing whitespace from a string. + * + * @private + * @param {string} string The string to trim. + * @returns {string} The trimmed string. + */ + function trim(string) { + return String(string).replace(/^ +| +$/g, ''); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a new platform object. + * + * @memberOf platform + * @param {Object|string} [ua=navigator.userAgent] The user agent string or + * context object. + * @returns {Object} A platform object. + */ + function parse(ua) { + + /** The environment context object. */ + var context = root; + + /** Used to flag when a custom context is provided. */ + var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; + + // Juggle arguments. + if (isCustomContext) { + context = ua; + ua = null; + } + + /** Browser navigator object. */ + var nav = context.navigator || {}; + + /** Browser user agent string. */ + var userAgent = nav.userAgent || ''; + + ua || (ua = userAgent); + + /** Used to flag when `thisBinding` is the [ModuleScope]. */ + var isModuleScope = isCustomContext || thisBinding == oldRoot; + + /** Used to detect if browser is like Chrome. */ + var likeChrome = isCustomContext + ? !!nav.likeChrome + : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); + + /** Internal `[[Class]]` value shortcuts. */ + var objectClass = 'Object', + airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', + enviroClass = isCustomContext ? objectClass : 'Environment', + javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), + phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; + + /** Detect Java environments. */ + var java = /\bJava/.test(javaClass) && context.java; + + /** Detect Rhino. */ + var rhino = java && getClassOf(context.environment) == enviroClass; + + /** A character to represent alpha. */ + var alpha = java ? 'a' : '\u03b1'; + + /** A character to represent beta. */ + var beta = java ? 'b' : '\u03b2'; + + /** Browser document object. */ + var doc = context.document || {}; + + /** + * Detect Opera browser (Presto-based). + * http://www.howtocreate.co.uk/operaStuff/operaObject.html + * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini + */ + var opera = context.operamini || context.opera; + + /** Opera `[[Class]]`. */ + var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) + ? operaClass + : (opera = null); + + /*------------------------------------------------------------------------*/ + + /** Temporary variable used over the script's lifetime. */ + var data; + + /** The CPU architecture. */ + var arch = ua; + + /** Platform description array. */ + var description = []; + + /** Platform alpha/beta indicator. */ + var prerelease = null; + + /** A flag to indicate that environment features should be used to resolve the platform. */ + var useFeatures = ua == userAgent; + + /** The browser/environment version. */ + var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); + + /** A flag to indicate if the OS ends with "/ Version" */ + var isSpecialCasedOS; + + /* Detectable layout engines (order is important). */ + var layout = getLayout([ + { 'label': 'EdgeHTML', 'pattern': 'Edge' }, + 'Trident', + { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, + 'iCab', + 'Presto', + 'NetFront', + 'Tasman', + 'KHTML', + 'Gecko' + ]); + + /* Detectable browser names (order is important). */ + var name = getName([ + 'Adobe AIR', + 'Arora', + 'Avant Browser', + 'Breach', + 'Camino', + 'Electron', + 'Epiphany', + 'Fennec', + 'Flock', + 'Galeon', + 'GreenBrowser', + 'iCab', + 'Iceweasel', + 'K-Meleon', + 'Konqueror', + 'Lunascape', + 'Maxthon', + { 'label': 'Microsoft Edge', 'pattern': 'Edge' }, + 'Midori', + 'Nook Browser', + 'PaleMoon', + 'PhantomJS', + 'Raven', + 'Rekonq', + 'RockMelt', + { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' }, + 'SeaMonkey', + { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Sleipnir', + 'SlimBrowser', + { 'label': 'SRWare Iron', 'pattern': 'Iron' }, + 'Sunrise', + 'Swiftfox', + 'Waterfox', + 'WebPositive', + 'Opera Mini', + { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, + 'Opera', + { 'label': 'Opera', 'pattern': 'OPR' }, + 'Chrome', + { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, + { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, + { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' }, + { 'label': 'IE', 'pattern': 'IEMobile' }, + { 'label': 'IE', 'pattern': 'MSIE' }, + 'Safari' + ]); + + /* Detectable products (order is important). */ + var product = getProduct([ + { 'label': 'BlackBerry', 'pattern': 'BB10' }, + 'BlackBerry', + { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, + { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, + { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, + { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, + { 'label': 'Galaxy S5', 'pattern': 'SM-G900' }, + { 'label': 'Galaxy S6', 'pattern': 'SM-G920' }, + { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' }, + { 'label': 'Galaxy S7', 'pattern': 'SM-G930' }, + { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' }, + 'Google TV', + 'Lumia', + 'iPad', + 'iPod', + 'iPhone', + 'Kindle', + { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Nexus', + 'Nook', + 'PlayBook', + 'PlayStation Vita', + 'PlayStation', + 'TouchPad', + 'Transformer', + { 'label': 'Wii U', 'pattern': 'WiiU' }, + 'Wii', + 'Xbox One', + { 'label': 'Xbox 360', 'pattern': 'Xbox' }, + 'Xoom' + ]); + + /* Detectable manufacturers. */ + var manufacturer = getManufacturer({ + 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, + 'Archos': {}, + 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, + 'Asus': { 'Transformer': 1 }, + 'Barnes & Noble': { 'Nook': 1 }, + 'BlackBerry': { 'PlayBook': 1 }, + 'Google': { 'Google TV': 1, 'Nexus': 1 }, + 'HP': { 'TouchPad': 1 }, + 'HTC': {}, + 'LG': {}, + 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, + 'Motorola': { 'Xoom': 1 }, + 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, + 'Nokia': { 'Lumia': 1 }, + 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, + 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 } + }); + + /* Detectable operating systems (order is important). */ + var os = getOS([ + 'Windows Phone', + 'Android', + 'CentOS', + { 'label': 'Chrome OS', 'pattern': 'CrOS' }, + 'Debian', + 'Fedora', + 'FreeBSD', + 'Gentoo', + 'Haiku', + 'Kubuntu', + 'Linux Mint', + 'OpenBSD', + 'Red Hat', + 'SuSE', + 'Ubuntu', + 'Xubuntu', + 'Cygwin', + 'Symbian OS', + 'hpwOS', + 'webOS ', + 'webOS', + 'Tablet OS', + 'Tizen', + 'Linux', + 'Mac OS X', + 'Macintosh', + 'Mac', + 'Windows 98;', + 'Windows ' + ]); + + /*------------------------------------------------------------------------*/ + + /** + * Picks the layout engine from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected layout engine. + */ + function getLayout(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the manufacturer from an array of guesses. + * + * @private + * @param {Array} guesses An object of guesses. + * @returns {null|string} The detected manufacturer. + */ + function getManufacturer(guesses) { + return reduce(guesses, function(result, value, key) { + // Lookup the manufacturer by product or scan the UA for the manufacturer. + return result || ( + value[product] || + value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || + RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) + ) && key; + }); + } + + /** + * Picks the browser name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected browser name. + */ + function getName(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the OS name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected OS name. + */ + function getOS(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) + )) { + result = cleanupOS(result, pattern, guess.label || guess); + } + return result; + }); + } + + /** + * Picks the product name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected product name. + */ + function getProduct(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || + RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) || + RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) + )) { + // Split by forward slash and append product version if needed. + if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { + result[0] += ' ' + result[1]; + } + // Correct character case and cleanup string. + guess = guess.label || guess; + result = format(result[0] + .replace(RegExp(pattern, 'i'), guess) + .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') + .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); + } + return result; + }); + } + + /** + * Resolves the version using an array of UA patterns. + * + * @private + * @param {Array} patterns An array of UA patterns. + * @returns {null|string} The detected version. + */ + function getVersion(patterns) { + return reduce(patterns, function(result, pattern) { + return result || (RegExp(pattern + + '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; + }); + } + + /** + * Returns `platform.description` when the platform object is coerced to a string. + * + * @name toString + * @memberOf platform + * @returns {string} Returns `platform.description` if available, else an empty string. + */ + function toStringPlatform() { + return this.description || ''; + } + + /*------------------------------------------------------------------------*/ + + // Convert layout to an array so we can add extra details. + layout && (layout = [layout]); + + // Detect product names that contain their manufacturer's name. + if (manufacturer && !product) { + product = getProduct([manufacturer]); + } + // Clean up Google TV. + if ((data = /\bGoogle TV\b/.exec(product))) { + product = data[0]; + } + // Detect simulators. + if (/\bSimulator\b/i.test(ua)) { + product = (product ? product + ' ' : '') + 'Simulator'; + } + // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. + if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { + description.push('running in Turbo/Uncompressed mode'); + } + // Detect IE Mobile 11. + if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) { + data = parse(ua.replace(/like iPhone OS/, '')); + manufacturer = data.manufacturer; + product = data.product; + } + // Detect iOS. + else if (/^iP/.test(product)) { + name || (name = 'Safari'); + os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) + ? ' ' + data[1].replace(/_/g, '.') + : ''); + } + // Detect Kubuntu. + else if (name == 'Konqueror' && !/buntu/i.test(os)) { + os = 'Kubuntu'; + } + // Detect Android browsers. + else if ((manufacturer && manufacturer != 'Google' && + ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) || + (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) { + name = 'Android Browser'; + os = /\bAndroid\b/.test(os) ? os : 'Android'; + } + // Detect Silk desktop/accelerated modes. + else if (name == 'Silk') { + if (!/\bMobi/i.test(ua)) { + os = 'Android'; + description.unshift('desktop mode'); + } + if (/Accelerated *= *true/i.test(ua)) { + description.unshift('accelerated'); + } + } + // Detect PaleMoon identifying as Firefox. + else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { + description.push('identifying as Firefox ' + data[1]); + } + // Detect Firefox OS and products running Firefox. + else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { + os || (os = 'Firefox OS'); + product || (product = data[1]); + } + // Detect false positives for Firefox/Safari. + else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { + // Escape the `/` for Firefox 1. + if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { + // Clear name of false positives. + name = null; + } + // Reassign a generic name. + if ((data = product || manufacturer || os) && + (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { + name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; + } + } + // Add Chrome version to description for Electron. + else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) { + description.push('Chromium ' + data); + } + // Detect non-Opera (Presto-based) versions (order is important). + if (!version) { + version = getVersion([ + '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))', + 'Version', + qualify(name), + '(?:Firefox|Minefield|NetFront)' + ]); + } + // Detect stubborn layout engines. + if ((data = + layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || + /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || + /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || + !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || + layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' + )) { + layout = [data]; + } + // Detect Windows Phone 7 desktop mode. + if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { + name += ' Mobile'; + os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); + description.unshift('desktop mode'); + } + // Detect Windows Phone 8.x desktop mode. + else if (/\bWPDesktop\b/i.test(ua)) { + name = 'IE Mobile'; + os = 'Windows Phone 8.x'; + description.unshift('desktop mode'); + version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); + } + // Detect IE 11 identifying as other browsers. + else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { + if (name) { + description.push('identifying as ' + name + (version ? ' ' + version : '')); + } + name = 'IE'; + version = data[1]; + } + // Leverage environment features. + if (useFeatures) { + // Detect server-side environments. + // Rhino has a global function while others have a global object. + if (isHostType(context, 'global')) { + if (java) { + data = java.lang.System; + arch = data.getProperty('os.arch'); + os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); + } + if (rhino) { + try { + version = context.require('ringo/engine').version.join('.'); + name = 'RingoJS'; + } catch(e) { + if ((data = context.system) && data.global.system == context.system) { + name = 'Narwhal'; + os || (os = data[0].os || null); + } + } + if (!name) { + name = 'Rhino'; + } + } + else if ( + typeof context.process == 'object' && !context.process.browser && + (data = context.process) + ) { + if (typeof data.versions == 'object') { + if (typeof data.versions.electron == 'string') { + description.push('Node ' + data.versions.node); + name = 'Electron'; + version = data.versions.electron; + } else if (typeof data.versions.nw == 'string') { + description.push('Chromium ' + version, 'Node ' + data.versions.node); + name = 'NW.js'; + version = data.versions.nw; + } + } + if (!name) { + name = 'Node.js'; + arch = data.arch; + os = data.platform; + version = /[\d.]+/.exec(data.version); + version = version ? version[0] : null; + } + } + } + // Detect Adobe AIR. + else if (getClassOf((data = context.runtime)) == airRuntimeClass) { + name = 'Adobe AIR'; + os = data.flash.system.Capabilities.os; + } + // Detect PhantomJS. + else if (getClassOf((data = context.phantom)) == phantomClass) { + name = 'PhantomJS'; + version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); + } + // Detect IE compatibility modes. + else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { + // We're in compatibility mode when the Trident version + 4 doesn't + // equal the document mode. + version = [version, doc.documentMode]; + if ((data = +data[1] + 4) != version[1]) { + description.push('IE ' + version[1] + ' mode'); + layout && (layout[1] = ''); + version[1] = data; + } + version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; + } + // Detect IE 11 masking as other browsers. + else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) { + description.push('masking as ' + name + ' ' + version); + name = 'IE'; + version = '11.0'; + layout = ['Trident']; + os = 'Windows'; + } + os = os && format(os); + } + // Detect prerelease phases. + if (version && (data = + /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || + /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || + /\bMinefield\b/i.test(ua) && 'a' + )) { + prerelease = /b/i.test(data) ? 'beta' : 'alpha'; + version = version.replace(RegExp(data + '\\+?$'), '') + + (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); + } + // Detect Firefox Mobile. + if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) { + name = 'Firefox Mobile'; + } + // Obscure Maxthon's unreliable version. + else if (name == 'Maxthon' && version) { + version = version.replace(/\.[\d.]+/, '.x'); + } + // Detect Xbox 360 and Xbox One. + else if (/\bXbox\b/i.test(product)) { + if (product == 'Xbox 360') { + os = null; + } + if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { + description.unshift('mobile mode'); + } + } + // Add mobile postfix. + else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && + (os == 'Windows CE' || /Mobi/i.test(ua))) { + name += ' Mobile'; + } + // Detect IE platform preview. + else if (name == 'IE' && useFeatures) { + try { + if (context.external === null) { + description.unshift('platform preview'); + } + } catch(e) { + description.unshift('embedded'); + } + } + // Detect BlackBerry OS version. + // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp + else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = + (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || + version + )) { + data = [data, /BB10/.test(ua)]; + os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; + version = null; + } + // Detect Opera identifying/masking itself as another browser. + // http://www.opera.com/support/kb/view/843/ + else if (this != forOwn && product != 'Wii' && ( + (useFeatures && opera) || + (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || + (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || + (name == 'IE' && ( + (os && !/^Win/.test(os) && version > 5.5) || + /\bWindows XP\b/.test(os) && version > 8 || + version == 8 && !/\bTrident\b/.test(ua) + )) + ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { + // When "identifying", the UA contains both Opera and the other browser's name. + data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); + if (reOpera.test(name)) { + if (/\bIE\b/.test(data) && os == 'Mac OS') { + os = null; + } + data = 'identify' + data; + } + // When "masking", the UA contains only the other browser's name. + else { + data = 'mask' + data; + if (operaClass) { + name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); + } else { + name = 'Opera'; + } + if (/\bIE\b/.test(data)) { + os = null; + } + if (!useFeatures) { + version = null; + } + } + layout = ['Presto']; + description.push(data); + } + // Detect WebKit Nightly and approximate Chrome/Safari versions. + if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { + // Correct build number for numeric comparison. + // (e.g. "532.5" becomes "532.05") + data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; + // Nightly builds are postfixed with a "+". + if (name == 'Safari' && data[1].slice(-1) == '+') { + name = 'WebKit Nightly'; + prerelease = 'alpha'; + version = data[1].slice(0, -1); + } + // Clear incorrect browser versions. + else if (version == data[1] || + version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { + version = null; + } + // Use the full Chrome version when available. + data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]; + // Detect Blink layout engine. + if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { + layout = ['Blink']; + } + // Detect JavaScriptCore. + // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi + if (!useFeatures || (!likeChrome && !data[1])) { + layout && (layout[1] = 'like Safari'); + data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8'); + } else { + layout && (layout[1] = 'like Chrome'); + data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); + } + // Add the postfix of ".x" or "+" for approximate versions. + layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); + // Obscure version for some Safari 1-2 releases. + if (name == 'Safari' && (!version || parseInt(version) > 45)) { + version = data; + } + } + // Detect Opera desktop modes. + if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { + name += ' '; + description.unshift('desktop mode'); + if (data == 'zvav') { + name += 'Mini'; + version = null; + } else { + name += 'Mobile'; + } + os = os.replace(RegExp(' *' + data + '$'), ''); + } + // Detect Chrome desktop mode. + else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { + description.unshift('desktop mode'); + name = 'Chrome Mobile'; + version = null; + + if (/\bOS X\b/.test(os)) { + manufacturer = 'Apple'; + os = 'iOS 4.3+'; + } else { + os = null; + } + } + // Strip incorrect OS versions. + if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && + ua.indexOf('/' + data + '-') > -1) { + os = trim(os.replace(data, '')); + } + // Add layout engine. + if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( + /Browser|Lunascape|Maxthon/.test(name) || + name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || + /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) { + // Don't add layout details to description if they are falsey. + (data = layout[layout.length - 1]) && description.push(data); + } + // Combine contextual information. + if (description.length) { + description = ['(' + description.join('; ') + ')']; + } + // Append manufacturer to description. + if (manufacturer && product && product.indexOf(manufacturer) < 0) { + description.push('on ' + manufacturer); + } + // Append product to description. + if (product) { + description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); + } + // Parse the OS into an object. + if (os) { + data = / ([\d.+]+)$/.exec(os); + isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; + os = { + 'architecture': 32, + 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, + 'version': data ? data[1] : null, + 'toString': function() { + var version = this.version; + return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); + } + }; + } + // Add browser/OS architecture. + if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { + if (os) { + os.architecture = 64; + os.family = os.family.replace(RegExp(' *' + data), ''); + } + if ( + name && (/\bWOW64\b/i.test(ua) || + (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) + ) { + description.unshift('32-bit'); + } + } + // Chrome 39 and above on OS X is always 64-bit. + else if ( + os && /^OS X/.test(os.family) && + name == 'Chrome' && parseFloat(version) >= 39 + ) { + os.architecture = 64; + } + + ua || (ua = null); + + /*------------------------------------------------------------------------*/ + + /** + * The platform object. + * + * @name platform + * @type Object + */ + var platform = {}; + + /** + * The platform description. + * + * @memberOf platform + * @type string|null + */ + platform.description = ua; + + /** + * The name of the browser's layout engine. + * + * The list of common layout engines include: + * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit" + * + * @memberOf platform + * @type string|null + */ + platform.layout = layout && layout[0]; + + /** + * The name of the product's manufacturer. + * + * The list of manufacturers include: + * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry", + * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo", + * "Nokia", "Samsung" and "Sony" + * + * @memberOf platform + * @type string|null + */ + platform.manufacturer = manufacturer; + + /** + * The name of the browser/environment. + * + * The list of common browser names include: + * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE", + * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk", + * "Opera Mini" and "Opera" + * + * Mobile versions of some browsers have "Mobile" appended to their name: + * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile" + * + * @memberOf platform + * @type string|null + */ + platform.name = name; + + /** + * The alpha/beta release indicator. + * + * @memberOf platform + * @type string|null + */ + platform.prerelease = prerelease; + + /** + * The name of the product hosting the browser. + * + * The list of common products include: + * + * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle", + * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer" + * + * @memberOf platform + * @type string|null + */ + platform.product = product; + + /** + * The browser's user agent string. + * + * @memberOf platform + * @type string|null + */ + platform.ua = ua; + + /** + * The browser/environment version. + * + * @memberOf platform + * @type string|null + */ + platform.version = name && version; + + /** + * The name of the operating system. + * + * @memberOf platform + * @type Object + */ + platform.os = os || { + + /** + * The CPU architecture the OS is built for. + * + * @memberOf platform.os + * @type number|null + */ + 'architecture': null, + + /** + * The family of the OS. + * + * Common values include: + * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", + * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", + * "Android", "iOS" and "Windows Phone" + * + * @memberOf platform.os + * @type string|null + */ + 'family': null, + + /** + * The version of the OS. + * + * @memberOf platform.os + * @type string|null + */ + 'version': null, + + /** + * Returns the OS string. + * + * @memberOf platform.os + * @returns {string} The OS string. + */ + 'toString': function() { return 'null'; } + }; + + platform.parse = parse; + platform.toString = toStringPlatform; + + if (platform.version) { + description.unshift(version); + } + if (platform.name) { + description.unshift(name); + } + if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { + description.push(product ? '(' + os + ')' : 'on ' + os); + } + if (description.length) { + platform.description = description.join(' '); + } + return platform; + } + + /*--------------------------------------------------------------------------*/ + + // Export platform. + var platform = parse(); + + // Some AMD build optimizers, like r.js, check for condition patterns like the following: + if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // Expose platform on the global object to prevent errors when platform is + // loaded by a script tag in the presence of an AMD loader. + // See http://requirejs.org/docs/errors.html#mismatch for more details. + root.platform = platform; + + // Define as an anonymous module so platform can be aliased through path mapping. + define(function() { + return platform; + }); + } + // Check for `exports` after `define` in case a build optimizer adds an `exports` object. + else if (freeExports && freeModule) { + // Export for CommonJS support. + forOwn(platform, function(value, key) { + freeExports[key] = value; + }); + } + else { + // Export to the global object. + root.platform = platform; + } +}.call(this)); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],9:[function(require,module,exports){ +var v1 = require('./v1'); +var v4 = require('./v4'); + +var uuid = v4; +uuid.v1 = v1; +uuid.v4 = v4; + +module.exports = uuid; + +},{"./v1":12,"./v4":13}],10:[function(require,module,exports){ +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +var byteToHex = []; +for (var i = 0; i < 256; ++i) { + byteToHex[i] = (i + 0x100).toString(16).substr(1); +} + +function bytesToUuid(buf, offset) { + var i = offset || 0; + var bth = byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; +} + +module.exports = bytesToUuid; + +},{}],11:[function(require,module,exports){ +// Unique ID creation requires a high quality random # generator. In the +// browser this is a little complicated due to unknown quality of Math.random() +// and inconsistent support for the `crypto` API. We do the best we can via +// feature-detection + +// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. +var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) || + (typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto)); +if (getRandomValues) { + // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto + var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef + + module.exports = function whatwgRNG() { + getRandomValues(rnds8); + return rnds8; + }; +} else { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var rnds = new Array(16); + + module.exports = function mathRNG() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return rnds; + }; +} + +},{}],12:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html + +var _nodeId; +var _clockseq; + +// Previous uuid creation time +var _lastMSecs = 0; +var _lastNSecs = 0; + +// See https://github.com/broofa/node-uuid for API details +function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + var node = options.node || _nodeId; + var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; + + // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + if (node == null || clockseq == null) { + var seedBytes = rng(); + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [ + seedBytes[0] | 0x01, + seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] + ]; + } + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + for (var n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf ? buf : bytesToUuid(b); +} + +module.exports = v1; + +},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +function v4(options, buf, offset) { + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options === 'binary' ? new Array(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ++ii) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || bytesToUuid(rnds); +} + +module.exports = v4; + +},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){ +/* +WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based +on @visionmedia's Emitter from UI Kit. + +Why? I wanted it standalone. + +I also wanted support for wildcard emitters like this: + +emitter.on('*', function (eventName, other, event, payloads) { + +}); + +emitter.on('somenamespace*', function (eventName, payloads) { + +}); + +Please note that callbacks triggered by wildcard registered events also get +the event name as the first argument. +*/ + +module.exports = WildEmitter; + +function WildEmitter() { } + +WildEmitter.mixin = function (constructor) { + var prototype = constructor.prototype || constructor; + + prototype.isWildEmitter= true; + + // Listen on the given `event` with `fn`. Store a group name if present. + prototype.on = function (event, groupName, fn) { + this.callbacks = this.callbacks || {}; + var hasGroup = (arguments.length === 3), + group = hasGroup ? arguments[1] : undefined, + func = hasGroup ? arguments[2] : arguments[1]; + func._groupName = group; + (this.callbacks[event] = this.callbacks[event] || []).push(func); + return this; + }; + + // Adds an `event` listener that will be invoked a single + // time then automatically removed. + prototype.once = function (event, groupName, fn) { + var self = this, + hasGroup = (arguments.length === 3), + group = hasGroup ? arguments[1] : undefined, + func = hasGroup ? arguments[2] : arguments[1]; + function on() { + self.off(event, on); + func.apply(this, arguments); + } + this.on(event, group, on); + return this; + }; + + // Unbinds an entire group + prototype.releaseGroup = function (groupName) { + this.callbacks = this.callbacks || {}; + var item, i, len, handlers; + for (item in this.callbacks) { + handlers = this.callbacks[item]; + for (i = 0, len = handlers.length; i < len; i++) { + if (handlers[i]._groupName === groupName) { + //console.log('removing'); + // remove it and shorten the array we're looping through + handlers.splice(i, 1); + i--; + len--; + } + } + } + return this; + }; + + // Remove the given callback for `event` or all + // registered callbacks. + prototype.off = function (event, fn) { + this.callbacks = this.callbacks || {}; + var callbacks = this.callbacks[event], + i; + + if (!callbacks) return this; + + // remove all handlers + if (arguments.length === 1) { + delete this.callbacks[event]; + return this; + } + + // remove specific handler + i = callbacks.indexOf(fn); + callbacks.splice(i, 1); + if (callbacks.length === 0) { + delete this.callbacks[event]; + } + return this; + }; + + /// Emit `event` with the given args. + // also calls any `*` handlers + prototype.emit = function (event) { + this.callbacks = this.callbacks || {}; + var args = [].slice.call(arguments, 1), + callbacks = this.callbacks[event], + specialCallbacks = this.getWildcardCallbacks(event), + i, + len, + item, + listeners; + + if (callbacks) { + listeners = callbacks.slice(); + for (i = 0, len = listeners.length; i < len; ++i) { + if (!listeners[i]) { + break; + } + listeners[i].apply(this, args); + } + } + + if (specialCallbacks) { + len = specialCallbacks.length; + listeners = specialCallbacks.slice(); + for (i = 0, len = listeners.length; i < len; ++i) { + if (!listeners[i]) { + break; + } + listeners[i].apply(this, [event].concat(args)); + } + } + + return this; + }; + + // Helper for for finding special wildcard event handlers that match the event + prototype.getWildcardCallbacks = function (eventName) { + this.callbacks = this.callbacks || {}; + var item, + split, + result = []; + + for (item in this.callbacks) { + split = item.split('*'); + if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { + result = result.concat(this.callbacks[item]); + } + } + return result; + }; + +}; + +WildEmitter.mixin(WildEmitter); + +},{}],15:[function(require,module,exports){ +/*! + * EventEmitter v5.2.4 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - http://oli.me.uk/ + * @preserve + */ + +;(function (exports) { + 'use strict'; + + /** + * Class for managing events. + * Can be extended to provide event functionality in other classes. + * + * @class EventEmitter Manages event registering and emitting. + */ + function EventEmitter() {} + + // Shortcuts to improve speed and size + var proto = EventEmitter.prototype; + var originalGlobalValue = exports.EventEmitter; + + /** + * Finds the index of the listener for the event in its storage array. + * + * @param {Function[]} listeners Array of listeners to search through. + * @param {Function} listener Method to look for. + * @return {Number} Index of the specified listener, -1 if not found + * @api private + */ + function indexOfListener(listeners, listener) { + var i = listeners.length; + while (i--) { + if (listeners[i].listener === listener) { + return i; + } + } + + return -1; + } + + /** + * Alias a method while keeping the context correct, to allow for overwriting of target method. + * + * @param {String} name The name of the target method. + * @return {Function} The aliased method + * @api private + */ + function alias(name) { + return function aliasClosure() { + return this[name].apply(this, arguments); + }; + } + + /** + * Returns the listener array for the specified event. + * Will initialise the event object and listener arrays if required. + * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. + * Each property in the object response is an array of listener functions. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Function[]|Object} All listener functions for the event. + */ + proto.getListeners = function getListeners(evt) { + var events = this._getEvents(); + var response; + var key; + + // Return a concatenated array of all matching events if + // the selector is a regular expression. + if (evt instanceof RegExp) { + response = {}; + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + response[key] = events[key]; + } + } + } + else { + response = events[evt] || (events[evt] = []); + } + + return response; + }; + + /** + * Takes a list of listener objects and flattens it into a list of listener functions. + * + * @param {Object[]} listeners Raw listener objects. + * @return {Function[]} Just the listener functions. + */ + proto.flattenListeners = function flattenListeners(listeners) { + var flatListeners = []; + var i; + + for (i = 0; i < listeners.length; i += 1) { + flatListeners.push(listeners[i].listener); + } + + return flatListeners; + }; + + /** + * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Object} All listener functions for an event in an object. + */ + proto.getListenersAsObject = function getListenersAsObject(evt) { + var listeners = this.getListeners(evt); + var response; + + if (listeners instanceof Array) { + response = {}; + response[evt] = listeners; + } + + return response || listeners; + }; + + function isValidListener (listener) { + if (typeof listener === 'function' || listener instanceof RegExp) { + return true + } else if (listener && typeof listener === 'object') { + return isValidListener(listener.listener) + } else { + return false + } + } + + /** + * Adds a listener function to the specified event. + * The listener will not be added if it is a duplicate. + * If the listener returns true then it will be removed after it is called. + * If you pass a regular expression as the event name then the listener will be added to all events that match it. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListener = function addListener(evt, listener) { + if (!isValidListener(listener)) { + throw new TypeError('listener must be a function'); + } + + var listeners = this.getListenersAsObject(evt); + var listenerIsWrapped = typeof listener === 'object'; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { + listeners[key].push(listenerIsWrapped ? listener : { + listener: listener, + once: false + }); + } + } + + return this; + }; + + /** + * Alias of addListener + */ + proto.on = alias('addListener'); + + /** + * Semi-alias of addListener. It will add a listener that will be + * automatically removed after its first execution. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addOnceListener = function addOnceListener(evt, listener) { + return this.addListener(evt, { + listener: listener, + once: true + }); + }; + + /** + * Alias of addOnceListener. + */ + proto.once = alias('addOnceListener'); + + /** + * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. + * You need to tell it what event names should be matched by a regex. + * + * @param {String} evt Name of the event to create. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvent = function defineEvent(evt) { + this.getListeners(evt); + return this; + }; + + /** + * Uses defineEvent to define multiple events. + * + * @param {String[]} evts An array of event names to define. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvents = function defineEvents(evts) { + for (var i = 0; i < evts.length; i += 1) { + this.defineEvent(evts[i]); + } + return this; + }; + + /** + * Removes a listener function from the specified event. + * When passed a regular expression as the event name, it will remove the listener from all events that match it. + * + * @param {String|RegExp} evt Name of the event to remove the listener from. + * @param {Function} listener Method to remove from the event. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListener = function removeListener(evt, listener) { + var listeners = this.getListenersAsObject(evt); + var index; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key)) { + index = indexOfListener(listeners[key], listener); + + if (index !== -1) { + listeners[key].splice(index, 1); + } + } + } + + return this; + }; + + /** + * Alias of removeListener + */ + proto.off = alias('removeListener'); + + /** + * Adds listeners in bulk using the manipulateListeners method. + * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. + * You can also pass it a regular expression to add the array of listeners to all events that match it. + * Yeah, this function does quite a bit. That's probably a bad thing. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListeners = function addListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(false, evt, listeners); + }; + + /** + * Removes listeners in bulk using the manipulateListeners method. + * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be removed. + * You can also pass it a regular expression to remove the listeners from all events that match it. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListeners = function removeListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(true, evt, listeners); + }; + + /** + * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. + * The first argument will determine if the listeners are removed (true) or added (false). + * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be added/removed. + * You can also pass it a regular expression to manipulate the listeners of all events that match it. + * + * @param {Boolean} remove True if you want to remove listeners, false if you want to add. + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add/remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { + var i; + var value; + var single = remove ? this.removeListener : this.addListener; + var multiple = remove ? this.removeListeners : this.addListeners; + + // If evt is an object then pass each of its properties to this method + if (typeof evt === 'object' && !(evt instanceof RegExp)) { + for (i in evt) { + if (evt.hasOwnProperty(i) && (value = evt[i])) { + // Pass the single listener straight through to the singular method + if (typeof value === 'function') { + single.call(this, i, value); + } + else { + // Otherwise pass back to the multiple function + multiple.call(this, i, value); + } + } + } + } + else { + // So evt must be a string + // And listeners must be an array of listeners + // Loop over it and pass each one to the multiple method + i = listeners.length; + while (i--) { + single.call(this, evt, listeners[i]); + } + } + + return this; + }; + + /** + * Removes all listeners from a specified event. + * If you do not specify an event then all listeners will be removed. + * That means every event will be emptied. + * You can also pass a regex to remove all events that match it. + * + * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeEvent = function removeEvent(evt) { + var type = typeof evt; + var events = this._getEvents(); + var key; + + // Remove different things depending on the state of evt + if (type === 'string') { + // Remove all listeners for the specified event + delete events[evt]; + } + else if (evt instanceof RegExp) { + // Remove all events matching the regex. + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + delete events[key]; + } + } + } + else { + // Remove all listeners in all events + delete this._events; + } + + return this; + }; + + /** + * Alias of removeEvent. + * + * Added to mirror the node API. + */ + proto.removeAllListeners = alias('removeEvent'); + + /** + * Emits an event of your choice. + * When emitted, every listener attached to that event will be executed. + * If you pass the optional argument array then those arguments will be passed to every listener upon execution. + * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. + * So they will not arrive within the array on the other side, they will be separate. + * You can also pass a regular expression to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {Array} [args] Optional array of arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emitEvent = function emitEvent(evt, args) { + var listenersMap = this.getListenersAsObject(evt); + var listeners; + var listener; + var i; + var key; + var response; + + for (key in listenersMap) { + if (listenersMap.hasOwnProperty(key)) { + listeners = listenersMap[key].slice(0); + + for (i = 0; i < listeners.length; i++) { + // If the listener returns true then it shall be removed from the event + // The function is executed either with a basic call or an apply if there is an args array + listener = listeners[i]; + + if (listener.once === true) { + this.removeListener(evt, listener.listener); + } + + response = listener.listener.apply(this, args || []); + + if (response === this._getOnceReturnValue()) { + this.removeListener(evt, listener.listener); + } + } + } + } + + return this; + }; + + /** + * Alias of emitEvent + */ + proto.trigger = alias('emitEvent'); + + /** + * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. + * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {...*} Optional additional arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emit = function emit(evt) { + var args = Array.prototype.slice.call(arguments, 1); + return this.emitEvent(evt, args); + }; + + /** + * Sets the current value to check against when executing listeners. If a + * listeners return value matches the one set here then it will be removed + * after execution. This value defaults to true. + * + * @param {*} value The new value to check for when executing listeners. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.setOnceReturnValue = function setOnceReturnValue(value) { + this._onceReturnValue = value; + return this; + }; + + /** + * Fetches the current value to check against when executing listeners. If + * the listeners return value matches this one then it should be removed + * automatically. It will return true by default. + * + * @return {*|Boolean} The current value to check for or the default, true. + * @api private + */ + proto._getOnceReturnValue = function _getOnceReturnValue() { + if (this.hasOwnProperty('_onceReturnValue')) { + return this._onceReturnValue; + } + else { + return true; + } + }; + + /** + * Fetches the events object and creates one if required. + * + * @return {Object} The events storage object. + * @api private + */ + proto._getEvents = function _getEvents() { + return this._events || (this._events = {}); + }; + + /** + * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. + * + * @return {Function} Non conflicting EventEmitter class. + */ + EventEmitter.noConflict = function noConflict() { + exports.EventEmitter = originalGlobalValue; + return EventEmitter; + }; + + // Expose the class either via AMD, CommonJS or the global object + if (typeof define === 'function' && define.amd) { + define(function () { + return EventEmitter; + }); + } + else if (typeof module === 'object' && module.exports){ + module.exports = EventEmitter; + } + else { + exports.EventEmitter = EventEmitter; + } +}(this || {})); + +},{}],16:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenVidu_1 = require("./OpenVidu/OpenVidu"); +if (window) { + window['OpenVidu'] = OpenVidu_1.OpenVidu; +} + +},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Stream_1 = require("./Stream"); +var Connection = (function () { + function Connection(session, opts) { + this.session = session; + this.disposed = false; + var msg = "'Connection' created "; + if (!!opts) { + msg += "(remote) with 'connectionId' [" + opts.id + ']'; + } + else { + msg += '(local)'; + } + console.info(msg); + this.options = opts; + if (!!opts) { + this.connectionId = opts.id; + if (opts.metadata) { + this.data = opts.metadata; + } + if (opts.streams) { + this.initRemoteStreams(opts.streams); + } + } + this.creationTime = new Date().getTime(); + } + Connection.prototype.sendIceCandidate = function (candidate) { + console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate)); + this.session.openvidu.sendRequest('onIceCandidate', { + endpointName: this.connectionId, + candidate: candidate.candidate, + sdpMid: candidate.sdpMid, + sdpMLineIndex: candidate.sdpMLineIndex + }, function (error, response) { + if (error) { + console.error('Error sending ICE candidate: ' + + JSON.stringify(error)); + } + }); + }; + Connection.prototype.initRemoteStreams = function (options) { + var _this = this; + options.forEach(function (opts) { + var streamOptions = { + id: opts.id, + connection: _this, + frameRate: opts.frameRate, + recvAudio: opts.audioActive, + recvVideo: opts.videoActive, + typeOfVideo: opts.typeOfVideo + }; + var stream = new Stream_1.Stream(_this.session, streamOptions); + _this.addStream(stream); + }); + console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); + }; + Connection.prototype.addStream = function (stream) { + stream.connection = this; + this.stream = stream; + }; + Connection.prototype.removeStream = function (streamId) { + delete this.stream; + }; + Connection.prototype.dispose = function () { + if (!!this.stream) { + delete this.stream; + } + this.disposed = true; + }; + return Connection; +}()); +exports.Connection = Connection; + +},{"./Stream":22}],18:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState"); +var LocalRecorder = (function () { + function LocalRecorder(stream) { + this.stream = stream; + this.chunks = []; + this.count = 0; + this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; + this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; + this.state = LocalRecorderState_1.LocalRecorderState.READY; + } + LocalRecorder.prototype.record = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (typeof MediaRecorder === 'undefined') { + console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); + throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); + } + if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) { + throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); + } + console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'"); + if (typeof MediaRecorder.isTypeSupported === 'function') { + var options = void 0; + if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { + options = { mimeType: 'video/webm;codecs=vp9' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { + options = { mimeType: 'video/webm;codecs=h264' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { + options = { mimeType: 'video/webm;codecs=vp8' }; + } + console.log('Using mimeType ' + options.mimeType); + _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options); + } + else { + console.warn('isTypeSupported is not supported, using default codecs for browser'); + _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream()); + } + _this.mediaRecorder.start(10); + } + catch (err) { + reject(err); + } + _this.mediaRecorder.ondataavailable = function (e) { + _this.chunks.push(e.data); + }; + _this.mediaRecorder.onerror = function (e) { + console.error('MediaRecorder error: ', e); + }; + _this.mediaRecorder.onstart = function () { + console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + }; + _this.mediaRecorder.onpause = function () { + console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onresume = function () { + console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onwarning = function (e) { + console.log('MediaRecorder warning: ' + e); + }; + _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; + resolve(); + }); + }; + LocalRecorder.prototype.stop = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before')); + } + _this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + resolve(); + }; + _this.mediaRecorder.stop(); + } + catch (e) { + reject(e); + } + }); + }; + LocalRecorder.prototype.pause = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) { + reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before')); + } + _this.mediaRecorder.pause(); + _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED; + } + catch (error) { + reject(error); + } + }); + }; + LocalRecorder.prototype.resume = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) { + throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before')); + } + _this.mediaRecorder.resume(); + _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; + } + catch (error) { + reject(error); + } + }); + }; + LocalRecorder.prototype.preview = function (parentElement) { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + this.videoPreview = document.createElement('video'); + this.videoPreview.id = this.id; + this.videoPreview.autoplay = true; + if (typeof parentElement === 'string') { + this.htmlParentElementId = parentElement; + var parentElementDom = document.getElementById(parentElement); + if (parentElementDom) { + this.videoPreview = parentElementDom.appendChild(this.videoPreview); + } + } + else { + this.htmlParentElementId = parentElement.id; + this.videoPreview = parentElement.appendChild(this.videoPreview); + } + this.videoPreview.src = this.videoPreviewSrc; + return this.videoPreview; + }; + LocalRecorder.prototype.clean = function () { + var _this = this; + var f = function () { + delete _this.blob; + _this.chunks = []; + _this.count = 0; + delete _this.mediaRecorder; + _this.state = LocalRecorderState_1.LocalRecorderState.READY; + }; + if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) { + this.stop().then(function () { return f(); }).catch(function () { return f(); }); + } + else { + f(); + } + }; + LocalRecorder.prototype.download = function () { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var a = document.createElement('a'); + a.style.display = 'none'; + document.body.appendChild(a); + var url = window.URL.createObjectURL(this.blob); + a.href = url; + a.download = this.id + '.webm'; + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + } + }; + LocalRecorder.prototype.getBlob = function () { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); + } + else { + return this.blob; + } + }; + LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var http_1 = new XMLHttpRequest(); + http_1.open('POST', endpoint, true); + if (typeof headers === 'object') { + for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { + var key = _a[_i]; + http_1.setRequestHeader(key, headers[key]); + } + } + http_1.onreadystatechange = function () { + if (http_1.readyState === 4) { + if (http_1.status.toString().charAt(0) === '2') { + resolve(http_1.responseText); + } + else { + reject(http_1.status); + } + } + }; + http_1.send(_this.blob); + } + }); + }; + LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var http_2 = new XMLHttpRequest(); + http_2.open('POST', endpoint, true); + if (typeof headers === 'object') { + for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { + var key = _a[_i]; + http_2.setRequestHeader(key, headers[key]); + } + } + var sendable = new FormData(); + sendable.append('file', _this.blob, _this.id + '.webm'); + http_2.onreadystatechange = function () { + if (http_2.readyState === 4) { + if (http_2.status.toString().charAt(0) === '2') { + resolve(http_2.responseText); + } + else { + reject(http_2.status); + } + } + }; + http_2.send(sendable); + } + }); + }; + LocalRecorder.prototype.onStopDefault = function () { + console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')'); + this.blob = new Blob(this.chunks, { type: 'video/webm' }); + this.chunks = []; + this.videoPreviewSrc = window.URL.createObjectURL(this.blob); + this.state = LocalRecorderState_1.LocalRecorderState.FINISHED; + }; + return LocalRecorder; +}()); +exports.LocalRecorder = LocalRecorder; + +},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorder_1 = require("./LocalRecorder"); +var Publisher_1 = require("./Publisher"); +var Session_1 = require("./Session"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); +var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); +var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); +var platform = require("platform"); +var OpenVidu = (function () { + function OpenVidu() { + this.secret = ''; + this.recorder = false; + this.advancedConfiguration = {}; + console.info("'OpenVidu' initialized"); + } + OpenVidu.prototype.initSession = function () { + this.session = new Session_1.Session(this); + return this.session; + }; + OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) { + var properties; + if (!!param2 && (typeof param2 !== 'function')) { + properties = param2; + properties = { + audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, + frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), + insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, + mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, + publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, + publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, + resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), + videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined + }; + } + else { + properties = { + insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, + mirror: true, + publishAudio: true, + publishVideo: true, + resolution: '640x480' + }; + } + var publisher = new Publisher_1.Publisher(targetElement, properties, this); + var completionHandler; + if (!!param2 && (typeof param2 === 'function')) { + completionHandler = param2; + } + else if (!!param3) { + completionHandler = param3; + } + publisher.initialize() + .then(function () { + if (completionHandler !== undefined) { + completionHandler(undefined); + } + publisher.emitEvent('accessAllowed', []); + }).catch(function (error) { + if (completionHandler !== undefined) { + completionHandler(error); + } + publisher.emitEvent('accessDenied', []); + }); + return publisher; + }; + OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { + var _this = this; + return new Promise(function (resolve, reject) { + var publisher; + var callback = function (error) { + if (!!error) { + reject(error); + } + else { + resolve(publisher); + } + }; + if (!!properties) { + publisher = _this.initPublisher(targetElement, properties, callback); + } + else { + publisher = _this.initPublisher(targetElement, callback); + } + }); + }; + OpenVidu.prototype.initLocalRecorder = function (stream) { + return new LocalRecorder_1.LocalRecorder(stream); + }; + OpenVidu.prototype.checkSystemRequirements = function () { + var browser = platform.name; + var version = platform.version; + if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') && + (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') && + (browser !== 'Opera') && (browser !== 'Opera Mobile') && + (browser !== 'Safari')) { + return 0; + } + else { + return 1; + } + }; + OpenVidu.prototype.getDevices = function () { + return new Promise(function (resolve, reject) { + navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { + var devices = []; + deviceInfos.forEach(function (deviceInfo) { + if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { + devices.push({ + kind: deviceInfo.kind, + deviceId: deviceInfo.deviceId, + label: deviceInfo.label + }); + } + }); + resolve(devices); + }).catch(function (error) { + console.error('Error getting devices', error); + reject(error); + }); + }); + }; + OpenVidu.prototype.getUserMedia = function (options) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.generateMediaConstraints(options) + .then(function (constraints) { + navigator.mediaDevices.getUserMedia(constraints) + .then(function (mediaStream) { + resolve(mediaStream); + }) + .catch(function (error) { + var errorName; + var errorMessage = error.toString(); + if (!(options.videoSource === 'screen')) { + errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; + } + reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + OpenVidu.prototype.enableProdMode = function () { + console.log = function () { }; + console.debug = function () { }; + console.info = function () { }; + console.warn = function () { }; + }; + OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { + this.advancedConfiguration = configuration; + }; + OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { + var _this = this; + return new Promise(function (resolve, reject) { + var audio, video; + if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) { + audio = false; + } + else if (publisherProperties.audioSource === undefined) { + audio = true; + } + else { + audio = publisherProperties.audioSource; + } + if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) { + video = false; + } + else { + video = { + height: { + ideal: 480 + }, + width: { + ideal: 640 + } + }; + } + var mediaConstraints = { + audio: audio, + video: video + }; + if (typeof mediaConstraints.audio === 'string') { + mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } }; + } + if (mediaConstraints.video) { + if (!!publisherProperties.resolution) { + var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); + var width = Number(widthAndHeight[0]); + var height = Number(widthAndHeight[1]); + mediaConstraints.video.width.ideal = width; + mediaConstraints.video.height.ideal = height; + } + if (!!publisherProperties.frameRate) { + mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate }; + } + if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') { + if (publisherProperties.videoSource === 'screen') { + if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) { + var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); + console.error(error); + reject(error); + } + else { + if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) { + screenSharing.getScreenConstraints(function (error, screenConstraints) { + if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') { + if (error === 'permission-denied' || error === 'PermissionDeniedError') { + var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); + console.error(error_1); + reject(error_1); + } + else { + var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); + screenSharing.getChromeExtensionStatus(extensionId, function (status) { + if (status === 'installed-disabled') { + var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); + console.error(error_2); + reject(error_2); + } + if (status === 'not-installed') { + var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); + console.error(error_3); + reject(error_3); + } + }); + } + } + else { + mediaConstraints.video = screenConstraints; + resolve(mediaConstraints); + } + }); + } + else { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + if (!!error) { + if (error === 'not-installed') { + var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension : + 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold'; + var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl); + console.error(error_4); + reject(error_4); + } + else if (error === 'installed-disabled') { + var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); + console.error(error_5); + reject(error_5); + } + else if (error === 'permission-denied') { + var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); + console.error(error_6); + reject(error_6); + } + } + else { + mediaConstraints.video = screenConstraints.video; + resolve(mediaConstraints); + } + }); + } + publisherProperties.videoSource = 'screen'; + } + } + else { + mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource }; + resolve(mediaConstraints); + } + } + else { + resolve(mediaConstraints); + } + } + else { + resolve(mediaConstraints); + } + }); + }; + OpenVidu.prototype.startWs = function (onConnectSucces) { + var config = { + heartbeat: 5000, + sendCloseMessage: false, + ws: { + uri: this.wsUri, + useSockJS: false, + onconnected: onConnectSucces, + ondisconnect: this.disconnectCallback.bind(this), + onreconnecting: this.reconnectingCallback.bind(this), + onreconnected: this.reconnectedCallback.bind(this) + }, + rpc: { + requestTimeout: 10000, + participantJoined: this.session.onParticipantJoined.bind(this.session), + participantPublished: this.session.onParticipantPublished.bind(this.session), + participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), + participantLeft: this.session.onParticipantLeft.bind(this.session), + participantEvicted: this.session.onParticipantEvicted.bind(this.session), + recordingStarted: this.session.onRecordingStarted.bind(this.session), + recordingStopped: this.session.onRecordingStopped.bind(this.session), + sendMessage: this.session.onNewMessage.bind(this.session), + iceCandidate: this.session.recvIceCandidate.bind(this.session), + mediaError: this.session.onMediaError.bind(this.session) + } + }; + this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); + }; + OpenVidu.prototype.closeWs = function () { + this.jsonRpcClient.close(); + }; + OpenVidu.prototype.sendRequest = function (method, params, callback) { + if (params && params instanceof Function) { + callback = params; + params = {}; + } + console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); + this.jsonRpcClient.send(method, params, callback); + }; + OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) { + var is = (!!mediaSource && + mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' && + mediaSource.id !== undefined && typeof mediaSource.id === 'string' && + mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' && + mediaSource.label !== undefined && typeof mediaSource.label === 'string' && + mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' && + mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string'); + return is; + }; + OpenVidu.prototype.getWsUri = function () { + return this.wsUri; + }; + OpenVidu.prototype.getSecret = function () { + return this.secret; + }; + OpenVidu.prototype.getRecorder = function () { + return this.recorder; + }; + OpenVidu.prototype.disconnectCallback = function () { + console.warn('Websocket connection lost'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenVidu.prototype.reconnectingCallback = function () { + console.warn('Websocket connection lost (reconnecting)'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenVidu.prototype.reconnectedCallback = function () { + console.warn('Websocket reconnected'); + }; + OpenVidu.prototype.isRoomAvailable = function () { + if (this.session !== undefined && this.session instanceof Session_1.Session) { + return true; + } + else { + console.warn('Session instance not found'); + return false; + } + }; + return OpenVidu; +}()); +exports.OpenVidu = OpenVidu; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":42,"../OpenViduInternal/ScreenSharing/Screen-Capturing":47,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":46,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Session_1 = require("./Session"); +var Stream_1 = require("./Stream"); +var StreamManager_1 = require("./StreamManager"); +var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); +var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var Publisher = (function (_super) { + __extends(Publisher, _super); + function Publisher(targEl, properties, openvidu) { + var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this; + _this.openvidu = openvidu; + _this.accessAllowed = false; + _this.isSubscribedToRemote = false; + _this.accessDenied = false; + _this.properties = properties; + _this.stream.ee.on('local-stream-destroyed-by-disconnect', function (reason) { + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + }); + return _this; + } + Publisher.prototype.publishAudio = function (value) { + this.stream.getMediaStream().getAudioTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream'); + }; + Publisher.prototype.publishVideo = function (value) { + this.stream.getMediaStream().getVideoTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream'); + }; + Publisher.prototype.subscribeToRemote = function (value) { + value = (value !== undefined) ? value : true; + this.isSubscribedToRemote = value; + this.stream.subscribeToMyRemote(value); + }; + Publisher.prototype.on = function (type, handler) { + var _this = this; + _super.prototype.on.call(this, type, handler); + if (type === 'streamCreated') { + if (!!this.stream && this.stream.isLocalStreamPublished) { + this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); + } + else { + this.stream.ee.on('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); + }); + } + } + if (type === 'remoteVideoPlaying') { + if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); + } + } + if (type === 'accessAllowed') { + if (this.accessAllowed) { + this.ee.emitEvent('accessAllowed'); + } + } + if (type === 'accessDenied') { + if (this.accessDenied) { + this.ee.emitEvent('accessDenied'); + } + } + return this; + }; + Publisher.prototype.once = function (type, handler) { + var _this = this; + _super.prototype.once.call(this, type, handler); + if (type === 'streamCreated') { + if (!!this.stream && this.stream.isLocalStreamPublished) { + this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); + } + else { + this.stream.ee.once('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); + }); + } + } + if (type === 'remoteVideoPlaying') { + if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); + } + } + if (type === 'accessAllowed') { + if (this.accessAllowed) { + this.ee.emitEvent('accessAllowed'); + } + } + if (type === 'accessDenied') { + if (this.accessDenied) { + this.ee.emitEvent('accessDenied'); + } + } + return this; + }; + Publisher.prototype.initialize = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var errorCallback = function (openViduError) { + _this.accessDenied = true; + _this.accessAllowed = false; + reject(openViduError); + }; + var successCallback = function (mediaStream) { + _this.accessAllowed = true; + _this.accessDenied = false; + if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) { + mediaStream.removeTrack(mediaStream.getAudioTracks()[0]); + mediaStream.addTrack(_this.properties.audioSource); + } + if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) { + mediaStream.removeTrack(mediaStream.getVideoTracks()[0]); + mediaStream.addTrack(_this.properties.videoSource); + } + if (!!mediaStream.getAudioTracks()[0]) { + mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; + } + if (!!mediaStream.getVideoTracks()[0]) { + mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; + } + _this.stream.setMediaStream(mediaStream); + if (!_this.stream.displayMyRemote()) { + _this.stream.updateMediaStreamInVideos(); + } + _this.stream.isLocalStreamReadyToPublish = true; + _this.stream.ee.emitEvent('stream-ready-to-publish', []); + if (!!_this.firstVideoElement) { + _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode); + } + delete _this.firstVideoElement; + resolve(); + }; + _this.openvidu.generateMediaConstraints(_this.properties) + .then(function (constraints) { + var outboundStreamOptions = { + mediaConstraints: constraints, + publisherProperties: _this.properties + }; + _this.stream.setOutboundStreamOptions(outboundStreamOptions); + var constraintsAux = {}; + var timeForDialogEvent = 1250; + if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) { + var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio); + constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1; + constraintsAux.video = constraints.video; + var startTime_1 = Date.now(); + _this.setPermissionDialogTimer(timeForDialogEvent); + navigator.mediaDevices.getUserMedia(constraintsAux) + .then(function (mediaStream) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) { + constraintsAux.audio = definedAudioConstraint_1; + constraintsAux.video = false; + startTime_1 = Date.now(); + _this.setPermissionDialogTimer(timeForDialogEvent); + navigator.mediaDevices.getUserMedia(constraintsAux) + .then(function (audioOnlyStream) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); + successCallback(mediaStream); + }) + .catch(function (error) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + var errorName, errorMessage; + switch (error.name.toLowerCase()) { + case 'notfounderror': + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'notallowederror': + errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'overconstrainederror': + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + } + }); + } + else { + successCallback(mediaStream); + } + }) + .catch(function (error) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + var errorName, errorMessage; + switch (error.name.toLowerCase()) { + case 'notfounderror': + navigator.mediaDevices.getUserMedia({ + audio: false, + video: constraints.video + }) + .then(function (mediaStream) { + mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }).catch(function (e) { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + break; + case 'notallowederror': + errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'overconstrainederror': + navigator.mediaDevices.getUserMedia({ + audio: false, + video: constraints.video + }) + .then(function (mediaStream) { + mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }).catch(function (e) { + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; + errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + break; + } + }); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'")); + } + }) + .catch(function (error) { + errorCallback(error); + }); + }); + }; + Publisher.prototype.updateSession = function (session) { + this.session = session; + this.stream.session = session; + }; + Publisher.prototype.emitEvent = function (type, eventArray) { + this.ee.emitEvent(type, eventArray); + }; + Publisher.prototype.reestablishStreamPlayingEvent = function () { + if (this.ee.getListeners('streamPlaying').length > 0) { + this.addPlayEventToFirstVideo(); + } + }; + Publisher.prototype.setPermissionDialogTimer = function (waitTime) { + var _this = this; + this.permissionDialogTimeout = setTimeout(function () { + _this.ee.emitEvent('accessDialogOpened', []); + }, waitTime); + }; + Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) { + clearTimeout(this.permissionDialogTimeout); + if ((Date.now() - startTime) > waitTime) { + this.ee.emitEvent('accessDialogClosed', []); + } + }; + return Publisher; +}(StreamManager_1.StreamManager)); +exports.Publisher = Publisher; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/VideoElementEvent":36,"./Session":21,"./Stream":22,"./StreamManager":23}],21:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Connection_1 = require("./Connection"); +var Subscriber_1 = require("./Subscriber"); +var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent"); +var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent"); +var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); +var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent"); +var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var platform = require("platform"); +var EventEmitter = require("wolfy87-eventemitter"); +var Session = (function () { + function Session(openvidu) { + this.streamManagers = []; + this.remoteStreamsCreated = {}; + this.remoteConnections = {}; + this.speakingEventsEnabled = false; + this.ee = new EventEmitter(); + this.openvidu = openvidu; + } + Session.prototype.connect = function (token, metadata) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.processToken(token); + if (_this.openvidu.checkSystemRequirements()) { + _this.options = { + sessionId: _this.sessionId, + participantId: token, + metadata: !!metadata ? _this.stringClientMetadata(metadata) : '' + }; + _this.connectAux(token).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu')); + } + }); + }; + Session.prototype.disconnect = function () { + this.leave(false, 'disconnect'); + }; + Session.prototype.subscribe = function (stream, targetElement, param3, param4) { + var properties = {}; + if (!!param3 && typeof param3 !== 'function') { + properties = { + insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, + subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, + subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true + }; + } + else { + properties = { + insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, + subscribeToAudio: true, + subscribeToVideo: true + }; + } + var completionHandler; + if (!!param3 && (typeof param3 === 'function')) { + completionHandler = param3; + } + else if (!!param4) { + completionHandler = param4; + } + console.info('Subscribing to ' + stream.connection.connectionId); + stream.subscribe() + .then(function () { + console.info('Subscribed correctly to ' + stream.connection.connectionId); + if (completionHandler !== undefined) { + completionHandler(undefined); + } + }) + .catch(function (error) { + if (completionHandler !== undefined) { + completionHandler(error); + } + }); + var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties); + if (!!subscriber.targetElement) { + stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode); + } + return subscriber; + }; + Session.prototype.subscribeAsync = function (stream, targetElement, properties) { + var _this = this; + return new Promise(function (resolve, reject) { + var subscriber; + var callback = function (error) { + if (!!error) { + reject(error); + } + else { + resolve(subscriber); + } + }; + if (!!properties) { + subscriber = _this.subscribe(stream, targetElement, properties, callback); + } + else { + subscriber = _this.subscribe(stream, targetElement, callback); + } + }); + }; + Session.prototype.unsubscribe = function (subscriber) { + var connectionId = subscriber.stream.connection.connectionId; + console.info('Unsubscribing from ' + connectionId); + this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { + if (error) { + console.error('Error unsubscribing from ' + connectionId, error); + } + else { + console.info('Unsubscribed correctly from ' + connectionId); + } + subscriber.stream.disposeWebRtcPeer(); + subscriber.stream.disposeMediaStream(); + }); + subscriber.stream.streamManager.removeAllVideos(); + }; + Session.prototype.publish = function (publisher) { + var _this = this; + return new Promise(function (resolve, reject) { + publisher.session = _this; + publisher.stream.session = _this; + if (!publisher.stream.isLocalStreamPublished) { + _this.connection.addStream(publisher.stream); + publisher.stream.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + } + else { + publisher.initialize() + .then(function () { + _this.connection.addStream(publisher.stream); + publisher.reestablishStreamPlayingEvent(); + publisher.stream.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }).catch(function (error) { + reject(error); + }); + } + }); + }; + Session.prototype.unpublish = function (publisher) { + var stream = publisher.stream; + if (!stream.connection) { + console.error('The associated Connection object of this Publisher is null', stream); + return; + } + else if (stream.connection !== this.connection) { + console.error('The associated Connection object of this Publisher is not your local Connection.' + + "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); + return; + } + else { + console.info('Unpublishing local media (' + stream.connection.connectionId + ')'); + this.openvidu.sendRequest('unpublishVideo', function (error, response) { + if (error) { + console.error(error); + } + else { + console.info('Media unpublished correctly'); + } + }); + stream.disposeWebRtcPeer(); + delete stream.connection.stream; + var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish'); + publisher.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + } + }; + Session.prototype.signal = function (signal) { + var _this = this; + return new Promise(function (resolve, reject) { + var signalMessage = {}; + if (signal.to && signal.to.length > 0) { + var connectionIds_1 = []; + signal.to.forEach(function (connection) { + connectionIds_1.push(connection.connectionId); + }); + signalMessage['to'] = connectionIds_1; + } + else { + signalMessage['to'] = []; + } + signalMessage['data'] = signal.data ? signal.data : ''; + signalMessage['type'] = signal.type ? signal.type : ''; + _this.openvidu.sendRequest('sendMessage', { + message: JSON.stringify(signalMessage) + }, function (error, response) { + if (!!error) { + reject(error); + } + else { + resolve(); + } + }); + }); + }; + Session.prototype.on = function (type, handler) { + this.ee.on(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + type + "' triggered by 'Session'"); + } + handler(event); + }); + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = true; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !str.speechEvent && str.hasAudio) { + str.enableSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.once = function (type, handler) { + this.ee.once(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + type + "' triggered by 'Session'"); + } + handler(event); + }); + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = true; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !str.speechEvent && str.hasAudio) { + str.enableOnceSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.off = function (type, handler) { + if (!handler) { + this.ee.removeAllListeners(type); + } + else { + this.ee.off(type, handler); + } + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = false; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !!str.speechEvent) { + str.disableSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.onParticipantJoined = function (response) { + var _this = this; + this.getConnection(response.id, '') + .then(function (connection) { + console.warn('Connection ' + response.id + ' already exists in connections list'); + }) + .catch(function (openViduError) { + var connection = new Connection_1.Connection(_this, response); + _this.remoteConnections[response.id] = connection; + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); + }); + }; + Session.prototype.onParticipantLeft = function (msg) { + var _this = this; + this.getRemoteConnection(msg.name, 'Remote connection ' + msg.name + " unknown when 'onParticipantLeft'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (connection) { + if (!!connection.stream) { + var stream = connection.stream; + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + delete _this.remoteStreamsCreated[stream.streamId]; + } + delete _this.remoteConnections[connection.connectionId]; + _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onParticipantPublished = function (response) { + var _this = this; + var afterConnectionFound = function (connection) { + _this.remoteConnections[connection.connectionId] = connection; + if (!_this.remoteStreamsCreated[connection.stream.streamId]) { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]); + } + _this.remoteStreamsCreated[connection.stream.streamId] = true; + }; + var connection; + this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (con) { + connection = con; + response.metadata = con.data; + connection.options = response; + connection.initRemoteStreams(response.streams); + afterConnectionFound(connection); + }) + .catch(function (openViduError) { + connection = new Connection_1.Connection(_this, response); + afterConnectionFound(connection); + }); + }; + Session.prototype.onParticipantUnpublished = function (msg) { + var _this = this; + this.getRemoteConnection(msg.name, "Remote connection '" + msg.name + "' unknown when 'onParticipantUnpublished'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (connection) { + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + var streamId = connection.stream.streamId; + delete _this.remoteStreamsCreated[streamId]; + connection.removeStream(streamId); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onParticipantEvicted = function (msg) { + }; + Session.prototype.onNewMessage = function (msg) { + var _this = this; + console.info('New signal: ' + JSON.stringify(msg)); + this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: " + + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId) + .then(function (connection) { + _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); + _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.recvIceCandidate = function (msg) { + var candidate = { + candidate: msg.candidate, + sdpMid: msg.sdpMid, + sdpMLineIndex: msg.sdpMLineIndex, + toJSON: function () { + return { candidate: msg.candidate }; + } + }; + this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) + .then(function (connection) { + var stream = connection.stream; + stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) { + console.error('Error adding candidate for ' + stream.streamId + + ' stream of endpoint ' + msg.endpointName + ': ' + error); + }); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onSessionClosed = function (msg) { + console.info('Session closed: ' + JSON.stringify(msg)); + var s = msg.room; + if (s !== undefined) { + this.ee.emitEvent('session-closed', [{ + session: s + }]); + } + else { + console.warn('Session undefined on session closed', msg); + } + }; + Session.prototype.onLostConnection = function () { + console.warn('Lost connection in Session ' + this.sessionId); + if (!!this.sessionId && !this.connection.disposed) { + this.leave(true, 'networkDisconnect'); + } + }; + Session.prototype.onMediaError = function (params) { + console.error('Media error: ' + JSON.stringify(params)); + var err = params.error; + if (err) { + this.ee.emitEvent('error-media', [{ + error: err + }]); + } + else { + console.warn('Received undefined media error. Params:', params); + } + }; + Session.prototype.onRecordingStarted = function (response) { + this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]); + }; + Session.prototype.onRecordingStopped = function (response) { + this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]); + }; + Session.prototype.emitEvent = function (type, eventArray) { + this.ee.emitEvent(type, eventArray); + }; + Session.prototype.leave = function (forced, reason) { + var _this = this; + forced = !!forced; + console.info('Leaving Session (forced=' + forced + ')'); + if (!!this.connection) { + if (!this.connection.disposed && !forced) { + this.openvidu.sendRequest('leaveRoom', function (error, response) { + if (error) { + console.error(error); + } + _this.openvidu.closeWs(); + }); + } + else { + this.openvidu.closeWs(); + } + if (!!this.connection.stream) { + this.connection.stream.disposeWebRtcPeer(); + if (this.connection.stream.isLocalStreamPublished) { + this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); + } + } + if (!this.connection.disposed) { + var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason); + this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); + sessionDisconnectEvent.callDefaultBehaviour(); + } + } + else { + console.warn('You were not connected to the session ' + this.sessionId); + } + }; + Session.prototype.connectAux = function (token) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.openvidu.startWs(function (error) { + if (!!error) { + reject(error); + } + else { + var joinParams = { + token: (!!token) ? token : '', + session: _this.sessionId, + metadata: !!_this.options.metadata ? _this.options.metadata : '', + secret: _this.openvidu.getSecret(), + recorder: _this.openvidu.getRecorder(), + }; + _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { + if (!!error) { + reject(error); + } + else { + _this.connection = new Connection_1.Connection(_this); + _this.connection.connectionId = response.id; + _this.connection.data = response.metadata; + var events_1 = { + connections: new Array(), + streams: new Array() + }; + var existingParticipants = response.value; + existingParticipants.forEach(function (participant) { + var connection = new Connection_1.Connection(_this, participant); + _this.remoteConnections[connection.connectionId] = connection; + events_1.connections.push(connection); + if (!!connection.stream) { + _this.remoteStreamsCreated[connection.stream.streamId] = true; + events_1.streams.push(connection.stream); + } + }); + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]); + events_1.connections.forEach(function (connection) { + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); + }); + events_1.streams.forEach(function (stream) { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]); + }); + resolve(); + } + }); + } + }); + }); + }; + Session.prototype.stringClientMetadata = function (metadata) { + if (typeof metadata !== 'string') { + return JSON.stringify(metadata); + } + else { + return metadata; + } + }; + Session.prototype.getConnection = function (connectionId, errorMessage) { + var _this = this; + return new Promise(function (resolve, reject) { + var connection = _this.remoteConnections[connectionId]; + if (!!connection) { + resolve(connection); + } + else { + if (_this.connection.connectionId === connectionId) { + resolve(_this.connection); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); + } + } + }); + }; + Session.prototype.getRemoteConnection = function (connectionId, errorMessage) { + var _this = this; + return new Promise(function (resolve, reject) { + var connection = _this.remoteConnections[connectionId]; + if (!!connection) { + resolve(connection); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); + } + }); + }; + Session.prototype.processToken = function (token) { + var url = new URL(token); + this.sessionId = url.searchParams.get('sessionId'); + var secret = url.searchParams.get('secret'); + var recorder = url.searchParams.get('recorder'); + var turnUsername = url.searchParams.get('turnUsername'); + var turnCredential = url.searchParams.get('turnCredential'); + var role = url.searchParams.get('role'); + if (!!secret) { + this.openvidu.secret = secret; + } + if (!!recorder) { + this.openvidu.recorder = true; + } + if (!!turnUsername && !!turnCredential) { + var stunUrl = 'stun:' + url.hostname + ':3478'; + var turnUrl1 = 'turn:' + url.hostname + ':3478'; + var turnUrl2 = turnUrl1 + '?transport=tcp'; + this.openvidu.iceServers = [ + { urls: [stunUrl] }, + { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential } + ]; + console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']'); + } + if (!!role) { + this.openvidu.role = role; + } + this.openvidu.wsUri = 'wss://' + url.host + '/openvidu'; + }; + return Session; +}()); +exports.Session = Session; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer"); +var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats"); +var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent"); +var EventEmitter = require("wolfy87-eventemitter"); +var hark = require("hark"); +var Stream = (function () { + function Stream(session, options) { + var _this = this; + this.ee = new EventEmitter(); + this.isSubscribeToRemote = false; + this.isLocalStreamReadyToPublish = false; + this.isLocalStreamPublished = false; + this.session = session; + if (options.hasOwnProperty('id')) { + this.inboundStreamOpts = options; + this.streamId = this.inboundStreamOpts.id; + this.hasAudio = this.inboundStreamOpts.recvAudio; + this.hasVideo = this.inboundStreamOpts.recvVideo; + this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo; + this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; + } + else { + this.outboundStreamOpts = options; + if (this.isSendVideo()) { + if (this.isSendScreen()) { + this.typeOfVideo = 'SCREEN'; + } + else { + this.typeOfVideo = 'CAMERA'; + } + this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; + } + else { + delete this.typeOfVideo; + } + this.hasAudio = this.isSendAudio(); + this.hasVideo = this.isSendVideo(); + } + this.ee.on('mediastream-updated', function () { + _this.streamManager.updateMediaStream(_this.mediaStream); + console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']'); + }); + } + Stream.prototype.getMediaStream = function () { + return this.mediaStream; + }; + Stream.prototype.setMediaStream = function (mediaStream) { + this.mediaStream = mediaStream; + }; + Stream.prototype.updateMediaStreamInVideos = function () { + this.ee.emitEvent('mediastream-updated'); + }; + Stream.prototype.getWebRtcPeer = function () { + return this.webRtcPeer; + }; + Stream.prototype.getRTCPeerConnection = function () { + return this.webRtcPeer.pc; + }; + Stream.prototype.subscribeToMyRemote = function (value) { + this.isSubscribeToRemote = value; + }; + Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { + this.outboundStreamOpts = outboundStreamOpts; + }; + Stream.prototype.subscribe = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.initWebRtcPeerReceive() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + Stream.prototype.publish = function () { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.isLocalStreamReadyToPublish) { + _this.initWebRtcPeerSend() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + } + else { + _this.ee.once('stream-ready-to-publish', function () { + _this.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }); + } + }); + }; + Stream.prototype.disposeWebRtcPeer = function () { + if (this.webRtcPeer) { + this.webRtcPeer.dispose(); + } + if (this.speechEvent) { + this.speechEvent.stop(); + } + this.stopWebRtcStats(); + console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed'); + }; + Stream.prototype.disposeMediaStream = function () { + if (this.mediaStream) { + this.mediaStream.getAudioTracks().forEach(function (track) { + track.stop(); + }); + this.mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + delete this.mediaStream; + } + console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed'); + }; + Stream.prototype.displayMyRemote = function () { + return this.isSubscribeToRemote; + }; + Stream.prototype.isSendAudio = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.audioSource !== null && + this.outboundStreamOpts.publisherProperties.audioSource !== false); + }; + Stream.prototype.isSendVideo = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.videoSource !== null && + this.outboundStreamOpts.publisherProperties.videoSource !== false); + }; + Stream.prototype.isSendScreen = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.videoSource === 'screen'); + }; + Stream.prototype.setSpeechEventIfNotExists = function () { + if (!this.speechEvent) { + var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}; + harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50; + harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50; + this.speechEvent = hark(this.mediaStream, harkOptions); + } + }; + Stream.prototype.enableSpeakingEvents = function () { + var _this = this; + this.setSpeechEventIfNotExists(); + this.speechEvent.on('speaking', function () { + _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); + }); + this.speechEvent.on('stopped_speaking', function () { + _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); + }); + }; + Stream.prototype.enableOnceSpeakingEvents = function () { + var _this = this; + this.setSpeechEventIfNotExists(); + this.speechEvent.on('speaking', function () { + _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); + _this.disableSpeakingEvents(); + }); + this.speechEvent.on('stopped_speaking', function () { + _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); + _this.disableSpeakingEvents(); + }); + }; + Stream.prototype.disableSpeakingEvents = function () { + this.speechEvent.stop(); + this.speechEvent = undefined; + }; + Stream.prototype.isLocal = function () { + return (!this.inboundStreamOpts && !!this.outboundStreamOpts); + }; + Stream.prototype.getSelectedIceCandidate = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.webRtcStats.getSelectedIceCandidateInfo() + .then(function (report) { return resolve(report); }) + .catch(function (error) { return reject(error); }); + }); + }; + Stream.prototype.getRemoteIceCandidateList = function () { + return this.webRtcPeer.remoteCandidatesQueue; + }; + Stream.prototype.getLocalIceCandidateList = function () { + return this.webRtcPeer.localCandidatesQueue; + }; + Stream.prototype.initWebRtcPeerSend = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var userMediaConstraints = { + audio: _this.isSendAudio(), + video: _this.isSendVideo() + }; + var options = { + mediaStream: _this.mediaStream, + mediaConstraints: userMediaConstraints, + onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), + iceServers: _this.getIceServersConf(), + simulcast: false + }; + var successCallback = function (sdpOfferParam) { + console.debug('Sending SDP offer to publish as ' + + _this.streamId, sdpOfferParam); + _this.session.openvidu.sendRequest('publishVideo', { + sdpOffer: sdpOfferParam, + doLoopback: _this.displayMyRemote() || false, + audioActive: _this.isSendAudio(), + videoActive: _this.isSendVideo(), + typeOfVideo: ((_this.isSendVideo()) ? (_this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''), + frameRate: !!_this.frameRate ? _this.frameRate : -1 + }, function (error, response) { + if (error) { + reject('Error on publishVideo: ' + JSON.stringify(error)); + } + else { + _this.webRtcPeer.processAnswer(response.sdpAnswer) + .then(function () { + _this.streamId = response.id; + _this.isLocalStreamPublished = true; + if (_this.displayMyRemote()) { + _this.remotePeerSuccesfullyEstablished(); + } + _this.ee.emitEvent('stream-created-by-publisher'); + _this.initWebRtcStats(); + resolve(); + }) + .catch(function (error) { + reject(error); + }); + console.info("'Publisher' successfully published to session"); + } + }); + }; + if (_this.displayMyRemote()) { + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options); + } + else { + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options); + } + _this.webRtcPeer.generateOffer().then(function (offer) { + successCallback(offer); + }).catch(function (error) { + reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error))); + }); + }); + }; + Stream.prototype.initWebRtcPeerReceive = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var offerConstraints = { + audio: _this.inboundStreamOpts.recvAudio, + video: _this.inboundStreamOpts.recvVideo + }; + console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); + var options = { + onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), + mediaConstraints: offerConstraints, + iceServers: _this.getIceServersConf(), + simulcast: false + }; + var successCallback = function (sdpOfferParam) { + console.debug('Sending SDP offer to subscribe to ' + + _this.streamId, sdpOfferParam); + _this.session.openvidu.sendRequest('receiveVideoFrom', { + sender: _this.streamId, + sdpOffer: sdpOfferParam + }, function (error, response) { + if (error) { + reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error))); + } + else { + _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () { + _this.remotePeerSuccesfullyEstablished(); + _this.initWebRtcStats(); + resolve(); + }).catch(function (error) { + reject(error); + }); + } + }); + }; + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options); + _this.webRtcPeer.generateOffer() + .then(function (offer) { + successCallback(offer); + }) + .catch(function (error) { + reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error))); + }); + }); + }; + Stream.prototype.remotePeerSuccesfullyEstablished = function () { + this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0]; + console.debug('Peer remote stream', this.mediaStream); + if (!!this.mediaStream) { + this.ee.emitEvent('mediastream-updated'); + if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) { + this.enableSpeakingEvents(); + } + } + }; + Stream.prototype.initWebRtcStats = function () { + this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); + this.webRtcStats.initWebRtcStats(); + }; + Stream.prototype.stopWebRtcStats = function () { + if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { + this.webRtcStats.stopWebRtcStats(); + } + }; + Stream.prototype.getIceServersConf = function () { + var returnValue; + if (!!this.session.openvidu.advancedConfiguration.iceServers) { + returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ? + undefined : + this.session.openvidu.advancedConfiguration.iceServers; + } + else if (this.session.openvidu.iceServers) { + returnValue = this.session.openvidu.iceServers; + } + else { + returnValue = undefined; + } + return returnValue; + }; + return Stream; +}()); +exports.Stream = Stream; + +},{"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":48,"../OpenViduInternal/WebRtcStats/WebRtcStats":49,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); +var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var EventEmitter = require("wolfy87-eventemitter"); +var StreamManager = (function () { + function StreamManager(stream, targetElement) { + var _this = this; + this.videos = []; + this.lazyLaunchVideoElementCreatedEvent = false; + this.ee = new EventEmitter(); + this.stream = stream; + this.stream.streamManager = this; + this.remote = !this.stream.isLocal(); + if (!!targetElement) { + var targEl = void 0; + if (typeof targetElement === 'string') { + targEl = document.getElementById(targetElement); + } + else if (targetElement instanceof HTMLElement) { + targEl = targetElement; + } + if (!!targEl) { + this.firstVideoElement = { + targetElement: targEl, + video: document.createElement('video'), + id: '' + }; + this.targetElement = targEl; + this.element = targEl; + } + } + this.canPlayListener = function () { + if (_this.stream.isLocal()) { + if (!_this.stream.displayMyRemote()) { + console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); + } + else { + console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]); + } + } + else { + console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); + } + _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]); + }; + } + StreamManager.prototype.on = function (type, handler) { + this.ee.on(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered", event); + } + else { + console.info("Event '" + type + "' triggered"); + } + handler(event); + }); + if (type === 'videoElementCreated') { + if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); + this.lazyLaunchVideoElementCreatedEvent = false; + } + } + if (type === 'streamPlaying' || type === 'videoPlaying') { + if (this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); + this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); + } + } + return this; + }; + StreamManager.prototype.once = function (type, handler) { + this.ee.once(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered once", event); + } + else { + console.info("Event '" + type + "' triggered once"); + } + handler(event); + }); + if (type === 'videoElementCreated') { + if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); + } + } + if (type === 'streamPlaying' || type === 'videoPlaying') { + if (this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); + this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); + } + } + return this; + }; + StreamManager.prototype.off = function (type, handler) { + if (!handler) { + this.ee.removeAllListeners(type); + } + else { + this.ee.off(type, handler); + } + return this; + }; + StreamManager.prototype.addVideoElement = function (video) { + this.initializeVideoProperties(video); + for (var _i = 0, _a = this.videos; _i < _a.length; _i++) { + var v = _a[_i]; + if (v.video === video) { + return 0; + } + } + var returnNumber = 1; + this.initializeVideoProperties(video); + for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) { + var streamManager = _c[_b]; + if (streamManager.disassociateVideo(video)) { + returnNumber = -1; + break; + } + } + this.stream.session.streamManagers.forEach(function (streamManager) { + streamManager.disassociateVideo(video); + }); + this.pushNewStreamManagerVideo({ + video: video, + id: video.id + }); + console.info('New video element associated to ', this); + return returnNumber; + }; + StreamManager.prototype.createVideoElement = function (targetElement, insertMode) { + var targEl; + if (typeof targetElement === 'string') { + targEl = document.getElementById(targEl); + if (!targEl) { + throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); + } + } + else if (targetElement instanceof HTMLElement) { + targEl = targetElement; + } + else { + throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); + } + var video = document.createElement('video'); + this.initializeVideoProperties(video); + var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; + switch (insMode) { + case VideoInsertMode_1.VideoInsertMode.AFTER: + targEl.parentNode.insertBefore(video, targEl.nextSibling); + break; + case VideoInsertMode_1.VideoInsertMode.APPEND: + targEl.appendChild(video); + break; + case VideoInsertMode_1.VideoInsertMode.BEFORE: + targEl.parentNode.insertBefore(video, targEl); + break; + case VideoInsertMode_1.VideoInsertMode.PREPEND: + targEl.insertBefore(video, targEl.childNodes[0]); + break; + case VideoInsertMode_1.VideoInsertMode.REPLACE: + targEl.parentNode.replaceChild(video, targEl); + break; + default: + insMode = VideoInsertMode_1.VideoInsertMode.APPEND; + targEl.appendChild(video); + break; + } + var v = { + targetElement: targEl, + video: video, + insertMode: insMode, + id: video.id + }; + this.pushNewStreamManagerVideo(v); + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]); + this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement; + return video; + }; + StreamManager.prototype.initializeVideoProperties = function (video) { + video.srcObject = this.stream.getMediaStream(); + video.autoplay = true; + video.controls = false; + if (!video.id) { + video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId; + if (!this.id && !!this.targetElement) { + this.id = video.id; + } + } + if (!this.remote && !this.stream.displayMyRemote()) { + video.muted = true; + if (this.stream.outboundStreamOpts.publisherProperties.mirror) { + this.mirrorVideo(video); + } + } + }; + StreamManager.prototype.removeAllVideos = function () { + var _this = this; + for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) { + if (this.stream.session.streamManagers[i] === this) { + this.stream.session.streamManagers.splice(i, 1); + } + } + this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) { + streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener); + if (!!streamManagerVideo.targetElement) { + streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video); + _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]); + _this.videos.splice(videos.length - 1 - index, 1); + } + else { + streamManagerVideo.video.srcObject = null; + } + }); + }; + StreamManager.prototype.disassociateVideo = function (video) { + var disassociated = false; + for (var i = 0; i < this.videos.length; i++) { + if (this.videos[i].video === video) { + this.videos.splice(i, 1); + disassociated = true; + console.info('Video element disassociated from ', this); + break; + } + } + return disassociated; + }; + StreamManager.prototype.addPlayEventToFirstVideo = function () { + if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) { + this.videos[0].video.addEventListener('canplay', this.canPlayListener); + } + }; + StreamManager.prototype.updateMediaStream = function (mediaStream) { + this.videos.forEach(function (streamManagerVideo) { + streamManagerVideo.video.srcObject = mediaStream; + }); + }; + StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) { + this.videos.push(streamManagerVideo); + this.addPlayEventToFirstVideo(); + if (this.stream.session.streamManagers.indexOf(this) === -1) { + this.stream.session.streamManagers.push(this); + } + }; + StreamManager.prototype.mirrorVideo = function (video) { + video.style.transform = 'rotateY(180deg)'; + video.style.webkitTransform = 'rotateY(180deg)'; + }; + return StreamManager; +}()); +exports.StreamManager = StreamManager; + +},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":36,"wolfy87-eventemitter":15}],24:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var StreamManager_1 = require("./StreamManager"); +var Subscriber = (function (_super) { + __extends(Subscriber, _super); + function Subscriber(stream, targEl, properties) { + var _this = _super.call(this, stream, targEl) || this; + _this.element = _this.targetElement; + _this.stream = stream; + _this.properties = properties; + return _this; + } + Subscriber.prototype.subscribeToAudio = function (value) { + this.stream.getMediaStream().getAudioTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream'); + return this; + }; + Subscriber.prototype.subscribeToVideo = function (value) { + this.stream.getMediaStream().getVideoTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream'); + return this; + }; + return Subscriber; +}(StreamManager_1.StreamManager)); +exports.Subscriber = Subscriber; + +},{"./StreamManager":23}],25:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorderState; +(function (LocalRecorderState) { + LocalRecorderState["READY"] = "READY"; + LocalRecorderState["RECORDING"] = "RECORDING"; + LocalRecorderState["PAUSED"] = "PAUSED"; + LocalRecorderState["FINISHED"] = "FINISHED"; +})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {})); + +},{}],26:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduErrorName; +(function (OpenViduErrorName) { + OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; + OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED"; + OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; + OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; + OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; + OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED"; + OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; + OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; + OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; + OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; + OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; + OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED"; + OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; +})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); +var OpenViduError = (function () { + function OpenViduError(name, message) { + this.name = name; + this.message = message; + } + return OpenViduError; +}()); +exports.OpenViduError = OpenViduError; + +},{}],27:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var VideoInsertMode; +(function (VideoInsertMode) { + VideoInsertMode["AFTER"] = "AFTER"; + VideoInsertMode["APPEND"] = "APPEND"; + VideoInsertMode["BEFORE"] = "BEFORE"; + VideoInsertMode["PREPEND"] = "PREPEND"; + VideoInsertMode["REPLACE"] = "REPLACE"; +})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); + +},{}],28:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var ConnectionEvent = (function (_super) { + __extends(ConnectionEvent, _super); + function ConnectionEvent(cancelable, target, type, connection, reason) { + var _this = _super.call(this, cancelable, target, type) || this; + _this.connection = connection; + _this.reason = reason; + return _this; + } + ConnectionEvent.prototype.callDefaultBehaviour = function () { }; + return ConnectionEvent; +}(Event_1.Event)); +exports.ConnectionEvent = ConnectionEvent; + +},{"./Event":29}],29:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Event = (function () { + function Event(cancelable, target, type) { + this.hasBeenPrevented = false; + this.cancelable = cancelable; + this.target = target; + this.type = type; + } + Event.prototype.isDefaultPrevented = function () { + return this.hasBeenPrevented; + }; + Event.prototype.preventDefault = function () { + this.callDefaultBehaviour = function () { }; + this.hasBeenPrevented = true; + }; + return Event; +}()); +exports.Event = Event; + +},{}],30:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var PublisherSpeakingEvent = (function (_super) { + __extends(PublisherSpeakingEvent, _super); + function PublisherSpeakingEvent(target, type, connection, streamId) { + var _this = _super.call(this, false, target, type) || this; + _this.type = type; + _this.connection = connection; + _this.streamId = streamId; + return _this; + } + PublisherSpeakingEvent.prototype.callDefaultBehaviour = function () { }; + return PublisherSpeakingEvent; +}(Event_1.Event)); +exports.PublisherSpeakingEvent = PublisherSpeakingEvent; + +},{"./Event":29}],31:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var RecordingEvent = (function (_super) { + __extends(RecordingEvent, _super); + function RecordingEvent(target, type, id, name) { + var _this = _super.call(this, false, target, type) || this; + _this.id = id; + if (name !== id) { + _this.name = name; + } + return _this; + } + RecordingEvent.prototype.callDefaultBehaviour = function () { }; + return RecordingEvent; +}(Event_1.Event)); +exports.RecordingEvent = RecordingEvent; + +},{"./Event":29}],32:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var SessionDisconnectedEvent = (function (_super) { + __extends(SessionDisconnectedEvent, _super); + function SessionDisconnectedEvent(target, reason) { + var _this = _super.call(this, true, target, 'sessionDisconnected') || this; + _this.reason = reason; + return _this; + } + SessionDisconnectedEvent.prototype.callDefaultBehaviour = function () { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); + var session = this.target; + for (var connectionId in session.remoteConnections) { + if (!!session.remoteConnections[connectionId].stream) { + session.remoteConnections[connectionId].stream.disposeWebRtcPeer(); + session.remoteConnections[connectionId].stream.disposeMediaStream(); + if (session.remoteConnections[connectionId].stream.streamManager) { + session.remoteConnections[connectionId].stream.streamManager.removeAllVideos(); + } + delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId]; + session.remoteConnections[connectionId].dispose(); + } + delete session.remoteConnections[connectionId]; + } + }; + return SessionDisconnectedEvent; +}(Event_1.Event)); +exports.SessionDisconnectedEvent = SessionDisconnectedEvent; + +},{"./Event":29}],33:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var SignalEvent = (function (_super) { + __extends(SignalEvent, _super); + function SignalEvent(target, type, data, from) { + var _this = _super.call(this, false, target, type) || this; + _this.type = type; + _this.data = data; + _this.from = from; + return _this; + } + SignalEvent.prototype.callDefaultBehaviour = function () { }; + return SignalEvent; +}(Event_1.Event)); +exports.SignalEvent = SignalEvent; + +},{"./Event":29}],34:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var Publisher_1 = require("../../OpenVidu/Publisher"); +var Session_1 = require("../../OpenVidu/Session"); +var StreamEvent = (function (_super) { + __extends(StreamEvent, _super); + function StreamEvent(cancelable, target, type, stream, reason) { + var _this = _super.call(this, cancelable, target, type) || this; + _this.stream = stream; + _this.reason = reason; + return _this; + } + StreamEvent.prototype.callDefaultBehaviour = function () { + if (this.type === 'streamDestroyed') { + if (this.target instanceof Session_1.Session) { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); + this.stream.disposeWebRtcPeer(); + } + else if (this.target instanceof Publisher_1.Publisher) { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Publisher'"); + this.stream.isLocalStreamReadyToPublish = false; + } + this.stream.disposeMediaStream(); + if (this.stream.streamManager) + this.stream.streamManager.removeAllVideos(); + delete this.stream.session.remoteStreamsCreated[this.stream.streamId]; + var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId]; + if (!!remoteConnection && !!remoteConnection.options) { + var streamOptionsServer = remoteConnection.options.streams; + for (var i = streamOptionsServer.length - 1; i >= 0; --i) { + if (streamOptionsServer[i].id === this.stream.streamId) { + streamOptionsServer.splice(i, 1); + } + } + } + } + }; + return StreamEvent; +}(Event_1.Event)); +exports.StreamEvent = StreamEvent; + +},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var StreamManagerEvent = (function (_super) { + __extends(StreamManagerEvent, _super); + function StreamManagerEvent(target) { + return _super.call(this, false, target, 'streamPlaying') || this; + } + StreamManagerEvent.prototype.callDefaultBehaviour = function () { }; + return StreamManagerEvent; +}(Event_1.Event)); +exports.StreamManagerEvent = StreamManagerEvent; + +},{"./Event":29}],36:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var VideoElementEvent = (function (_super) { + __extends(VideoElementEvent, _super); + function VideoElementEvent(element, target, type) { + var _this = _super.call(this, false, target, type) || this; + _this.element = element; + return _this; + } + VideoElementEvent.prototype.callDefaultBehaviour = function () { }; + return VideoElementEvent; +}(Event_1.Event)); +exports.VideoElementEvent = VideoElementEvent; + +},{"./Event":29}],37:[function(require,module,exports){ +function Mapper() { + var sources = {}; + this.forEach = function (callback) { + for (var key in sources) { + var source = sources[key]; + for (var key2 in source) + callback(source[key2]); + } + ; + }; + this.get = function (id, source) { + var ids = sources[source]; + if (ids == undefined) + return undefined; + return ids[id]; + }; + this.remove = function (id, source) { + var ids = sources[source]; + if (ids == undefined) + return; + delete ids[id]; + for (var i in ids) { + return false; + } + delete sources[source]; + }; + this.set = function (value, id, source) { + if (value == undefined) + return this.remove(id, source); + var ids = sources[source]; + if (ids == undefined) + sources[source] = ids = {}; + ids[id] = value; + }; +} +; +Mapper.prototype.pop = function (id, source) { + var value = this.get(id, source); + if (value == undefined) + return undefined; + this.remove(id, source); + return value; +}; +module.exports = Mapper; + +},{}],38:[function(require,module,exports){ +var JsonRpcClient = require('./jsonrpcclient'); +exports.JsonRpcClient = JsonRpcClient; + +},{"./jsonrpcclient":39}],39:[function(require,module,exports){ +var RpcBuilder = require('../'); +var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); +Date.now = Date.now || function () { + return +new Date; +}; +var PING_INTERVAL = 5000; +var RECONNECTING = 'RECONNECTING'; +var CONNECTED = 'CONNECTED'; +var DISCONNECTED = 'DISCONNECTED'; +var Logger = console; +function JsonRpcClient(configuration) { + var self = this; + var wsConfig = configuration.ws; + var notReconnectIfNumLessThan = -1; + var pingNextNum = 0; + var enabledPings = true; + var pingPongStarted = false; + var pingInterval; + var status = DISCONNECTED; + var onreconnecting = wsConfig.onreconnecting; + var onreconnected = wsConfig.onreconnected; + var onconnected = wsConfig.onconnected; + var onerror = wsConfig.onerror; + configuration.rpc.pull = function (params, request) { + request.reply(null, "push"); + }; + wsConfig.onreconnecting = function () { + Logger.debug("--------- ONRECONNECTING -----------"); + if (status === RECONNECTING) { + Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it"); + return; + } + status = RECONNECTING; + if (onreconnecting) { + onreconnecting(); + } + }; + wsConfig.onreconnected = function () { + Logger.debug("--------- ONRECONNECTED -----------"); + if (status === CONNECTED) { + Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it"); + return; + } + status = CONNECTED; + enabledPings = true; + updateNotReconnectIfLessThan(); + usePing(); + if (onreconnected) { + onreconnected(); + } + }; + wsConfig.onconnected = function () { + Logger.debug("--------- ONCONNECTED -----------"); + if (status === CONNECTED) { + Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it"); + return; + } + status = CONNECTED; + enabledPings = true; + usePing(); + if (onconnected) { + onconnected(); + } + }; + wsConfig.onerror = function (error) { + Logger.debug("--------- ONERROR -----------"); + status = DISCONNECTED; + if (onerror) { + onerror(error); + } + }; + var ws = new WebSocketWithReconnection(wsConfig); + Logger.debug('Connecting websocket to URI: ' + wsConfig.uri); + var rpcBuilderOptions = { + request_timeout: configuration.rpc.requestTimeout, + ping_request_timeout: configuration.rpc.heartbeatRequestTimeout + }; + var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) { + Logger.debug('Received request: ' + JSON.stringify(request)); + try { + var func = configuration.rpc[request.method]; + if (func === undefined) { + Logger.error("Method " + request.method + " not registered in client"); + } + else { + func(request.params, request); + } + } + catch (err) { + Logger.error('Exception processing request: ' + JSON.stringify(request)); + Logger.error(err); + } + }); + this.send = function (method, params, callback) { + if (method !== 'ping') { + Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); + } + var requestTime = Date.now(); + rpc.encode(method, params, function (error, result) { + if (error) { + try { + Logger.error("ERROR:" + error.message + " in Request: method:" + + method + " params:" + JSON.stringify(params) + " request:" + + error.request); + if (error.data) { + Logger.error("ERROR DATA:" + JSON.stringify(error.data)); + } + } + catch (e) { } + error.requestTime = requestTime; + } + if (callback) { + if (result != undefined && result.value !== 'pong') { + Logger.debug('Response: ' + JSON.stringify(result)); + } + callback(error, result); + } + }); + }; + function updateNotReconnectIfLessThan() { + Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' + + notReconnectIfNumLessThan + ')'); + notReconnectIfNumLessThan = pingNextNum; + } + function sendPing() { + if (enabledPings) { + var params = null; + if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) { + params = { + interval: configuration.heartbeat || PING_INTERVAL + }; + } + pingNextNum++; + self.send('ping', params, (function (pingNum) { + return function (error, result) { + if (error) { + Logger.debug("Error in ping request #" + pingNum + " (" + + error.message + ")"); + if (pingNum > notReconnectIfNumLessThan) { + enabledPings = false; + updateNotReconnectIfLessThan(); + Logger.debug("Server did not respond to ping message #" + + pingNum + ". Reconnecting... "); + ws.reconnectWs(); + } + } + }; + })(pingNextNum)); + } + else { + Logger.debug("Trying to send ping, but ping is not enabled"); + } + } + function usePing() { + if (!pingPongStarted) { + Logger.debug("Starting ping (if configured)"); + pingPongStarted = true; + if (configuration.heartbeat != undefined) { + pingInterval = setInterval(sendPing, configuration.heartbeat); + sendPing(); + } + } + } + this.close = function () { + Logger.debug("Closing jsonRpcClient explicitly by client"); + if (pingInterval != undefined) { + Logger.debug("Clearing ping interval"); + clearInterval(pingInterval); + } + pingPongStarted = false; + enabledPings = false; + if (configuration.sendCloseMessage) { + Logger.debug("Sending close message"); + this.send('closeSession', null, function (error, result) { + if (error) { + Logger.error("Error sending close message: " + JSON.stringify(error)); + } + ws.close(); + }); + } + else { + ws.close(); + } + }; + this.forceClose = function (millis) { + ws.forceClose(millis); + }; + this.reconnect = function () { + ws.reconnectWs(); + }; +} +module.exports = JsonRpcClient; + +},{"../":42,"./transports/webSocketWithReconnection":41}],40:[function(require,module,exports){ +var WebSocketWithReconnection = require('./webSocketWithReconnection'); +exports.WebSocketWithReconnection = WebSocketWithReconnection; + +},{"./webSocketWithReconnection":41}],41:[function(require,module,exports){ +(function (global){ +"use strict"; +var BrowserWebSocket = global.WebSocket || global.MozWebSocket; +var Logger = console; +var MAX_RETRIES = 2000; +var RETRY_TIME_MS = 3000; +var CONNECTING = 0; +var OPEN = 1; +var CLOSING = 2; +var CLOSED = 3; +function WebSocketWithReconnection(config) { + var closing = false; + var registerMessageHandler; + var wsUri = config.uri; + var useSockJS = config.useSockJS; + var reconnecting = false; + var forcingDisconnection = false; + var ws; + if (useSockJS) { + ws = new SockJS(wsUri); + } + else { + ws = new WebSocket(wsUri); + } + ws.onopen = function () { + logConnected(ws, wsUri); + if (config.onconnected) { + config.onconnected(); + } + }; + ws.onerror = function (error) { + Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error); + if (config.onerror) { + config.onerror(error); + } + }; + function logConnected(ws, wsUri) { + try { + Logger.debug("WebSocket connected to " + wsUri); + } + catch (e) { + Logger.error(e); + } + } + var reconnectionOnClose = function () { + if (ws.readyState === CLOSED) { + if (closing) { + Logger.debug("Connection closed by user"); + } + else { + Logger.debug("Connection closed unexpectecly. Reconnecting..."); + reconnectToSameUri(MAX_RETRIES, 1); + } + } + else { + Logger.debug("Close callback from previous websocket. Ignoring it"); + } + }; + ws.onclose = reconnectionOnClose; + function reconnectToSameUri(maxRetries, numRetries) { + Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); + if (numRetries === 1) { + if (reconnecting) { + Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); + return; + } + else { + reconnecting = true; + } + if (config.onreconnecting) { + config.onreconnecting(); + } + } + if (forcingDisconnection) { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + else { + if (config.newWsUriOnReconnection) { + config.newWsUriOnReconnection(function (error, newWsUri) { + if (error) { + Logger.debug(error); + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + else { + reconnectToNewUri(maxRetries, numRetries, newWsUri); + } + }); + } + else { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + } + } + function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { + Logger.debug("Reconnection attempt #" + numRetries); + ws.close(); + wsUri = reconnectWsUri || wsUri; + var newWs; + if (useSockJS) { + newWs = new SockJS(wsUri); + } + else { + newWs = new WebSocket(wsUri); + } + newWs.onopen = function () { + Logger.debug("Reconnected after " + numRetries + " attempts..."); + logConnected(newWs, wsUri); + reconnecting = false; + registerMessageHandler(); + if (config.onreconnected()) { + config.onreconnected(); + } + newWs.onclose = reconnectionOnClose; + }; + var onErrorOrClose = function (error) { + Logger.warn("Reconnection error: ", error); + if (numRetries === maxRetries) { + if (config.ondisconnect) { + config.ondisconnect(); + } + } + else { + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + }; + newWs.onerror = onErrorOrClose; + ws = newWs; + } + this.close = function () { + closing = true; + ws.close(); + }; + this.forceClose = function (millis) { + Logger.debug("Testing: Force WebSocket close"); + if (millis) { + Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); + var goodWsUri = wsUri; + wsUri = "wss://21.234.12.34.4:443/"; + forcingDisconnection = true; + setTimeout(function () { + Logger.debug("Testing: Recover good wsUri " + goodWsUri); + wsUri = goodWsUri; + forcingDisconnection = false; + }, millis); + } + ws.close(); + }; + this.reconnectWs = function () { + Logger.debug("reconnectWs"); + reconnectToSameUri(MAX_RETRIES, 1, wsUri); + }; + this.send = function (message) { + ws.send(message); + }; + this.addEventListener = function (type, callback) { + registerMessageHandler = function () { + ws.addEventListener(type, callback); + }; + registerMessageHandler(); + }; +} +module.exports = WebSocketWithReconnection; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],42:[function(require,module,exports){ +var defineProperty_IE8 = false; +if (Object.defineProperty) { + try { + Object.defineProperty({}, "x", {}); + } + catch (e) { + defineProperty_IE8 = true; + } +} +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== 'function') { + throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); + }; + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + return fBound; + }; +} +var EventEmitter = require('events').EventEmitter; +var inherits = require('inherits'); +var packers = require('./packers'); +var Mapper = require('./Mapper'); +var BASE_TIMEOUT = 5000; +function unifyResponseMethods(responseMethods) { + if (!responseMethods) + return {}; + for (var key in responseMethods) { + var value = responseMethods[key]; + if (typeof value == 'string') + responseMethods[key] = + { + response: value + }; + } + ; + return responseMethods; +} +; +function unifyTransport(transport) { + if (!transport) + return; + if (transport instanceof Function) + return { send: transport }; + if (transport.send instanceof Function) + return transport; + if (transport.postMessage instanceof Function) { + transport.send = transport.postMessage; + return transport; + } + if (transport.write instanceof Function) { + transport.send = transport.write; + return transport; + } + if (transport.onmessage !== undefined) + return; + if (transport.pause instanceof Function) + return; + throw new SyntaxError("Transport is not a function nor a valid object"); +} +; +function RpcNotification(method, params) { + if (defineProperty_IE8) { + this.method = method; + this.params = params; + } + else { + Object.defineProperty(this, 'method', { value: method, enumerable: true }); + Object.defineProperty(this, 'params', { value: params, enumerable: true }); + } +} +; +function RpcBuilder(packer, options, transport, onRequest) { + var self = this; + if (!packer) + throw new SyntaxError('Packer is not defined'); + if (!packer.pack || !packer.unpack) + throw new SyntaxError('Packer is invalid'); + var responseMethods = unifyResponseMethods(packer.responseMethods); + if (options instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after onRequest"); + onRequest = options; + transport = undefined; + options = undefined; + } + ; + if (options && options.send instanceof Function) { + if (transport && !(transport instanceof Function)) + throw new SyntaxError("Only a function can be after transport"); + onRequest = transport; + transport = options; + options = undefined; + } + ; + if (transport instanceof Function) { + if (onRequest != undefined) + throw new SyntaxError("There can't be parameters after onRequest"); + onRequest = transport; + transport = undefined; + } + ; + if (transport && transport.send instanceof Function) + if (onRequest && !(onRequest instanceof Function)) + throw new SyntaxError("Only a function can be after transport"); + options = options || {}; + EventEmitter.call(this); + if (onRequest) + this.on('request', onRequest); + if (defineProperty_IE8) + this.peerID = options.peerID; + else + Object.defineProperty(this, 'peerID', { value: options.peerID }); + var max_retries = options.max_retries || 0; + function transportMessage(event) { + self.decode(event.data || event); + } + ; + this.getTransport = function () { + return transport; + }; + this.setTransport = function (value) { + if (transport) { + if (transport.removeEventListener) + transport.removeEventListener('message', transportMessage); + else if (transport.removeListener) + transport.removeListener('data', transportMessage); + } + ; + if (value) { + if (value.addEventListener) + value.addEventListener('message', transportMessage); + else if (value.addListener) + value.addListener('data', transportMessage); + } + ; + transport = unifyTransport(value); + }; + if (!defineProperty_IE8) + Object.defineProperty(this, 'transport', { + get: this.getTransport.bind(this), + set: this.setTransport.bind(this) + }); + this.setTransport(transport); + var request_timeout = options.request_timeout || BASE_TIMEOUT; + var ping_request_timeout = options.ping_request_timeout || request_timeout; + var response_timeout = options.response_timeout || BASE_TIMEOUT; + var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT; + var requestID = 0; + var requests = new Mapper(); + var responses = new Mapper(); + var processedResponses = new Mapper(); + var message2Key = {}; + function storeResponse(message, id, dest) { + var response = { + message: message, + timeout: setTimeout(function () { + responses.remove(id, dest); + }, response_timeout) + }; + responses.set(response, id, dest); + } + ; + function storeProcessedResponse(ack, from) { + var timeout = setTimeout(function () { + processedResponses.remove(ack, from); + }, duplicates_timeout); + processedResponses.set(timeout, ack, from); + } + ; + function RpcRequest(method, params, id, from, transport) { + RpcNotification.call(this, method, params); + this.getTransport = function () { + return transport; + }; + this.setTransport = function (value) { + transport = unifyTransport(value); + }; + if (!defineProperty_IE8) + Object.defineProperty(this, 'transport', { + get: this.getTransport.bind(this), + set: this.setTransport.bind(this) + }); + var response = responses.get(id, from); + if (!(transport || self.getTransport())) { + if (defineProperty_IE8) + this.duplicated = Boolean(response); + else + Object.defineProperty(this, 'duplicated', { + value: Boolean(response) + }); + } + var responseMethod = responseMethods[method]; + this.pack = packer.pack.bind(packer, this, id); + this.reply = function (error, result, transport) { + if (error instanceof Function || error && error.send instanceof Function) { + if (result != undefined) + throw new SyntaxError("There can't be parameters after callback"); + transport = error; + result = null; + error = undefined; + } + else if (result instanceof Function + || result && result.send instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after callback"); + transport = result; + result = null; + } + ; + transport = unifyTransport(transport); + if (response) + clearTimeout(response.timeout); + if (from != undefined) { + if (error) + error.dest = from; + if (result) + result.dest = from; + } + ; + var message; + if (error || result != undefined) { + if (self.peerID != undefined) { + if (error) + error.from = self.peerID; + else + result.from = self.peerID; + } + if (responseMethod) { + if (responseMethod.error == undefined && error) + message = + { + error: error + }; + else { + var method = error + ? responseMethod.error + : responseMethod.response; + message = + { + method: method, + params: error || result + }; + } + } + else + message = + { + error: error, + result: result + }; + message = packer.pack(message, id); + } + else if (response) + message = response.message; + else + message = packer.pack({ result: null }, id); + storeResponse(message, id, from); + transport = transport || this.getTransport() || self.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + } + ; + inherits(RpcRequest, RpcNotification); + function cancel(message) { + var key = message2Key[message]; + if (!key) + return; + delete message2Key[message]; + var request = requests.pop(key.id, key.dest); + if (!request) + return; + clearTimeout(request.timeout); + storeProcessedResponse(key.id, key.dest); + } + ; + this.cancel = function (message) { + if (message) + return cancel(message); + for (var message in message2Key) + cancel(message); + }; + this.close = function () { + var transport = this.getTransport(); + if (transport && transport.close) + transport.close(); + this.cancel(); + processedResponses.forEach(clearTimeout); + responses.forEach(function (response) { + clearTimeout(response.timeout); + }); + }; + this.encode = function (method, params, dest, transport, callback) { + if (params instanceof Function) { + if (dest != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = params; + transport = undefined; + dest = undefined; + params = undefined; + } + else if (dest instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = dest; + transport = undefined; + dest = undefined; + } + else if (transport instanceof Function) { + if (callback != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = transport; + transport = undefined; + } + ; + if (self.peerID != undefined) { + params = params || {}; + params.from = self.peerID; + } + ; + if (dest != undefined) { + params = params || {}; + params.dest = dest; + } + ; + var message = { + method: method, + params: params + }; + if (callback) { + var id = requestID++; + var retried = 0; + message = packer.pack(message, id); + function dispatchCallback(error, result) { + self.cancel(message); + callback(error, result); + } + ; + var request = { + message: message, + callback: dispatchCallback, + responseMethods: responseMethods[method] || {} + }; + var encode_transport = unifyTransport(transport); + function sendRequest(transport) { + var rt = (method === 'ping' ? ping_request_timeout : request_timeout); + request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++)); + message2Key[message] = { id: id, dest: dest }; + requests.set(request, id, dest); + transport = transport || encode_transport || self.getTransport(); + if (transport) + return transport.send(message); + return message; + } + ; + function retry(transport) { + transport = unifyTransport(transport); + console.warn(retried + ' retry for request message:', message); + var timeout = processedResponses.pop(id, dest); + clearTimeout(timeout); + return sendRequest(transport); + } + ; + function timeout() { + if (retried < max_retries) + return retry(transport); + var error = new Error('Request has timed out'); + error.request = message; + error.retry = retry; + dispatchCallback(error); + } + ; + return sendRequest(transport); + } + ; + message = packer.pack(message); + transport = transport || this.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + this.decode = function (message, transport) { + if (!message) + throw new TypeError("Message is not defined"); + try { + message = packer.unpack(message); + } + catch (e) { + return console.debug(e, message); + } + ; + var id = message.id; + var ack = message.ack; + var method = message.method; + var params = message.params || {}; + var from = params.from; + var dest = params.dest; + if (self.peerID != undefined && from == self.peerID) + return; + if (id == undefined && ack == undefined) { + var notification = new RpcNotification(method, params); + if (self.emit('request', notification)) + return; + return notification; + } + ; + function processRequest() { + transport = unifyTransport(transport) || self.getTransport(); + if (transport) { + var response = responses.get(id, from); + if (response) + return transport.send(response.message); + } + ; + var idAck = (id != undefined) ? id : ack; + var request = new RpcRequest(method, params, idAck, from, transport); + if (self.emit('request', request)) + return; + return request; + } + ; + function processResponse(request, error, result) { + request.callback(error, result); + } + ; + function duplicatedResponse(timeout) { + console.warn("Response already processed", message); + clearTimeout(timeout); + storeProcessedResponse(ack, from); + } + ; + if (method) { + if (dest == undefined || dest == self.peerID) { + var request = requests.get(ack, from); + if (request) { + var responseMethods = request.responseMethods; + if (method == responseMethods.error) + return processResponse(request, params); + if (method == responseMethods.response) + return processResponse(request, null, params); + return processRequest(); + } + var processed = processedResponses.get(ack, from); + if (processed) + return duplicatedResponse(processed); + } + return processRequest(); + } + ; + var error = message.error; + var result = message.result; + if (error && error.dest && error.dest != self.peerID) + return; + if (result && result.dest && result.dest != self.peerID) + return; + var request = requests.get(ack, from); + if (!request) { + var processed = processedResponses.get(ack, from); + if (processed) + return duplicatedResponse(processed); + return console.warn("No callback was defined for this message", message); + } + ; + processResponse(request, error, result); + }; +} +; +inherits(RpcBuilder, EventEmitter); +RpcBuilder.RpcNotification = RpcNotification; +module.exports = RpcBuilder; +var clients = require('./clients'); +var transports = require('./clients/transports'); +RpcBuilder.clients = clients; +RpcBuilder.clients.transports = transports; +RpcBuilder.packers = packers; + +},{"./Mapper":37,"./clients":38,"./clients/transports":40,"./packers":45,"events":1,"inherits":6}],43:[function(require,module,exports){ +function pack(message, id) { + var result = { + jsonrpc: "2.0" + }; + if (message.method) { + result.method = message.method; + if (message.params) + result.params = message.params; + if (id != undefined) + result.id = id; + } + else if (id != undefined) { + if (message.error) { + if (message.result !== undefined) + throw new TypeError("Both result and error are defined"); + result.error = message.error; + } + else if (message.result !== undefined) + result.result = message.result; + else + throw new TypeError("No result or error is defined"); + result.id = id; + } + ; + return JSON.stringify(result); +} +; +function unpack(message) { + var result = message; + if (typeof message === 'string' || message instanceof String) { + result = JSON.parse(message); + } + var version = result.jsonrpc; + if (version !== '2.0') + throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); + if (result.method == undefined) { + if (result.id == undefined) + throw new TypeError("Invalid message: " + message); + var result_defined = result.result !== undefined; + var error_defined = result.error !== undefined; + if (result_defined && error_defined) + throw new TypeError("Both result and error are defined: " + message); + if (!result_defined && !error_defined) + throw new TypeError("No result or error is defined: " + message); + result.ack = result.id; + delete result.id; + } + return result; +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],44:[function(require,module,exports){ +function pack(message) { + throw new TypeError("Not yet implemented"); +} +; +function unpack(message) { + throw new TypeError("Not yet implemented"); +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],45:[function(require,module,exports){ +var JsonRPC = require('./JsonRPC'); +var XmlRPC = require('./XmlRPC'); +exports.JsonRPC = JsonRPC; +exports.XmlRPC = XmlRPC; + +},{"./JsonRPC":43,"./XmlRPC":44}],46:[function(require,module,exports){ +window.getScreenId = function (callback, custom_parameter) { + if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) { + callback({ + video: true + }); + return; + } + if (!!navigator.mozGetUserMedia) { + callback(null, 'firefox', { + video: { + mozMediaSource: 'window', + mediaSource: 'window' + } + }); + return; + } + window.addEventListener('message', onIFrameCallback); + function onIFrameCallback(event) { + if (!event.data) + return; + if (event.data.chromeMediaSourceId) { + if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { + callback('permission-denied'); + } + else { + callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack)); + } + window.removeEventListener('message', onIFrameCallback); + } + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); + window.removeEventListener('message', onIFrameCallback); + } + } + if (!custom_parameter) { + setTimeout(postGetSourceIdMessage, 100); + } + else { + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); + } +}; +function getScreenConstraints(error, sourceId, canRequestAudioTrack) { + var screen_constraints = { + audio: false, + video: { + mandatory: { + chromeMediaSource: error ? 'screen' : 'desktop', + maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, + maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 + }, + optional: [] + } + }; + if (!!canRequestAudioTrack) { + screen_constraints.audio = { + mandatory: { + chromeMediaSource: error ? 'screen' : 'desktop', + }, + optional: [] + }; + } + if (sourceId) { + screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; + if (screen_constraints.audio && screen_constraints.audio.mandatory) { + screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId; + } + } + return screen_constraints; +} +function postGetSourceIdMessage(custom_parameter) { + if (!iframe) { + loadIFrame(function () { + postGetSourceIdMessage(custom_parameter); + }); + return; + } + if (!iframe.isLoaded) { + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); + return; + } + if (!custom_parameter) { + iframe.contentWindow.postMessage({ + captureSourceId: true + }, '*'); + } + else if (!!custom_parameter.forEach) { + iframe.contentWindow.postMessage({ + captureCustomSourceId: custom_parameter + }, '*'); + } + else { + iframe.contentWindow.postMessage({ + captureSourceIdWithAudio: true + }, '*'); + } +} +var iframe; +window.getScreenConstraints = function (callback) { + loadIFrame(function () { + getScreenId(function (error, sourceId, screen_constraints) { + if (!screen_constraints) { + screen_constraints = { + video: true + }; + } + callback(error, screen_constraints.video); + }); + }); +}; +function loadIFrame(loadCallback) { + if (iframe) { + loadCallback(); + return; + } + iframe = document.createElement('iframe'); + iframe.onload = function () { + iframe.isLoaded = true; + loadCallback(); + }; + iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/'; + iframe.style.display = 'none'; + (document.body || document.documentElement).appendChild(iframe); +} +window.getChromeExtensionStatus = function (callback) { + if (!!navigator.mozGetUserMedia) { + callback('installed-enabled'); + return; + } + window.addEventListener('message', onIFrameCallback); + function onIFrameCallback(event) { + if (!event.data) + return; + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus); + window.removeEventListener('message', onIFrameCallback); + } + } + setTimeout(postGetChromeExtensionStatusMessage, 100); +}; +function postGetChromeExtensionStatusMessage() { + if (!iframe) { + loadIFrame(postGetChromeExtensionStatusMessage); + return; + } + if (!iframe.isLoaded) { + setTimeout(postGetChromeExtensionStatusMessage, 100); + return; + } + iframe.contentWindow.postMessage({ + getChromeExtensionStatus: true + }, '*'); +} +exports.getScreenId = getScreenId; + +},{}],47:[function(require,module,exports){ +var chromeMediaSource = 'screen'; +var sourceId; +var screenCallback; +var isFirefox = typeof window.InstallTrigger !== 'undefined'; +var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; +var isChrome = !!window.chrome && !isOpera; +window.addEventListener('message', function (event) { + if (event.origin != window.location.origin) { + return; + } + onMessageCallback(event.data); +}); +function onMessageCallback(data) { + if (data == 'PermissionDeniedError') { + if (screenCallback) + return screenCallback('PermissionDeniedError'); + else + throw new Error('PermissionDeniedError'); + } + if (data == 'rtcmulticonnection-extension-loaded') { + chromeMediaSource = 'desktop'; + } + if (data.sourceId && screenCallback) { + screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true); + } +} +function isChromeExtensionAvailable(callback) { + if (!callback) + return; + if (chromeMediaSource == 'desktop') + return callback(true); + window.postMessage('are-you-there', '*'); + setTimeout(function () { + if (chromeMediaSource == 'screen') { + callback(false); + } + else + callback(true); + }, 2000); +} +function getSourceId(callback) { + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage('get-sourceId', '*'); +} +function getCustomSourceId(arr, callback) { + if (!arr || !arr.forEach) + throw '"arr" parameter is mandatory and it must be an array.'; + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage({ + 'get-custom-sourceId': arr + }, '*'); +} +function getSourceIdWithAudio(callback) { + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage('audio-plus-tab', '*'); +} +function getChromeExtensionStatus(extensionid, callback) { + if (isFirefox) + return callback('not-chrome'); + if (arguments.length != 2) { + callback = extensionid; + extensionid = 'lfcgfepafnobdloecchnfaclibenjold'; + } + var image = document.createElement('img'); + image.src = 'chrome-extension://' + extensionid + '/icon.png'; + image.onload = function () { + chromeMediaSource = 'screen'; + window.postMessage('are-you-there', '*'); + setTimeout(function () { + if (chromeMediaSource == 'screen') { + callback('installed-disabled'); + } + else + callback('installed-enabled'); + }, 2000); + }; + image.onerror = function () { + callback('not-installed'); + }; +} +function getScreenConstraintsWithAudio(callback) { + getScreenConstraints(callback, true); +} +function getScreenConstraints(callback, captureSourceIdWithAudio) { + sourceId = ''; + var firefoxScreenConstraints = { + mozMediaSource: 'window', + mediaSource: 'window' + }; + if (isFirefox) + return callback(null, firefoxScreenConstraints); + var screen_constraints = { + mandatory: { + chromeMediaSource: chromeMediaSource, + maxWidth: screen.width > 1920 ? screen.width : 1920, + maxHeight: screen.height > 1080 ? screen.height : 1080 + }, + optional: [] + }; + if (chromeMediaSource == 'desktop' && !sourceId) { + if (captureSourceIdWithAudio) { + getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + if (canRequestAudioTrack) { + screen_constraints.canRequestAudioTrack = true; + } + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } + else { + getSourceId(function (sourceId) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } + return; + } + if (chromeMediaSource == 'desktop') { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + } + callback(null, screen_constraints); +} +exports.getScreenConstraints = getScreenConstraints; +exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio; +exports.isChromeExtensionAvailable = isChromeExtensionAvailable; +exports.getChromeExtensionStatus = getChromeExtensionStatus; +exports.getSourceId = getSourceId; + +},{}],48:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var freeice = require("freeice"); +var uuid = require("uuid"); +var platform = require("platform"); +var WebRtcPeer = (function () { + function WebRtcPeer(configuration) { + var _this = this; + this.configuration = configuration; + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.iceCandidateList = []; + this.candidategatheringdone = false; + this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice(); + this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers }); + this.id = !!configuration.id ? configuration.id : uuid.v4(); + this.pc.onicecandidate = function (event) { + var candidate = event.candidate; + if (candidate) { + _this.localCandidatesQueue.push({ candidate: candidate.candidate }); + _this.candidategatheringdone = false; + _this.configuration.onicecandidate(event.candidate); + } + else if (!_this.candidategatheringdone) { + _this.candidategatheringdone = true; + } + }; + this.pc.onsignalingstatechange = function () { + if (_this.pc.signalingState === 'stable') { + while (_this.iceCandidateList.length > 0) { + _this.pc.addIceCandidate(_this.iceCandidateList.shift()); + } + } + }; + this.start(); + } + WebRtcPeer.prototype.start = function () { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.pc.signalingState === 'closed') { + reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); + } + if (!!_this.configuration.mediaStream) { + _this.pc.addStream(_this.configuration.mediaStream); + } + if (_this.configuration.mode === 'sendonly' && + (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) { + _this.configuration.mode = 'sendrecv'; + } + resolve(); + }); + }; + WebRtcPeer.prototype.dispose = function () { + var _this = this; + console.debug('Disposing WebRtcPeer'); + try { + if (this.pc) { + if (this.pc.signalingState === 'closed') { + return; + } + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.pc.getLocalStreams().forEach(function (str) { + _this.streamStop(str); + }); + this.pc.close(); + } + } + catch (err) { + console.warn('Exception disposing webrtc peer ' + err); + } + }; + WebRtcPeer.prototype.generateOffer = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var offerAudio, offerVideo = true; + if (!!_this.configuration.mediaConstraints) { + offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ? + _this.configuration.mediaConstraints.audio : true; + offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ? + _this.configuration.mediaConstraints.video : true; + } + var constraints = { + offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio), + offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo) + }; + console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints)); + _this.pc.createOffer(constraints).then(function (offer) { + console.debug('Created SDP offer'); + return _this.pc.setLocalDescription(offer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.processOffer = function (sdpOffer) { + var _this = this; + return new Promise(function (resolve, reject) { + var offer = { + type: 'offer', + sdp: sdpOffer + }; + console.debug('SDP offer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('PeerConnection is closed'); + } + _this.pc.setRemoteDescription(offer) + .then(function () { + return _this.pc.createAnswer(); + }).then(function (answer) { + console.debug('Created SDP answer'); + return _this.pc.setLocalDescription(answer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.processAnswer = function (sdpAnswer) { + var _this = this; + return new Promise(function (resolve, reject) { + var answer = { + type: 'answer', + sdp: sdpAnswer + }; + console.debug('SDP answer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('RTCPeerConnection is closed'); + } + _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) { + var _this = this; + return new Promise(function (resolve, reject) { + console.debug('Remote ICE candidate received', iceCandidate); + _this.remoteCandidatesQueue.push(iceCandidate); + switch (_this.pc.signalingState) { + case 'closed': + reject(new Error('PeerConnection object is closed')); + break; + case 'stable': + if (!!_this.pc.remoteDescription) { + _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); }); + } + break; + default: + _this.iceCandidateList.push(iceCandidate); + resolve(); + } + }); + }; + WebRtcPeer.prototype.streamStop = function (stream) { + stream.getTracks().forEach(function (track) { + track.stop(); + stream.removeTrack(track); + }); + }; + return WebRtcPeer; +}()); +exports.WebRtcPeer = WebRtcPeer; +var WebRtcPeerRecvonly = (function (_super) { + __extends(WebRtcPeerRecvonly, _super); + function WebRtcPeerRecvonly(configuration) { + var _this = this; + configuration.mode = 'recvonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerRecvonly; +}(WebRtcPeer)); +exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; +var WebRtcPeerSendonly = (function (_super) { + __extends(WebRtcPeerSendonly, _super); + function WebRtcPeerSendonly(configuration) { + var _this = this; + configuration.mode = 'sendonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendonly; +}(WebRtcPeer)); +exports.WebRtcPeerSendonly = WebRtcPeerSendonly; +var WebRtcPeerSendrecv = (function (_super) { + __extends(WebRtcPeerSendrecv, _super); + function WebRtcPeerSendrecv(configuration) { + var _this = this; + configuration.mode = 'sendrecv'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendrecv; +}(WebRtcPeer)); +exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; + +},{"freeice":2,"platform":8,"uuid":9}],49:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var platform = require("platform"); +var WebRtcStats = (function () { + function WebRtcStats(stream) { + this.stream = stream; + this.webRtcStatsEnabled = false; + this.statsInterval = 1; + this.stats = { + inbound: { + audio: { + bytesReceived: 0, + packetsReceived: 0, + packetsLost: 0 + }, + video: { + bytesReceived: 0, + packetsReceived: 0, + packetsLost: 0, + framesDecoded: 0, + nackCount: 0 + } + }, + outbound: { + audio: { + bytesSent: 0, + packetsSent: 0, + }, + video: { + bytesSent: 0, + packetsSent: 0, + framesEncoded: 0, + nackCount: 0 + } + } + }; + } + WebRtcStats.prototype.isEnabled = function () { + return this.webRtcStatsEnabled; + }; + WebRtcStats.prototype.initWebRtcStats = function () { + var _this = this; + var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); + if (elastestInstrumentation) { + console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); + this.webRtcStatsEnabled = true; + var instrumentation_1 = JSON.parse(elastestInstrumentation); + this.statsInterval = instrumentation_1.webrtc.interval; + console.warn('localStorage item: ' + JSON.stringify(instrumentation_1)); + this.webRtcStatsIntervalId = setInterval(function () { + _this.sendStatsToHttpEndpoint(instrumentation_1); + }, this.statsInterval * 1000); + return; + } + console.debug('WebRtc stats not enabled'); + }; + WebRtcStats.prototype.stopWebRtcStats = function () { + if (this.webRtcStatsEnabled) { + clearInterval(this.webRtcStatsIntervalId); + console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); + } + }; + WebRtcStats.prototype.getSelectedIceCandidateInfo = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) { + if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0; + var localCandidates = {}; + var remoteCandidates = {}; + for (var key in stats) { + var stat = stats[key]; + if (stat.type === 'localcandidate') { + localCandidates[stat.id] = stat; + } + else if (stat.type === 'remotecandidate') { + remoteCandidates[stat.id] = stat; + } + else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) { + googCandidatePair = stat; + localCandidateId = stat.localCandidateId; + remoteCandidateId = stat.remoteCandidateId; + } + } + var finalLocalCandidate_1 = localCandidates[localCandidateId]; + if (!!finalLocalCandidate_1) { + var candList = _this.stream.getLocalIceCandidateList(); + var cand = candList.filter(function (c) { + return (!!c.candidate && + c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 && + c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 && + c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0); + }); + finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates'; + } + else { + finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used'; + } + var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId]; + if (!!finalRemoteCandidate_1) { + var candList = _this.stream.getRemoteIceCandidateList(); + var cand = candList.filter(function (c) { + return (!!c.candidate && + c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 && + c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 && + c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0); + }); + finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates'; + } + else { + finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used'; + } + resolve({ + googCandidatePair: googCandidatePair, + localCandidate: finalLocalCandidate_1, + remoteCandidate: finalRemoteCandidate_1 + }); + } + else { + reject('Selected ICE candidate info only available for Chrome'); + } + }, function (error) { + reject(error); + }); + }); + }; + WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { + var _this = this; + var sendPost = function (json) { + var http = new XMLHttpRequest(); + var url = instrumentation.webrtc.httpEndpoint; + http.open('POST', url, true); + http.setRequestHeader('Content-type', 'application/json'); + http.onreadystatechange = function () { + if (http.readyState === 4 && http.status === 200) { + console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId); + } + }; + http.send(json); + }; + var f = function (stats) { + if (platform.name.indexOf('Firefox') !== -1) { + stats.forEach(function (stat) { + var json = {}; + if ((stat.type === 'inbound-rtp') && + (stat.nackCount !== null && + stat.isRemote === false && + stat.id.startsWith('inbound') && + stat.remoteId.startsWith('inbound'))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var jit = stat.jitter * 1000; + var metrics = { + bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + jitter: jit, + packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + bytesReceived: 'bytes', + jitter: 'ms', + packetsReceived: 'packets', + packetsLost: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = 'frames'; + units['nackCount'] = 'packets'; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.nackCount; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ((stat.type === 'outbound-rtp') && + (stat.isRemote === false && + stat.id.toLowerCase().includes('outbound'))) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + bytesSent: 'bytes', + packetsSent: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = 'frames'; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + }); + } + else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { + var key = _a[_i]; + var stat = stats[key]; + if (stat.type === 'ssrc') { + var json = {}; + if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || + (stat.mediaType === 'video' && 'qpSum' in stat))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + jitter: stat.googJitterBufferMs, + packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + bytesReceived: 'bytes', + jitter: 'ms', + packetsReceived: 'packets', + packetsLost: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = 'frames'; + units['nackCount'] = 'packets'; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.googNacksSent; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ('bytesSent' in stat) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + bytesSent: 'bytes', + packetsSent: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = 'frames'; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + } + } + } + }; + this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); }); + }; + WebRtcStats.prototype.standardizeReport = function (response) { + console.log(response); + var standardReport = {}; + if (platform.name.indexOf('Firefox') !== -1) { + Object.keys(response).forEach(function (key) { + console.log(response[key]); + }); + return response; + } + response.result().forEach(function (report) { + var standardStats = { + id: report.id, + timestamp: report.timestamp, + type: report.type + }; + report.names().forEach(function (name) { + standardStats[name] = report.stat(name); + }); + standardReport[standardStats.id] = standardStats; + }); + return standardReport; + }; + WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) { + var _this = this; + if (platform.name.indexOf('Firefox') !== -1) { + return pc.getStats(null).then(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }).catch(failureCb); + } + else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + return pc.getStats(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }, null, failureCb); + } + }; + return WebRtcStats; +}()); +exports.WebRtcStats = WebRtcStats; + +},{"platform":8}]},{},[16]) +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9NYXBwZXIuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvSnNvblJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL1htbFJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmctQXV0by5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNQZWVyL1dlYlJ0Y1BlZXIudHMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1N0YXRzL1dlYlJ0Y1N0YXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzZ0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3RlQSxnREFBK0M7QUFFL0MsSUFBSSxNQUFNLEVBQUU7SUFFUixNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsbUJBQVEsQ0FBQztDQUNqQzs7Ozs7QUNhRCxtQ0FBa0M7QUFVbEM7SUFvQ0ksb0JBQW9CLE9BQWdCLEVBQUUsSUFBd0I7UUFBMUMsWUFBTyxHQUFQLE9BQU8sQ0FBUztRQUxwQyxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBT2IsSUFBSSxHQUFHLEdBQUcsdUJBQXVCLENBQUM7UUFDbEMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFO1lBQ1IsR0FBRyxJQUFJLGdDQUFnQyxHQUFHLElBQUksQ0FBQyxFQUFFLEdBQUcsR0FBRyxDQUFDO1NBQzNEO2FBQU07WUFDSCxHQUFHLElBQUksU0FBUyxDQUFDO1NBQ3BCO1FBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVsQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUVwQixJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUU7WUFFUixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDNUIsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQzthQUM3QjtZQUNELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFDZCxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2FBQ3hDO1NBQ0o7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDN0MsQ0FBQztJQVFELHFDQUFnQixHQUFoQixVQUFpQixTQUEwQjtRQUV2QyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsZUFBZSxFQUNsRixJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUVsRCxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUU7WUFDaEQsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZO1lBQy9CLFNBQVMsRUFBRSxTQUFTLENBQUMsU0FBUztZQUM5QixNQUFNLEVBQUUsU0FBUyxDQUFDLE1BQU07WUFDeEIsYUFBYSxFQUFFLFNBQVMsQ0FBQyxhQUFhO1NBQ3pDLEVBQUUsVUFBQyxLQUFLLEVBQUUsUUFBUTtZQUNmLElBQUksS0FBSyxFQUFFO2dCQUNQLE9BQU8sQ0FBQyxLQUFLLENBQUMsK0JBQStCO3NCQUN2QyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7YUFDaEM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFLRCxzQ0FBaUIsR0FBakIsVUFBa0IsT0FBOEI7UUFBaEQsaUJBbUJDO1FBZkcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxVQUFBLElBQUk7WUFDaEIsSUFBTSxhQUFhLEdBQXlCO2dCQUN4QyxFQUFFLEVBQUUsSUFBSSxDQUFDLEVBQUU7Z0JBQ1gsVUFBVSxFQUFFLEtBQUk7Z0JBQ2hCLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztnQkFDekIsU0FBUyxFQUFFLElBQUksQ0FBQyxXQUFXO2dCQUMzQixTQUFTLEVBQUUsSUFBSSxDQUFDLFdBQVc7Z0JBQzNCLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVzthQUNoQyxDQUFDO1lBQ0YsSUFBTSxNQUFNLEdBQUcsSUFBSSxlQUFNLENBQUMsS0FBSSxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FBQztZQUV2RCxLQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzNCLENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxDQUFDLElBQUksQ0FBQywyQ0FBMkMsR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLDBEQUEwRCxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUM5SyxDQUFDO0lBS0QsOEJBQVMsR0FBVCxVQUFVLE1BQWM7UUFDcEIsTUFBTSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDekIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDekIsQ0FBQztJQUtELGlDQUFZLEdBQVosVUFBYSxRQUFnQjtRQUN6QixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDdkIsQ0FBQztJQUtELDRCQUFPLEdBQVA7UUFDSSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2YsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO1NBQ3RCO1FBQ0QsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7SUFDekIsQ0FBQztJQUVMLGlCQUFDO0FBQUQsQ0F2SUEsQUF1SUMsSUFBQTtBQXZJWSxnQ0FBVTs7Ozs7QUNWdkIsbUZBQWtGO0FBYWxGO0lBaUJJLHVCQUFvQixNQUFjO1FBQWQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQVgxQixXQUFNLEdBQVUsRUFBRSxDQUFDO1FBRW5CLFVBQUssR0FBRyxDQUFDLENBQUM7UUFVZCxJQUFJLENBQUMsWUFBWSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsb0JBQW9CLENBQUM7UUFDNUcsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLFlBQVksR0FBRyxjQUFjLENBQUM7UUFDMUUsSUFBSSxDQUFDLEtBQUssR0FBRyx1Q0FBa0IsQ0FBQyxLQUFLLENBQUM7SUFDMUMsQ0FBQztJQU9ELDhCQUFNLEdBQU47UUFBQSxpQkFxRUM7UUFwRUcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBRS9CLElBQUk7Z0JBRUEsSUFBSSxPQUFPLGFBQWEsS0FBSyxXQUFXLEVBQUU7b0JBQ3RDLE9BQU8sQ0FBQyxLQUFLLENBQUMsNkdBQTZHLENBQUMsQ0FBQztvQkFDN0gsTUFBTSxDQUFDLEtBQUssQ0FBQyw2R0FBNkcsQ0FBQyxDQUFDLENBQUM7aUJBQ2hJO2dCQUNELElBQUksS0FBSSxDQUFDLEtBQUssS0FBSyx1Q0FBa0IsQ0FBQyxLQUFLLEVBQUU7b0JBQ3pDLE1BQU0sQ0FBQyxLQUFLLENBQUMseUZBQXlGLEdBQUcsS0FBSSxDQUFDLEtBQUssR0FBRyx3RUFBd0UsQ0FBQyxDQUFDLENBQUM7aUJBQ3BNO2dCQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsc0NBQXNDLEdBQUcsS0FBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsbUJBQW1CLEdBQUcsS0FBSSxDQUFDLFlBQVksR0FBRyxHQUFHLENBQUMsQ0FBQztnQkFHM0gsSUFBSSxPQUFPLGFBQWEsQ0FBQyxlQUFlLEtBQUssVUFBVSxFQUFFO29CQUNyRCxJQUFJLE9BQU8sU0FBQSxDQUFDO29CQUNaLElBQUksYUFBYSxDQUFDLGVBQWUsQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFO3dCQUN4RCxPQUFPLEdBQUcsRUFBRSxRQUFRLEVBQUUsdUJBQXVCLEVBQUUsQ0FBQztxQkFDbkQ7eUJBQU0sSUFBSSxhQUFhLENBQUMsZUFBZSxDQUFDLHdCQUF3QixDQUFDLEVBQUU7d0JBQ2hFLE9BQU8sR0FBRyxFQUFFLFFBQVEsRUFBRSx3QkFBd0IsRUFBRSxDQUFDO3FCQUNwRDt5QkFBTSxJQUFJLGFBQWEsQ0FBQyxlQUFlLENBQUMsdUJBQXVCLENBQUMsRUFBRTt3QkFDL0QsT0FBTyxHQUFHLEVBQUUsUUFBUSxFQUFFLHVCQUF1QixFQUFFLENBQUM7cUJBQ25EO29CQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUNsRCxLQUFJLENBQUMsYUFBYSxHQUFHLElBQUksYUFBYSxDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7aUJBQ2pGO3FCQUFNO29CQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsb0VBQW9FLENBQUMsQ0FBQztvQkFDbkYsS0FBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLGFBQWEsQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7aUJBQ3hFO2dCQUVELEtBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2FBRWhDO1lBQUMsT0FBTyxHQUFHLEVBQUU7Z0JBQ1YsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQ2Y7WUFFRCxLQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsR0FBRyxVQUFDLENBQUM7Z0JBQ25DLEtBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM3QixDQUFDLENBQUM7WUFFRixLQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sR0FBRyxVQUFDLENBQUM7Z0JBQzNCLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDOUMsQ0FBQyxDQUFDO1lBRUYsS0FBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEdBQUc7Z0JBQ3pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsK0JBQStCLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUM7WUFDbEYsQ0FBQyxDQUFDO1lBRUYsS0FBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEdBQUc7Z0JBQ3hCLEtBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN6QixDQUFDLENBQUM7WUFFRixLQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sR0FBRztnQkFDekIsT0FBTyxDQUFDLEdBQUcsQ0FBQyw4QkFBOEIsR0FBRyxLQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQztZQUNqRixDQUFDLENBQUM7WUFFRixLQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsR0FBRztnQkFDMUIsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsR0FBRyxLQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQztZQUNsRixDQUFDLENBQUM7WUFFRixLQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxVQUFDLENBQUM7Z0JBQzdCLE9BQU8sQ0FBQyxHQUFHLENBQUMseUJBQXlCLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDL0MsQ0FBQyxDQUFDO1lBRUYsS0FBSSxDQUFDLEtBQUssR0FBRyx1Q0FBa0IsQ0FBQyxTQUFTLENBQUM7WUFDMUMsT0FBTyxFQUFFLENBQUM7UUFFZCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFPRCw0QkFBSSxHQUFKO1FBQUEsaUJBZUM7UUFkRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsSUFBSTtnQkFDQSxJQUFJLEtBQUksQ0FBQyxLQUFLLEtBQUssdUNBQWtCLENBQUMsS0FBSyxJQUFJLEtBQUksQ0FBQyxLQUFLLEtBQUssdUNBQWtCLENBQUMsUUFBUSxFQUFFO29CQUN2RixNQUFNLENBQUMsS0FBSyxDQUFDLHlHQUF5RyxHQUFHLEtBQUksQ0FBQyxLQUFLLEdBQUcsNENBQTRDLENBQUMsQ0FBQyxDQUFDO2lCQUN4TDtnQkFDRCxLQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sR0FBRztvQkFDeEIsS0FBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO29CQUNyQixPQUFPLEVBQUUsQ0FBQztnQkFDZCxDQUFDLENBQUM7Z0JBQ0YsS0FBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQzthQUM3QjtZQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUNSLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNiO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBT0QsNkJBQUssR0FBTDtRQUFBLGlCQVlDO1FBWEcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQy9CLElBQUk7Z0JBQ0EsSUFBSSxLQUFJLENBQUMsS0FBSyxLQUFLLHVDQUFrQixDQUFDLFNBQVMsRUFBRTtvQkFDN0MsTUFBTSxDQUFDLEtBQUssQ0FBQyw0RkFBNEYsR0FBRyxLQUFJLENBQUMsS0FBSyxHQUFHLDBFQUEwRSxDQUFDLENBQUMsQ0FBQztpQkFDek07Z0JBQ0QsS0FBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDM0IsS0FBSSxDQUFDLEtBQUssR0FBRyx1Q0FBa0IsQ0FBQyxNQUFNLENBQUM7YUFDMUM7WUFBQyxPQUFPLEtBQUssRUFBRTtnQkFDWixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDakI7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFNRCw4QkFBTSxHQUFOO1FBQUEsaUJBWUM7UUFYRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsSUFBSTtnQkFDQSxJQUFJLEtBQUksQ0FBQyxLQUFLLEtBQUssdUNBQWtCLENBQUMsTUFBTSxFQUFFO29CQUMxQyxNQUFNLENBQUMsS0FBSyxDQUFDLDBGQUEwRixHQUFHLEtBQUksQ0FBQyxLQUFLLEdBQUcsNENBQTRDLENBQUMsQ0FBQyxDQUFDO2lCQUN6SztnQkFDRCxLQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUM1QixLQUFJLENBQUMsS0FBSyxHQUFHLHVDQUFrQixDQUFDLFNBQVMsQ0FBQzthQUM3QztZQUFDLE9BQU8sS0FBSyxFQUFFO2dCQUNaLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUNqQjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQU1ELCtCQUFPLEdBQVAsVUFBUSxhQUFhO1FBRWpCLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyx1Q0FBa0IsQ0FBQyxRQUFRLEVBQUU7WUFDNUMsTUFBTSxDQUFDLEtBQUssQ0FBQyw2RkFBNkYsR0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLDJDQUEyQyxDQUFDLENBQUMsQ0FBQztTQUMzSztRQUVELElBQUksQ0FBQyxZQUFZLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVwRCxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQy9CLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUVsQyxJQUFJLE9BQU8sYUFBYSxLQUFLLFFBQVEsRUFBRTtZQUNuQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsYUFBYSxDQUFDO1lBRXpDLElBQU0sZ0JBQWdCLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUNoRSxJQUFJLGdCQUFnQixFQUFFO2dCQUNsQixJQUFJLENBQUMsWUFBWSxHQUFHLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7YUFDdkU7U0FDSjthQUFNO1lBQ0gsSUFBSSxDQUFDLG1CQUFtQixHQUFHLGFBQWEsQ0FBQyxFQUFFLENBQUM7WUFDNUMsSUFBSSxDQUFDLFlBQVksR0FBRyxhQUFhLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztTQUNwRTtRQUVELElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7UUFFN0MsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzdCLENBQUM7SUFNRCw2QkFBSyxHQUFMO1FBQUEsaUJBYUM7UUFaRyxJQUFNLENBQUMsR0FBRztZQUNOLE9BQU8sS0FBSSxDQUFDLElBQUksQ0FBQztZQUNqQixLQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztZQUNqQixLQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztZQUNmLE9BQU8sS0FBSSxDQUFDLGFBQWEsQ0FBQztZQUMxQixLQUFJLENBQUMsS0FBSyxHQUFHLHVDQUFrQixDQUFDLEtBQUssQ0FBQztRQUMxQyxDQUFDLENBQUM7UUFDRixJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssdUNBQWtCLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssdUNBQWtCLENBQUMsTUFBTSxFQUFFO1lBQ3pGLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsY0FBTSxPQUFBLENBQUMsRUFBRSxFQUFILENBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxjQUFNLE9BQUEsQ0FBQyxFQUFFLEVBQUgsQ0FBRyxDQUFDLENBQUM7U0FDaEQ7YUFBTTtZQUNILENBQUMsRUFBRSxDQUFDO1NBQ1A7SUFDTCxDQUFDO0lBTUQsZ0NBQVEsR0FBUjtRQUNJLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyx1Q0FBa0IsQ0FBQyxRQUFRLEVBQUU7WUFDNUMsTUFBTSxDQUFDLEtBQUssQ0FBQyw4RkFBOEYsR0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLDJDQUEyQyxDQUFDLENBQUMsQ0FBQztTQUM1SzthQUFNO1lBQ0gsSUFBTSxDQUFDLEdBQXNCLFFBQVEsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekQsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDO1lBQ3pCLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTdCLElBQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNsRCxDQUFDLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztZQUNiLENBQUMsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQUM7WUFDL0IsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1YsTUFBTSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFaEMsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDaEM7SUFDTCxDQUFDO0lBS0QsK0JBQU8sR0FBUDtRQUNJLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyx1Q0FBa0IsQ0FBQyxRQUFRLEVBQUU7WUFDNUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxzREFBc0QsQ0FBQyxDQUFDLENBQUM7U0FDekU7YUFBTTtZQUNILE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztTQUNwQjtJQUNMLENBQUM7SUFhRCxzQ0FBYyxHQUFkLFVBQWUsUUFBZ0IsRUFBRSxPQUFhO1FBQTlDLGlCQTJCQztRQTFCRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsSUFBSSxLQUFJLENBQUMsS0FBSyxLQUFLLHVDQUFrQixDQUFDLFFBQVEsRUFBRTtnQkFDNUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxvR0FBb0csR0FBRyxLQUFJLENBQUMsS0FBSyxHQUFHLDJDQUEyQyxDQUFDLENBQUMsQ0FBQzthQUNsTDtpQkFBTTtnQkFDSCxJQUFNLE1BQUksR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDO2dCQUNsQyxNQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBRWxDLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFO29CQUM3QixLQUFrQixVQUFvQixFQUFwQixLQUFBLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQXBCLGNBQW9CLEVBQXBCLElBQW9CLEVBQUU7d0JBQW5DLElBQU0sR0FBRyxTQUFBO3dCQUNWLE1BQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7cUJBQzVDO2lCQUNKO2dCQUVELE1BQUksQ0FBQyxrQkFBa0IsR0FBRztvQkFDdEIsSUFBSSxNQUFJLENBQUMsVUFBVSxLQUFLLENBQUMsRUFBRTt3QkFDdkIsSUFBSSxNQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUU7NEJBRTFDLE9BQU8sQ0FBQyxNQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7eUJBQzlCOzZCQUFNOzRCQUNILE1BQU0sQ0FBQyxNQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7eUJBQ3ZCO3FCQUNKO2dCQUNMLENBQUMsQ0FBQztnQkFDRixNQUFJLENBQUMsSUFBSSxDQUFDLEtBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUN4QjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQWFELDZDQUFxQixHQUFyQixVQUFzQixRQUFnQixFQUFFLE9BQWE7UUFBckQsaUJBK0JDO1FBOUJHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUMvQixJQUFJLEtBQUksQ0FBQyxLQUFLLEtBQUssdUNBQWtCLENBQUMsUUFBUSxFQUFFO2dCQUM1QyxNQUFNLENBQUMsS0FBSyxDQUFDLDJHQUEyRyxHQUFHLEtBQUksQ0FBQyxLQUFLLEdBQUcsMkNBQTJDLENBQUMsQ0FBQyxDQUFDO2FBQ3pMO2lCQUFNO2dCQUNILElBQU0sTUFBSSxHQUFHLElBQUksY0FBYyxFQUFFLENBQUM7Z0JBQ2xDLE1BQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFFbEMsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7b0JBQzdCLEtBQWtCLFVBQW9CLEVBQXBCLEtBQUEsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBcEIsY0FBb0IsRUFBcEIsSUFBb0IsRUFBRTt3QkFBbkMsSUFBTSxHQUFHLFNBQUE7d0JBQ1YsTUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztxQkFDNUM7aUJBQ0o7Z0JBRUQsSUFBTSxRQUFRLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDaEMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsS0FBSSxDQUFDLElBQUksRUFBRSxLQUFJLENBQUMsRUFBRSxHQUFHLE9BQU8sQ0FBQyxDQUFDO2dCQUV0RCxNQUFJLENBQUMsa0JBQWtCLEdBQUc7b0JBQ3RCLElBQUksTUFBSSxDQUFDLFVBQVUsS0FBSyxDQUFDLEVBQUU7d0JBQ3ZCLElBQUksTUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxFQUFFOzRCQUUxQyxPQUFPLENBQUMsTUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO3lCQUM5Qjs2QkFBTTs0QkFDSCxNQUFNLENBQUMsTUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO3lCQUN2QjtxQkFDSjtnQkFDTCxDQUFDLENBQUM7Z0JBRUYsTUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUN2QjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUtPLHFDQUFhLEdBQXJCO1FBQ0ksT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQ0FBZ0MsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQztRQUUvRSxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUVqQixJQUFJLENBQUMsZUFBZSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUU3RCxJQUFJLENBQUMsS0FBSyxHQUFHLHVDQUFrQixDQUFDLFFBQVEsQ0FBQztJQUM3QyxDQUFDO0lBRUwsb0JBQUM7QUFBRCxDQXBWQSxBQW9WQyxJQUFBO0FBcFZZLHNDQUFhOzs7OztBQ2QxQixpREFBZ0Q7QUFDaEQseUNBQXdDO0FBQ3hDLHFDQUFvQztBQUtwQyx5RUFBMkY7QUFDM0YsNkVBQTRFO0FBRTVFLDJGQUE2RjtBQUM3RixrRkFBb0Y7QUFFcEYsNkVBQWdGO0FBQ2hGLG1DQUFzQztBQU90QztJQWlDRTtRQWxCQSxXQUFNLEdBQUcsRUFBRSxDQUFDO1FBSVosYUFBUSxHQUFHLEtBQUssQ0FBQztRQVlqQiwwQkFBcUIsR0FBa0MsRUFBRSxDQUFDO1FBR3hELE9BQU8sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBTUQsOEJBQVcsR0FBWDtRQUNFLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxpQkFBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2pDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN0QixDQUFDO0lBNEJELGdDQUFhLEdBQWIsVUFBYyxhQUFtQyxFQUFFLE1BQU8sRUFBRSxNQUFPO1FBRWpFLElBQUksVUFBK0IsQ0FBQztRQUVwQyxJQUFJLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxPQUFPLE1BQU0sS0FBSyxVQUFVLENBQUMsRUFBRTtZQUk5QyxVQUFVLEdBQXlCLE1BQU8sQ0FBQztZQUUzQyxVQUFVLEdBQUc7Z0JBQ1gsV0FBVyxFQUFFLENBQUMsT0FBTyxVQUFVLENBQUMsV0FBVyxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxTQUFTO2dCQUNqRyxTQUFTLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxVQUFVLENBQUMsU0FBUyxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7Z0JBQzNKLFVBQVUsRUFBRSxDQUFDLE9BQU8sVUFBVSxDQUFDLFVBQVUsS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sVUFBVSxDQUFDLFVBQVUsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsaUNBQWUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsaUNBQWUsQ0FBQyxNQUFNO2dCQUNwTSxNQUFNLEVBQUUsQ0FBQyxPQUFPLFVBQVUsQ0FBQyxNQUFNLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUk7Z0JBQzdFLFlBQVksRUFBRSxDQUFDLE9BQU8sVUFBVSxDQUFDLFlBQVksS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDL0YsWUFBWSxFQUFFLENBQUMsT0FBTyxVQUFVLENBQUMsWUFBWSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUMvRixVQUFVLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxVQUFVLENBQUMsVUFBVSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7Z0JBQzlKLFdBQVcsRUFBRSxDQUFDLE9BQU8sVUFBVSxDQUFDLFdBQVcsS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsU0FBUzthQUNsRyxDQUFDO1NBQ0g7YUFBTTtZQUlMLFVBQVUsR0FBRztnQkFDWCxVQUFVLEVBQUUsaUNBQWUsQ0FBQyxNQUFNO2dCQUNsQyxNQUFNLEVBQUUsSUFBSTtnQkFDWixZQUFZLEVBQUUsSUFBSTtnQkFDbEIsWUFBWSxFQUFFLElBQUk7Z0JBQ2xCLFVBQVUsRUFBRSxTQUFTO2FBQ3RCLENBQUM7U0FDSDtRQUVELElBQU0sU0FBUyxHQUFjLElBQUkscUJBQVMsQ0FBQyxhQUFhLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRTVFLElBQUksaUJBQXFELENBQUM7UUFDMUQsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsT0FBTyxNQUFNLEtBQUssVUFBVSxDQUFDLEVBQUU7WUFDOUMsaUJBQWlCLEdBQUcsTUFBTSxDQUFDO1NBQzVCO2FBQU0sSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFO1lBQ25CLGlCQUFpQixHQUFHLE1BQU0sQ0FBQztTQUM1QjtRQUVELFNBQVMsQ0FBQyxVQUFVLEVBQUU7YUFDbkIsSUFBSSxDQUFDO1lBQ0osSUFBSSxpQkFBaUIsS0FBSyxTQUFTLEVBQUU7Z0JBQ25DLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQzlCO1lBQ0QsU0FBUyxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDM0MsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUMsS0FBSztZQUNiLElBQUksaUJBQWlCLEtBQUssU0FBUyxFQUFFO2dCQUNuQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUMxQjtZQUNELFNBQVMsQ0FBQyxTQUFTLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzFDLENBQUMsQ0FBQyxDQUFDO1FBRUwsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQVdELHFDQUFrQixHQUFsQixVQUFtQixhQUFtQyxFQUFFLFVBQWdDO1FBQXhGLGlCQW1CQztRQWxCQyxPQUFPLElBQUksT0FBTyxDQUFZLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFFNUMsSUFBSSxTQUFvQixDQUFDO1lBRXpCLElBQU0sUUFBUSxHQUFHLFVBQUMsS0FBWTtnQkFDNUIsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFO29CQUNYLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDZjtxQkFBTTtvQkFDTCxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7aUJBQ3BCO1lBQ0gsQ0FBQyxDQUFDO1lBRUYsSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFO2dCQUNoQixTQUFTLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLEVBQUUsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2FBQ3JFO2lCQUFNO2dCQUNMLFNBQVMsR0FBRyxLQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsRUFBRSxRQUFRLENBQUMsQ0FBQzthQUN6RDtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQU9ELG9DQUFpQixHQUFqQixVQUFrQixNQUFjO1FBQzlCLE9BQU8sSUFBSSw2QkFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFPRCwwQ0FBdUIsR0FBdkI7UUFDRSxJQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO1FBQzlCLElBQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUM7UUFFakMsSUFBSSxDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sS0FBSyxlQUFlLENBQUM7WUFDekQsQ0FBQyxPQUFPLEtBQUssU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEtBQUssZ0JBQWdCLENBQUMsSUFBSSxDQUFDLE9BQU8sS0FBSyxpQkFBaUIsQ0FBQztZQUM1RixDQUFDLE9BQU8sS0FBSyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sS0FBSyxjQUFjLENBQUM7WUFDckQsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLEVBQUU7WUFDeEIsT0FBTyxDQUFDLENBQUM7U0FDVjthQUFNO1lBQ0wsT0FBTyxDQUFDLENBQUM7U0FDVjtJQUNILENBQUM7SUFNRCw2QkFBVSxHQUFWO1FBQ0UsT0FBTyxJQUFJLE9BQU8sQ0FBVyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQzNDLFNBQVMsQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBQyxXQUFXO2dCQUN6RCxJQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7Z0JBQzdCLFdBQVcsQ0FBQyxPQUFPLENBQUMsVUFBQSxVQUFVO29CQUM1QixJQUFJLFVBQVUsQ0FBQyxJQUFJLEtBQUssWUFBWSxJQUFJLFVBQVUsQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFO3dCQUN4RSxPQUFPLENBQUMsSUFBSSxDQUFDOzRCQUNYLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTs0QkFDckIsUUFBUSxFQUFFLFVBQVUsQ0FBQyxRQUFROzRCQUM3QixLQUFLLEVBQUUsVUFBVSxDQUFDLEtBQUs7eUJBQ3hCLENBQUMsQ0FBQztxQkFDSjtnQkFDSCxDQUFDLENBQUMsQ0FBQztnQkFDSCxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbkIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUMsS0FBSztnQkFDYixPQUFPLENBQUMsS0FBSyxDQUFDLHVCQUF1QixFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUM5QyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFrREQsK0JBQVksR0FBWixVQUFhLE9BQTRCO1FBQXpDLGlCQXVCQztRQXRCQyxPQUFPLElBQUksT0FBTyxDQUFjLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDOUMsS0FBSSxDQUFDLHdCQUF3QixDQUFDLE9BQU8sQ0FBQztpQkFDbkMsSUFBSSxDQUFDLFVBQUEsV0FBVztnQkFDZixTQUFTLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUM7cUJBQzdDLElBQUksQ0FBQyxVQUFBLFdBQVc7b0JBQ2YsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUN2QixDQUFDLENBQUM7cUJBQ0QsS0FBSyxDQUFDLFVBQUEsS0FBSztvQkFDVixJQUFJLFNBQTRCLENBQUM7b0JBQ2pDLElBQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztvQkFDdEMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsRUFBRTt3QkFDdkMsU0FBUyxHQUFHLGlDQUFpQixDQUFDLG9CQUFvQixDQUFDO3FCQUNwRDt5QkFBTTt3QkFDTCxTQUFTLEdBQUcsaUNBQWlCLENBQUMscUJBQXFCLENBQUM7cUJBQ3JEO29CQUNELE1BQU0sQ0FBQyxJQUFJLDZCQUFhLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7Z0JBQ3JELENBQUMsQ0FBQyxDQUFDO1lBQ1AsQ0FBQyxDQUFDO2lCQUNELEtBQUssQ0FBQyxVQUFDLEtBQW9CO2dCQUMxQixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEIsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFPRCxpQ0FBYyxHQUFkO1FBQ0UsT0FBTyxDQUFDLEdBQUcsR0FBRyxjQUFRLENBQUMsQ0FBQztRQUN4QixPQUFPLENBQUMsS0FBSyxHQUFHLGNBQVEsQ0FBQyxDQUFDO1FBQzFCLE9BQU8sQ0FBQyxJQUFJLEdBQUcsY0FBUSxDQUFDLENBQUM7UUFDekIsT0FBTyxDQUFDLElBQUksR0FBRyxjQUFRLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBVUQsMkNBQXdCLEdBQXhCLFVBQXlCLGFBQTRDO1FBQ25FLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxhQUFhLENBQUM7SUFDN0MsQ0FBQztJQVFELDJDQUF3QixHQUF4QixVQUF5QixtQkFBd0M7UUFBakUsaUJBbUlDO1FBbElDLE9BQU8sSUFBSSxPQUFPLENBQXlCLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDekQsSUFBSSxLQUFLLEVBQUUsS0FBSyxDQUFDO1lBRWpCLElBQUksbUJBQW1CLENBQUMsV0FBVyxLQUFLLElBQUksSUFBSSxtQkFBbUIsQ0FBQyxXQUFXLEtBQUssS0FBSyxFQUFFO2dCQUN6RixLQUFLLEdBQUcsS0FBSyxDQUFDO2FBQ2Y7aUJBQU0sSUFBSSxtQkFBbUIsQ0FBQyxXQUFXLEtBQUssU0FBUyxFQUFFO2dCQUN4RCxLQUFLLEdBQUcsSUFBSSxDQUFDO2FBQ2Q7aUJBQU07Z0JBQ0wsS0FBSyxHQUFHLG1CQUFtQixDQUFDLFdBQVcsQ0FBQzthQUN6QztZQUVELElBQUksbUJBQW1CLENBQUMsV0FBVyxLQUFLLElBQUksSUFBSSxtQkFBbUIsQ0FBQyxXQUFXLEtBQUssS0FBSyxFQUFFO2dCQUN6RixLQUFLLEdBQUcsS0FBSyxDQUFDO2FBQ2Y7aUJBQU07Z0JBQ0wsS0FBSyxHQUFHO29CQUNOLE1BQU0sRUFBRTt3QkFDTixLQUFLLEVBQUUsR0FBRztxQkFDWDtvQkFDRCxLQUFLLEVBQUU7d0JBQ0wsS0FBSyxFQUFFLEdBQUc7cUJBQ1g7aUJBQ0YsQ0FBQzthQUNIO1lBRUQsSUFBTSxnQkFBZ0IsR0FBMkI7Z0JBQy9DLEtBQUssT0FBQTtnQkFDTCxLQUFLLE9BQUE7YUFDTixDQUFDO1lBRUYsSUFBSSxPQUFPLGdCQUFnQixDQUFDLEtBQUssS0FBSyxRQUFRLEVBQUU7Z0JBQzlDLGdCQUFnQixDQUFDLEtBQUssR0FBRyxFQUFFLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDO2FBQzFFO1lBRUQsSUFBSSxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUU7Z0JBRTFCLElBQUksQ0FBQyxDQUFDLG1CQUFtQixDQUFDLFVBQVUsRUFBRTtvQkFDcEMsSUFBTSxjQUFjLEdBQUcsbUJBQW1CLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDL0UsSUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUN4QyxJQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3hDLGdCQUFnQixDQUFDLEtBQWEsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztvQkFDbkQsZ0JBQWdCLENBQUMsS0FBYSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO2lCQUN2RDtnQkFFRCxJQUFJLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLEVBQUU7b0JBQ2xDLGdCQUFnQixDQUFDLEtBQWEsQ0FBQyxTQUFTLEdBQUcsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLENBQUMsU0FBUyxFQUFFLENBQUM7aUJBQ3RGO2dCQUVELElBQUksQ0FBQyxDQUFDLG1CQUFtQixDQUFDLFdBQVcsSUFBSSxPQUFPLG1CQUFtQixDQUFDLFdBQVcsS0FBSyxRQUFRLEVBQUU7b0JBRTVGLElBQUksbUJBQW1CLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTt3QkFFaEQsSUFBSSxRQUFRLENBQUMsSUFBSSxLQUFLLFFBQVEsSUFBSSxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTs0QkFDMUUsSUFBTSxLQUFLLEdBQUcsSUFBSSw2QkFBYSxDQUFDLGlDQUFpQixDQUFDLDRCQUE0QixFQUFFLDZFQUE2RSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQzs0QkFDL0ssT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQzs0QkFDckIsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO3lCQUNmOzZCQUFNOzRCQUVMLElBQUksQ0FBQyxDQUFDLEtBQUksQ0FBQyxxQkFBcUIsQ0FBQywwQkFBMEIsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtnQ0FJMUcsYUFBYSxDQUFDLG9CQUFvQixDQUFDLFVBQUMsS0FBSyxFQUFFLGlCQUFpQjtvQ0FDMUQsSUFBSSxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLElBQUksaUJBQWlCLENBQUMsU0FBUyxDQUFDLGlCQUFpQixLQUFLLFFBQVEsRUFBRTt3Q0FDMUcsSUFBSSxLQUFLLEtBQUssbUJBQW1CLElBQUksS0FBSyxLQUFLLHVCQUF1QixFQUFFOzRDQUN0RSxJQUFNLE9BQUssR0FBRyxJQUFJLDZCQUFhLENBQUMsaUNBQWlCLENBQUMscUJBQXFCLEVBQUUscURBQXFELENBQUMsQ0FBQzs0Q0FDaEksT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFLLENBQUMsQ0FBQzs0Q0FDckIsTUFBTSxDQUFDLE9BQUssQ0FBQyxDQUFDO3lDQUNmOzZDQUFNOzRDQUNMLElBQU0sV0FBVyxHQUFHLEtBQUksQ0FBQyxxQkFBcUIsQ0FBQywwQkFBMkIsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7NENBQ3JHLGFBQWEsQ0FBQyx3QkFBd0IsQ0FBQyxXQUFXLEVBQUUsVUFBQyxNQUFNO2dEQUN6RCxJQUFJLE1BQU0sS0FBSyxvQkFBb0IsRUFBRTtvREFDbkMsSUFBTSxPQUFLLEdBQUcsSUFBSSw2QkFBYSxDQUFDLGlDQUFpQixDQUFDLHlCQUF5QixFQUFFLHNDQUFzQyxDQUFDLENBQUM7b0RBQ3JILE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBSyxDQUFDLENBQUM7b0RBQ3JCLE1BQU0sQ0FBQyxPQUFLLENBQUMsQ0FBQztpREFDZjtnREFDRCxJQUFJLE1BQU0sS0FBSyxlQUFlLEVBQUU7b0RBQzlCLElBQU0sT0FBSyxHQUFHLElBQUksNkJBQWEsQ0FBQyxpQ0FBaUIsQ0FBQyw4QkFBOEIsRUFBVyxLQUFJLENBQUMscUJBQXFCLENBQUMsMEJBQTJCLENBQUMsQ0FBQztvREFDbkosT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFLLENBQUMsQ0FBQztvREFDckIsTUFBTSxDQUFDLE9BQUssQ0FBQyxDQUFDO2lEQUNmOzRDQUNILENBQUMsQ0FBQyxDQUFDO3lDQUNKO3FDQUNGO3lDQUFNO3dDQUNMLGdCQUFnQixDQUFDLEtBQUssR0FBRyxpQkFBaUIsQ0FBQzt3Q0FDM0MsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7cUNBQzNCO2dDQUNILENBQUMsQ0FBQyxDQUFDOzZCQUNKO2lDQUFNO2dDQUlMLGlCQUFpQixDQUFDLFdBQVcsQ0FBQyxVQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsaUJBQWlCO29DQUMvRCxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUU7d0NBQ1gsSUFBSSxLQUFLLEtBQUssZUFBZSxFQUFFOzRDQUM3QixJQUFNLFlBQVksR0FBRyxDQUFDLENBQUMsS0FBSSxDQUFDLHFCQUFxQixDQUFDLDBCQUEwQixDQUFDLENBQUMsQ0FBQyxLQUFJLENBQUMscUJBQXFCLENBQUMsMEJBQTBCLENBQUMsQ0FBQztnREFDcEksbUdBQW1HLENBQUM7NENBQ3RHLElBQU0sT0FBSyxHQUFHLElBQUksNkJBQWEsQ0FBQyxpQ0FBaUIsQ0FBQyw4QkFBOEIsRUFBRSxZQUFZLENBQUMsQ0FBQzs0Q0FDaEcsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFLLENBQUMsQ0FBQzs0Q0FDckIsTUFBTSxDQUFDLE9BQUssQ0FBQyxDQUFDO3lDQUNmOzZDQUFNLElBQUksS0FBSyxLQUFLLG9CQUFvQixFQUFFOzRDQUN6QyxJQUFNLE9BQUssR0FBRyxJQUFJLDZCQUFhLENBQUMsaUNBQWlCLENBQUMseUJBQXlCLEVBQUUsc0NBQXNDLENBQUMsQ0FBQzs0Q0FDckgsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFLLENBQUMsQ0FBQzs0Q0FDckIsTUFBTSxDQUFDLE9BQUssQ0FBQyxDQUFDO3lDQUNmOzZDQUFNLElBQUksS0FBSyxLQUFLLG1CQUFtQixFQUFFOzRDQUN4QyxJQUFNLE9BQUssR0FBRyxJQUFJLDZCQUFhLENBQUMsaUNBQWlCLENBQUMscUJBQXFCLEVBQUUscURBQXFELENBQUMsQ0FBQzs0Q0FDaEksT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFLLENBQUMsQ0FBQzs0Q0FDckIsTUFBTSxDQUFDLE9BQUssQ0FBQyxDQUFDO3lDQUNmO3FDQUNGO3lDQUFNO3dDQUNMLGdCQUFnQixDQUFDLEtBQUssR0FBRyxpQkFBaUIsQ0FBQyxLQUFLLENBQUM7d0NBQ2pELE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO3FDQUMzQjtnQ0FDSCxDQUFDLENBQUMsQ0FBQzs2QkFDSjs0QkFFRCxtQkFBbUIsQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDO3lCQUU1QztxQkFDRjt5QkFBTTt3QkFFTCxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLENBQUMsV0FBVyxFQUFFLENBQUM7d0JBQ2hGLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO3FCQUMzQjtpQkFDRjtxQkFBTTtvQkFDTCxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztpQkFDM0I7YUFDRjtpQkFBTTtnQkFDTCxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQzthQUMzQjtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUtELDBCQUFPLEdBQVAsVUFBUSxlQUF1QztRQUM3QyxJQUFNLE1BQU0sR0FBRztZQUNiLFNBQVMsRUFBRSxJQUFJO1lBQ2YsZ0JBQWdCLEVBQUUsS0FBSztZQUN2QixFQUFFLEVBQUU7Z0JBQ0YsR0FBRyxFQUFFLElBQUksQ0FBQyxLQUFLO2dCQUNmLFNBQVMsRUFBRSxLQUFLO2dCQUNoQixXQUFXLEVBQUUsZUFBZTtnQkFDNUIsWUFBWSxFQUFFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2dCQUNoRCxjQUFjLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7Z0JBQ3BELGFBQWEsRUFBRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQzthQUNuRDtZQUNELEdBQUcsRUFBRTtnQkFDSCxjQUFjLEVBQUUsS0FBSztnQkFDckIsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDdEUsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDNUUsc0JBQXNCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDaEYsZUFBZSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7Z0JBQ2xFLGtCQUFrQixFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7Z0JBQ3hFLGdCQUFnQixFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7Z0JBQ3BFLGdCQUFnQixFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7Z0JBQ3BFLFdBQVcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDekQsWUFBWSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7Z0JBQzlELFVBQVUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQzthQUN6RDtTQUNGLENBQUM7UUFDRixJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksVUFBVSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDcEUsQ0FBQztJQUtELDBCQUFPLEdBQVA7UUFDRSxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFLRCw4QkFBVyxHQUFYLFVBQVksTUFBYyxFQUFFLE1BQVcsRUFBRSxRQUFTO1FBQ2hELElBQUksTUFBTSxJQUFJLE1BQU0sWUFBWSxRQUFRLEVBQUU7WUFDeEMsUUFBUSxHQUFHLE1BQU0sQ0FBQztZQUNsQixNQUFNLEdBQUcsRUFBRSxDQUFDO1NBQ2I7UUFDRCxPQUFPLENBQUMsS0FBSyxDQUFDLDRCQUE0QixHQUFHLE1BQU0sR0FBRyxhQUFhLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUNwRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFLRCxxQ0FBa0IsR0FBbEIsVUFBbUIsV0FBZ0I7UUFDakMsSUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsV0FBVztZQUN2QixXQUFXLENBQUMsT0FBTyxLQUFLLFNBQVMsSUFBSSxPQUFPLFdBQVcsQ0FBQyxPQUFPLEtBQUssU0FBUztZQUM3RSxXQUFXLENBQUMsRUFBRSxLQUFLLFNBQVMsSUFBSSxPQUFPLFdBQVcsQ0FBQyxFQUFFLEtBQUssUUFBUTtZQUNsRSxXQUFXLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxPQUFPLFdBQVcsQ0FBQyxJQUFJLEtBQUssUUFBUTtZQUN0RSxXQUFXLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxPQUFPLFdBQVcsQ0FBQyxLQUFLLEtBQUssUUFBUTtZQUN4RSxXQUFXLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxPQUFPLFdBQVcsQ0FBQyxLQUFLLEtBQUssU0FBUztZQUN6RSxXQUFXLENBQUMsVUFBVSxLQUFLLFNBQVMsSUFBSSxPQUFPLFdBQVcsQ0FBQyxVQUFVLEtBQUssUUFBUSxDQUFDLENBQUM7UUFDdEYsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBS0QsMkJBQVEsR0FBUjtRQUNFLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0lBS0QsNEJBQVMsR0FBVDtRQUNFLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBS0QsOEJBQVcsR0FBWDtRQUNFLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN2QixDQUFDO0lBS08scUNBQWtCLEdBQTFCO1FBQ0UsT0FBTyxDQUFDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1FBQzFDLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFO1lBQzFCLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztTQUNqQzthQUFNO1lBQ0wsS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7U0FDaEQ7SUFDSCxDQUFDO0lBRU8sdUNBQW9CLEdBQTVCO1FBQ0UsT0FBTyxDQUFDLElBQUksQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1FBQ3pELElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFO1lBQzFCLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztTQUNqQzthQUFNO1lBQ0wsS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7U0FDaEQ7SUFDSCxDQUFDO0lBRU8sc0NBQW1CLEdBQTNCO1FBQ0UsT0FBTyxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFFTyxrQ0FBZSxHQUF2QjtRQUNFLElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxTQUFTLElBQUksSUFBSSxDQUFDLE9BQU8sWUFBWSxpQkFBTyxFQUFFO1lBQ2pFLE9BQU8sSUFBSSxDQUFDO1NBQ2I7YUFBTTtZQUNMLE9BQU8sQ0FBQyxJQUFJLENBQUMsNEJBQTRCLENBQUMsQ0FBQztZQUMzQyxPQUFPLEtBQUssQ0FBQztTQUNkO0lBQ0gsQ0FBQztJQUVILGVBQUM7QUFBRCxDQXpqQkEsQUF5akJDLElBQUE7QUF6akJZLDRCQUFROzs7Ozs7Ozs7Ozs7Ozs7QUNwQnJCLHFDQUFvQztBQUNwQyxtQ0FBa0M7QUFDbEMsaURBQWdEO0FBSWhELHNFQUFxRTtBQUNyRSxrRkFBaUY7QUFDakYseUVBQTJGO0FBTzNGO0lBQStCLDZCQUFhO0lBd0J4QyxtQkFBWSxNQUE0QixFQUFFLFVBQStCLEVBQVUsUUFBa0I7UUFBckcsWUFDSSxrQkFBTSxJQUFJLGVBQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksaUJBQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLG1CQUFtQixFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxTQVF4SjtRQVRrRixjQUFRLEdBQVIsUUFBUSxDQUFVO1FBbkJyRyxtQkFBYSxHQUFHLEtBQUssQ0FBQztRQUt0QiwwQkFBb0IsR0FBRyxLQUFLLENBQUM7UUFPckIsa0JBQVksR0FBRyxLQUFLLENBQUM7UUFTekIsS0FBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFFN0IsS0FBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLFVBQUMsTUFBYztZQUNyRSxJQUFNLFdBQVcsR0FBRyxJQUFJLHlCQUFXLENBQUMsSUFBSSxFQUFFLEtBQUksRUFBRSxpQkFBaUIsRUFBRSxLQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3hGLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGlCQUFpQixFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztZQUNwRCxXQUFXLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUN2QyxDQUFDLENBQUMsQ0FBQzs7SUFDUCxDQUFDO0lBT0QsZ0NBQVksR0FBWixVQUFhLEtBQWM7UUFDdkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBQyxLQUFLO1lBQ3hELEtBQUssQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBQzFCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ25HLENBQUM7SUFPRCxnQ0FBWSxHQUFaLFVBQWEsS0FBYztRQUN2QixJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDLGNBQWMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFDLEtBQUs7WUFDeEQsS0FBSyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDMUIsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxHQUFHLG1CQUFtQixDQUFDLENBQUM7SUFDbkcsQ0FBQztJQU1ELHFDQUFpQixHQUFqQixVQUFrQixLQUFlO1FBQzdCLEtBQUssR0FBRyxDQUFDLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDN0MsSUFBSSxDQUFDLG9CQUFvQixHQUFHLEtBQUssQ0FBQztRQUNsQyxJQUFJLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFNRCxzQkFBRSxHQUFGLFVBQUcsSUFBWSxFQUFFLE9BQStCO1FBQWhELGlCQStCQztRQTlCRyxpQkFBTSxFQUFFLFlBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3hCLElBQUksSUFBSSxLQUFLLGVBQWUsRUFBRTtZQUMxQixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsc0JBQXNCLEVBQUU7Z0JBQ3JELElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxDQUFDLElBQUkseUJBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN4RztpQkFBTTtnQkFDSCxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsNkJBQTZCLEVBQUU7b0JBQzdDLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxDQUFDLElBQUkseUJBQVcsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLGVBQWUsRUFBRSxLQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDekcsQ0FBQyxDQUFDLENBQUM7YUFDTjtTQUNKO1FBQ0QsSUFBSSxJQUFJLEtBQUssb0JBQW9CLEVBQUU7WUFDL0IsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUN2RSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxXQUFXLEdBQUcsQ0FBQztnQkFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLEtBQUs7Z0JBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxLQUFLO2dCQUNwQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssQ0FBQyxFQUFFO2dCQUN2QyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3RIO1NBQ0o7UUFDRCxJQUFJLElBQUksS0FBSyxlQUFlLEVBQUU7WUFDMUIsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUNwQixJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQzthQUN0QztTQUNKO1FBQ0QsSUFBSSxJQUFJLEtBQUssY0FBYyxFQUFFO1lBQ3pCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtnQkFDbkIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLENBQUM7YUFDckM7U0FDSjtRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFNRCx3QkFBSSxHQUFKLFVBQUssSUFBWSxFQUFFLE9BQStCO1FBQWxELGlCQStCQztRQTlCRyxpQkFBTSxJQUFJLFlBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzFCLElBQUksSUFBSSxLQUFLLGVBQWUsRUFBRTtZQUMxQixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsc0JBQXNCLEVBQUU7Z0JBQ3JELElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxDQUFDLElBQUkseUJBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN4RztpQkFBTTtnQkFDSCxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsNkJBQTZCLEVBQUU7b0JBQy9DLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxDQUFDLElBQUkseUJBQVcsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLGVBQWUsRUFBRSxLQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDekcsQ0FBQyxDQUFDLENBQUM7YUFDTjtTQUNKO1FBQ0QsSUFBSSxJQUFJLEtBQUssb0JBQW9CLEVBQUU7WUFDL0IsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUN2RSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxXQUFXLEdBQUcsQ0FBQztnQkFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLEtBQUs7Z0JBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxLQUFLO2dCQUNwQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssQ0FBQyxFQUFFO2dCQUN2QyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3RIO1NBQ0o7UUFDRCxJQUFJLElBQUksS0FBSyxlQUFlLEVBQUU7WUFDMUIsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUNwQixJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQzthQUN0QztTQUNKO1FBQ0QsSUFBSSxJQUFJLEtBQUssY0FBYyxFQUFFO1lBQ3pCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtnQkFDbkIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLENBQUM7YUFDckM7U0FDSjtRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFRRCw4QkFBVSxHQUFWO1FBQUEsaUJBcUxDO1FBcExHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUUvQixJQUFNLGFBQWEsR0FBRyxVQUFDLGFBQTRCO2dCQUMvQyxLQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztnQkFDekIsS0FBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7Z0JBQzNCLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUMxQixDQUFDLENBQUM7WUFFRixJQUFNLGVBQWUsR0FBRyxVQUFDLFdBQXdCO2dCQUM3QyxLQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztnQkFDMUIsS0FBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7Z0JBRTFCLElBQUksS0FBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxFQUFFO29CQUMvRCxXQUFXLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUN6RCxXQUFXLENBQUMsUUFBUSxDQUFvQixLQUFJLENBQUMsVUFBVSxDQUFDLFdBQVksQ0FBQyxDQUFDO2lCQUN6RTtnQkFFRCxJQUFJLEtBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsS0FBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsRUFBRTtvQkFDL0QsV0FBVyxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDekQsV0FBVyxDQUFDLFFBQVEsQ0FBb0IsS0FBSSxDQUFDLFVBQVUsQ0FBQyxXQUFZLENBQUMsQ0FBQztpQkFDekU7Z0JBR0QsSUFBSSxDQUFDLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFO29CQUNuQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLFlBQVksQ0FBQztpQkFDL0c7Z0JBQ0QsSUFBSSxDQUFDLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFO29CQUNuQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLFlBQVksQ0FBQztpQkFDL0c7Z0JBRUQsS0FBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ3hDLElBQUksQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxFQUFFO29CQUdoQyxLQUFJLENBQUMsTUFBTSxDQUFDLHlCQUF5QixFQUFFLENBQUM7aUJBQzNDO2dCQUNELEtBQUksQ0FBQyxNQUFNLENBQUMsMkJBQTJCLEdBQUcsSUFBSSxDQUFDO2dCQUMvQyxLQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMseUJBQXlCLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBRXhELElBQUksQ0FBQyxDQUFDLEtBQUksQ0FBQyxpQkFBaUIsRUFBRTtvQkFDMUIsS0FBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLEVBQW1CLEtBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7aUJBQzlHO2dCQUNELE9BQU8sS0FBSSxDQUFDLGlCQUFpQixDQUFDO2dCQUU5QixPQUFPLEVBQUUsQ0FBQztZQUNkLENBQUMsQ0FBQztZQUVGLEtBQUksQ0FBQyxRQUFRLENBQUMsd0JBQXdCLENBQUMsS0FBSSxDQUFDLFVBQVUsQ0FBQztpQkFDbEQsSUFBSSxDQUFDLFVBQUEsV0FBVztnQkFFYixJQUFNLHFCQUFxQixHQUFHO29CQUMxQixnQkFBZ0IsRUFBRSxXQUFXO29CQUM3QixtQkFBbUIsRUFBRSxLQUFJLENBQUMsVUFBVTtpQkFDdkMsQ0FBQztnQkFFRixLQUFJLENBQUMsTUFBTSxDQUFDLHdCQUF3QixDQUFDLHFCQUFxQixDQUFDLENBQUM7Z0JBRTVELElBQU0sY0FBYyxHQUEyQixFQUFFLENBQUM7Z0JBQ2xELElBQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDO2dCQUVoQyxJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLElBQUksS0FBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFBRTtvQkFDeEQsSUFBTSx3QkFBc0IsR0FBRyxDQUFDLENBQUMsV0FBVyxDQUFDLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQzlGLGNBQWMsQ0FBQyxLQUFLLEdBQUcsS0FBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyx3QkFBc0IsQ0FBQztvQkFDbkYsY0FBYyxDQUFDLEtBQUssR0FBRyxXQUFXLENBQUMsS0FBSyxDQUFDO29CQUN6QyxJQUFJLFdBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7b0JBQzNCLEtBQUksQ0FBQyx3QkFBd0IsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO29CQUVsRCxTQUFTLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUM7eUJBQzlDLElBQUksQ0FBQyxVQUFBLFdBQVc7d0JBQ2IsS0FBSSxDQUFDLDBCQUEwQixDQUFDLFdBQVMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO3dCQUUvRCxJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLElBQUksS0FBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFBRTs0QkFFekQsY0FBYyxDQUFDLEtBQUssR0FBRyx3QkFBc0IsQ0FBQzs0QkFDOUMsY0FBYyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7NEJBQzdCLFdBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7NEJBQ3ZCLEtBQUksQ0FBQyx3QkFBd0IsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDOzRCQUVsRCxTQUFTLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUM7aUNBQzlDLElBQUksQ0FBQyxVQUFBLGVBQWU7Z0NBQ2pCLEtBQUksQ0FBQywwQkFBMEIsQ0FBQyxXQUFTLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztnQ0FDL0QsV0FBVyxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQ0FDMUQsZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFDOzRCQUNqQyxDQUFDLENBQUM7aUNBQ0QsS0FBSyxDQUFDLFVBQUEsS0FBSztnQ0FDUixLQUFJLENBQUMsMEJBQTBCLENBQUMsV0FBUyxFQUFFLGtCQUFrQixDQUFDLENBQUM7Z0NBQy9ELElBQUksU0FBUyxFQUFFLFlBQVksQ0FBQztnQ0FDNUIsUUFBUSxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFO29DQUM5QixLQUFLLGVBQWU7d0NBQ2hCLFNBQVMsR0FBRyxpQ0FBaUIsQ0FBQyw0QkFBNEIsQ0FBQzt3Q0FDM0QsWUFBWSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQzt3Q0FDaEMsYUFBYSxDQUFDLElBQUksNkJBQWEsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQzt3Q0FDMUQsTUFBTTtvQ0FDVixLQUFLLGlCQUFpQjt3Q0FDbEIsU0FBUyxHQUFHLGlDQUFpQixDQUFDLG9CQUFvQixDQUFDO3dDQUNuRCxZQUFZLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO3dDQUNoQyxhQUFhLENBQUMsSUFBSSw2QkFBYSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO3dDQUMxRCxNQUFNO29DQUNWLEtBQUssc0JBQXNCO3dDQUN2QixJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLEtBQUssVUFBVSxFQUFFOzRDQUMvQyxTQUFTLEdBQUcsaUNBQWlCLENBQUMsNEJBQTRCLENBQUM7NENBQzNELFlBQVksR0FBRyxvQ0FBb0MsR0FBMEQsV0FBVyxDQUFDLEtBQU0sQ0FBQyxRQUFXLENBQUMsS0FBSyxHQUFHLGFBQWEsQ0FBQzt5Q0FDcks7NkNBQU07NENBQ0gsU0FBUyxHQUFHLGlDQUFpQixDQUFDLDBCQUEwQixDQUFDOzRDQUN6RCxZQUFZLEdBQUcsc0VBQXNFLEdBQUcsS0FBSyxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUM7eUNBQ2xIO3dDQUNELGFBQWEsQ0FBQyxJQUFJLDZCQUFhLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7d0NBQzFELE1BQU07aUNBQ2I7NEJBQ0wsQ0FBQyxDQUFDLENBQUM7eUJBQ1Y7NkJBQU07NEJBQ0gsZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFDO3lCQUNoQztvQkFDTCxDQUFDLENBQUM7eUJBQ0QsS0FBSyxDQUFDLFVBQUEsS0FBSzt3QkFDUixLQUFJLENBQUMsMEJBQTBCLENBQUMsV0FBUyxFQUFFLGtCQUFrQixDQUFDLENBQUM7d0JBQy9ELElBQUksU0FBUyxFQUFFLFlBQVksQ0FBQzt3QkFDNUIsUUFBUSxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFOzRCQUM5QixLQUFLLGVBQWU7Z0NBQ2hCLFNBQVMsQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDO29DQUNoQyxLQUFLLEVBQUUsS0FBSztvQ0FDWixLQUFLLEVBQUUsV0FBVyxDQUFDLEtBQUs7aUNBQzNCLENBQUM7cUNBQ0csSUFBSSxDQUFDLFVBQUEsV0FBVztvQ0FDYixXQUFXLENBQUMsY0FBYyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQUMsS0FBSzt3Q0FDdkMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO29DQUNqQixDQUFDLENBQUMsQ0FBQztvQ0FDSCxTQUFTLEdBQUcsaUNBQWlCLENBQUMsNEJBQTRCLENBQUM7b0NBQzNELFlBQVksR0FBRyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7b0NBQ2hDLGFBQWEsQ0FBQyxJQUFJLDZCQUFhLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7Z0NBQzlELENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFBLENBQUM7b0NBQ04sU0FBUyxHQUFHLGlDQUFpQixDQUFDLDRCQUE0QixDQUFDO29DQUMzRCxZQUFZLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO29DQUNoQyxhQUFhLENBQUMsSUFBSSw2QkFBYSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO2dDQUM5RCxDQUFDLENBQUMsQ0FBQztnQ0FDUCxNQUFNOzRCQUNWLEtBQUssaUJBQWlCO2dDQUNsQixTQUFTLEdBQUcsS0FBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsaUNBQWlCLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLGlDQUFpQixDQUFDLG9CQUFvQixDQUFDO2dDQUMxSCxZQUFZLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO2dDQUNoQyxhQUFhLENBQUMsSUFBSSw2QkFBYSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO2dDQUMxRCxNQUFNOzRCQUNWLEtBQUssc0JBQXNCO2dDQUN2QixTQUFTLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQztvQ0FDaEMsS0FBSyxFQUFFLEtBQUs7b0NBQ1osS0FBSyxFQUFFLFdBQVcsQ0FBQyxLQUFLO2lDQUMzQixDQUFDO3FDQUNHLElBQUksQ0FBQyxVQUFBLFdBQVc7b0NBQ2IsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFDLEtBQUs7d0NBQ3ZDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQ0FDakIsQ0FBQyxDQUFDLENBQUM7b0NBQ0gsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxLQUFLLFVBQVUsRUFBRTt3Q0FDL0MsU0FBUyxHQUFHLGlDQUFpQixDQUFDLDRCQUE0QixDQUFDO3dDQUMzRCxZQUFZLEdBQUcsb0NBQW9DLEdBQTBELFdBQVcsQ0FBQyxLQUFNLENBQUMsUUFBVyxDQUFDLEtBQUssR0FBRyxhQUFhLENBQUM7cUNBQ3JLO3lDQUFNO3dDQUNILFNBQVMsR0FBRyxpQ0FBaUIsQ0FBQywwQkFBMEIsQ0FBQzt3Q0FDekQsWUFBWSxHQUFHLHNFQUFzRSxHQUFHLEtBQUssQ0FBQyxVQUFVLEdBQUcsR0FBRyxDQUFDO3FDQUNsSDtvQ0FDRCxhQUFhLENBQUMsSUFBSSw2QkFBYSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO2dDQUM5RCxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBQSxDQUFDO29DQUNOLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxXQUFXLEVBQUUsS0FBSyxVQUFVLEVBQUU7d0NBQy9DLFNBQVMsR0FBRyxpQ0FBaUIsQ0FBQyw0QkFBNEIsQ0FBQzt3Q0FDM0QsWUFBWSxHQUFHLG9DQUFvQyxHQUEwRCxXQUFXLENBQUMsS0FBTSxDQUFDLFFBQVcsQ0FBQyxLQUFLLEdBQUcsYUFBYSxDQUFDO3FDQUNySzt5Q0FBTTt3Q0FDSCxTQUFTLEdBQUcsaUNBQWlCLENBQUMsMEJBQTBCLENBQUM7d0NBQ3pELFlBQVksR0FBRyxzRUFBc0UsR0FBRyxLQUFLLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQztxQ0FDbEg7b0NBQ0QsYUFBYSxDQUFDLElBQUksNkJBQWEsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztnQ0FDOUQsQ0FBQyxDQUFDLENBQUM7Z0NBQ1AsTUFBTTt5QkFDYjtvQkFDTCxDQUFDLENBQUMsQ0FBQztpQkFDVjtxQkFBTTtvQkFDSCxNQUFNLENBQUMsSUFBSSw2QkFBYSxDQUFDLGlDQUFpQixDQUFDLG1CQUFtQixFQUMxRCxrSUFBa0ksQ0FBQyxDQUFDLENBQUM7aUJBQzVJO1lBQ0wsQ0FBQyxDQUFDO2lCQUNELEtBQUssQ0FBQyxVQUFDLEtBQW9CO2dCQUN4QixhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDekIsQ0FBQyxDQUFDLENBQUM7UUFDWCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFLRCxpQ0FBYSxHQUFiLFVBQWMsT0FBZ0I7UUFDMUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQ2xDLENBQUM7SUFLRCw2QkFBUyxHQUFULFVBQVUsSUFBWSxFQUFFLFVBQWlCO1FBQ3JDLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBS0QsaURBQTZCLEdBQTdCO1FBQ0ksSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQ2xELElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1NBQ25DO0lBQ0wsQ0FBQztJQUtPLDRDQUF3QixHQUFoQyxVQUFpQyxRQUFnQjtRQUFqRCxpQkFJQztRQUhHLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxVQUFVLENBQUM7WUFDdEMsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDaEQsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2pCLENBQUM7SUFFTyw4Q0FBMEIsR0FBbEMsVUFBbUMsU0FBaUIsRUFBRSxRQUFnQjtRQUNsRSxZQUFZLENBQUMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsR0FBRyxRQUFRLEVBQUU7WUFFckMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsRUFBRSxDQUFDLENBQUM7U0FDL0M7SUFDTCxDQUFDO0lBRUwsZ0JBQUM7QUFBRCxDQXJYQSxBQXFYQyxDQXJYOEIsNkJBQWEsR0FxWDNDO0FBclhZLDhCQUFTOzs7OztBQ2hCdEIsMkNBQTBDO0FBSzFDLDJDQUEwQztBQU8xQyw4RUFBNkU7QUFFN0UsNEVBQTJFO0FBQzNFLGdHQUErRjtBQUMvRixzRUFBcUU7QUFDckUsc0VBQXFFO0FBQ3JFLHlFQUEyRjtBQUMzRiw2RUFBNEU7QUFFNUUsbUNBQXNDO0FBQ3RDLG1EQUFzRDtBQVF0RDtJQTZDSSxpQkFBWSxRQUFrQjtRQTlCOUIsbUJBQWMsR0FBb0IsRUFBRSxDQUFDO1FBTXJDLHlCQUFvQixHQUFvQixFQUFFLENBQUM7UUFLM0Msc0JBQWlCLEdBQXVCLEVBQUUsQ0FBQztRQVkzQywwQkFBcUIsR0FBRyxLQUFLLENBQUM7UUFFdEIsT0FBRSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFNNUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDN0IsQ0FBQztJQWdDRCx5QkFBTyxHQUFQLFVBQVEsS0FBYSxFQUFFLFFBQWM7UUFBckMsaUJBcUJDO1FBcEJHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUUvQixLQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBRXpCLElBQUksS0FBSSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsRUFBRSxFQUFFO2dCQUV6QyxLQUFJLENBQUMsT0FBTyxHQUFHO29CQUNYLFNBQVMsRUFBRSxLQUFJLENBQUMsU0FBUztvQkFDekIsYUFBYSxFQUFFLEtBQUs7b0JBQ3BCLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFJLENBQUMsb0JBQW9CLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7aUJBQ2xFLENBQUM7Z0JBQ0YsS0FBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUM7b0JBQ3hCLE9BQU8sRUFBRSxDQUFDO2dCQUNkLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFBLEtBQUs7b0JBQ1YsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNsQixDQUFDLENBQUMsQ0FBQzthQUNOO2lCQUFNO2dCQUNILE1BQU0sQ0FBQyxJQUFJLDZCQUFhLENBQUMsaUNBQWlCLENBQUMscUJBQXFCLEVBQUUsVUFBVSxHQUFHLFFBQVEsQ0FBQyxJQUFJLEdBQUcsR0FBRyxHQUFHLFFBQVEsQ0FBQyxPQUFPLEdBQUcsK0JBQStCLENBQUMsQ0FBQyxDQUFDO2FBQzdKO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBNkJELDRCQUFVLEdBQVY7UUFDSSxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBc0JELDJCQUFTLEdBQVQsVUFBVSxNQUFjLEVBQUUsYUFBbUMsRUFBRSxNQUFvRSxFQUFFLE1BQTZDO1FBQzlLLElBQUksVUFBVSxHQUF5QixFQUFFLENBQUM7UUFDMUMsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLE9BQU8sTUFBTSxLQUFLLFVBQVUsRUFBRTtZQUMxQyxVQUFVLEdBQUc7Z0JBQ1QsVUFBVSxFQUFFLENBQUMsT0FBTyxNQUFNLENBQUMsVUFBVSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxNQUFNLENBQUMsVUFBVSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxpQ0FBZSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxpQ0FBZSxDQUFDLE1BQU07Z0JBQ3hMLGdCQUFnQixFQUFFLENBQUMsT0FBTyxNQUFNLENBQUMsZ0JBQWdCLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDbkcsZ0JBQWdCLEVBQUUsQ0FBQyxPQUFPLE1BQU0sQ0FBQyxnQkFBZ0IsS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxJQUFJO2FBQ3RHLENBQUM7U0FDTDthQUFNO1lBQ0gsVUFBVSxHQUFHO2dCQUNULFVBQVUsRUFBRSxpQ0FBZSxDQUFDLE1BQU07Z0JBQ2xDLGdCQUFnQixFQUFFLElBQUk7Z0JBQ3RCLGdCQUFnQixFQUFFLElBQUk7YUFDekIsQ0FBQztTQUNMO1FBRUQsSUFBSSxpQkFBcUQsQ0FBQztRQUMxRCxJQUFJLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxPQUFPLE1BQU0sS0FBSyxVQUFVLENBQUMsRUFBRTtZQUM1QyxpQkFBaUIsR0FBRyxNQUFNLENBQUM7U0FDOUI7YUFBTSxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUU7WUFDakIsaUJBQWlCLEdBQUcsTUFBTSxDQUFDO1NBQzlCO1FBRUQsT0FBTyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRWpFLE1BQU0sQ0FBQyxTQUFTLEVBQUU7YUFDYixJQUFJLENBQUM7WUFDRixPQUFPLENBQUMsSUFBSSxDQUFDLDBCQUEwQixHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDMUUsSUFBSSxpQkFBaUIsS0FBSyxTQUFTLEVBQUU7Z0JBQ2pDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQ2hDO1FBQ0wsQ0FBQyxDQUFDO2FBQ0QsS0FBSyxDQUFDLFVBQUEsS0FBSztZQUNSLElBQUksaUJBQWlCLEtBQUssU0FBUyxFQUFFO2dCQUNqQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUM1QjtRQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ1AsSUFBTSxVQUFVLEdBQUcsSUFBSSx1QkFBVSxDQUFDLE1BQU0sRUFBRSxhQUFhLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDLGFBQWEsRUFBRTtZQUM1QixNQUFNLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQW1CLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUM3RztRQUNELE9BQU8sVUFBVSxDQUFDO0lBQ3RCLENBQUM7SUFTRCxnQ0FBYyxHQUFkLFVBQWUsTUFBYyxFQUFFLGFBQW1DLEVBQUUsVUFBaUM7UUFBckcsaUJBb0JDO1FBbkJHLE9BQU8sSUFBSSxPQUFPLENBQWEsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUUzQyxJQUFJLFVBQXNCLENBQUM7WUFFM0IsSUFBTSxRQUFRLEdBQUcsVUFBQyxLQUFZO2dCQUMxQixJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUU7b0JBQ1QsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2lCQUNqQjtxQkFBTTtvQkFDSCxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7aUJBQ3ZCO1lBQ0wsQ0FBQyxDQUFDO1lBRUYsSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFO2dCQUNkLFVBQVUsR0FBRyxLQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2FBQzVFO2lCQUFNO2dCQUNILFVBQVUsR0FBRyxLQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxhQUFhLEVBQUUsUUFBUSxDQUFDLENBQUM7YUFDaEU7UUFFTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFhRCw2QkFBVyxHQUFYLFVBQVksVUFBc0I7UUFDOUIsSUFBTSxZQUFZLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDO1FBRS9ELE9BQU8sQ0FBQyxJQUFJLENBQUMscUJBQXFCLEdBQUcsWUFBWSxDQUFDLENBQUM7UUFFbkQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQ3JCLHNCQUFzQixFQUN0QixFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLEVBQUUsRUFDckQsVUFBQyxLQUFLLEVBQUUsUUFBUTtZQUNaLElBQUksS0FBSyxFQUFFO2dCQUNQLE9BQU8sQ0FBQyxLQUFLLENBQUMsMkJBQTJCLEdBQUcsWUFBWSxFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQ3BFO2lCQUFNO2dCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsOEJBQThCLEdBQUcsWUFBWSxDQUFDLENBQUM7YUFDL0Q7WUFDRCxVQUFVLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDdEMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzNDLENBQUMsQ0FDSixDQUFDO1FBQ0YsVUFBVSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDdEQsQ0FBQztJQWdCRCx5QkFBTyxHQUFQLFVBQVEsU0FBb0I7UUFBNUIsaUJBaUNDO1FBaENHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUMvQixTQUFTLENBQUMsT0FBTyxHQUFHLEtBQUksQ0FBQztZQUN6QixTQUFTLENBQUMsTUFBTSxDQUFDLE9BQU8sR0FBRyxLQUFJLENBQUM7WUFFaEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsc0JBQXNCLEVBQUU7Z0JBRTFDLEtBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDNUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7cUJBQ3JCLElBQUksQ0FBQztvQkFDRixPQUFPLEVBQUUsQ0FBQztnQkFDZCxDQUFDLENBQUM7cUJBQ0QsS0FBSyxDQUFDLFVBQUEsS0FBSztvQkFDUixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ2xCLENBQUMsQ0FBQyxDQUFDO2FBQ1Y7aUJBQU07Z0JBRUgsU0FBUyxDQUFDLFVBQVUsRUFBRTtxQkFDakIsSUFBSSxDQUFDO29CQUNGLEtBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztvQkFDNUMsU0FBUyxDQUFDLDZCQUE2QixFQUFFLENBQUM7b0JBQzFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO3lCQUNyQixJQUFJLENBQUM7d0JBQ0YsT0FBTyxFQUFFLENBQUM7b0JBQ2QsQ0FBQyxDQUFDO3lCQUNELEtBQUssQ0FBQyxVQUFBLEtBQUs7d0JBQ1IsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUNsQixDQUFDLENBQUMsQ0FBQztnQkFDWCxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBQyxLQUFLO29CQUNYLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDbEIsQ0FBQyxDQUFDLENBQUM7YUFDVjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQXNCRCwyQkFBUyxHQUFULFVBQVUsU0FBb0I7UUFFMUIsSUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUVoQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRTtZQUNwQixPQUFPLENBQUMsS0FBSyxDQUFDLDREQUE0RCxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3BGLE9BQU87U0FDVjthQUFNLElBQUksTUFBTSxDQUFDLFVBQVUsS0FBSyxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQzlDLE9BQU8sQ0FBQyxLQUFLLENBQUMsa0ZBQWtGO2dCQUM1RixtRkFBbUYsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNqRyxPQUFPO1NBQ1Y7YUFBTTtZQUVILE9BQU8sQ0FBQyxJQUFJLENBQUMsNEJBQTRCLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLEdBQUcsR0FBRyxDQUFDLENBQUM7WUFFbEYsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsVUFBQyxLQUFLLEVBQUUsUUFBUTtnQkFDeEQsSUFBSSxLQUFLLEVBQUU7b0JBQ1AsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDeEI7cUJBQU07b0JBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO2lCQUMvQztZQUNMLENBQUMsQ0FBQyxDQUFDO1lBRUgsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDM0IsT0FBTyxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQztZQUVoQyxJQUFNLFdBQVcsR0FBRyxJQUFJLHlCQUFXLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3ZHLFNBQVMsQ0FBQyxTQUFTLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1lBQ3RELFdBQVcsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1NBQ3RDO0lBQ0wsQ0FBQztJQWVELHdCQUFNLEdBQU4sVUFBTyxNQUFxQjtRQUE1QixpQkE2QkM7UUE1QkcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBRS9CLElBQU0sYUFBYSxHQUFHLEVBQUUsQ0FBQztZQUV6QixJQUFJLE1BQU0sQ0FBQyxFQUFFLElBQUksTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUNuQyxJQUFNLGVBQWEsR0FBYSxFQUFFLENBQUM7Z0JBRW5DLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQUEsVUFBVTtvQkFDeEIsZUFBYSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQ2hELENBQUMsQ0FBQyxDQUFDO2dCQUNILGFBQWEsQ0FBQyxJQUFJLENBQUMsR0FBRyxlQUFhLENBQUM7YUFDdkM7aUJBQU07Z0JBQ0gsYUFBYSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQzthQUM1QjtZQUVELGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDdkQsYUFBYSxDQUFDLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUV2RCxLQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxhQUFhLEVBQUU7Z0JBQ3JDLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQzthQUN6QyxFQUFFLFVBQUMsS0FBSyxFQUFFLFFBQVE7Z0JBQ2YsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFO29CQUNULE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDakI7cUJBQU07b0JBQ0gsT0FBTyxFQUFFLENBQUM7aUJBQ2I7WUFDTCxDQUFDLENBQUMsQ0FBQztRQUNQLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQU9ELG9CQUFFLEdBQUYsVUFBRyxJQUFZLEVBQUUsT0FBMEk7UUFFdkosSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQUEsS0FBSztZQUNsQixJQUFJLEtBQUssRUFBRTtnQkFDUCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLEdBQUcsMEJBQTBCLEVBQUUsS0FBSyxDQUFDLENBQUM7YUFDdEU7aUJBQU07Z0JBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxHQUFHLDBCQUEwQixDQUFDLENBQUM7YUFDL0Q7WUFDRCxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLElBQUksS0FBSyx3QkFBd0IsSUFBSSxJQUFJLEtBQUssdUJBQXVCLEVBQUU7WUFDdkUsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQztZQUVsQyxLQUFLLElBQU0sWUFBWSxJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtnQkFDL0MsSUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFDeEQsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsSUFBSSxHQUFHLENBQUMsUUFBUSxFQUFFO29CQUMzQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztpQkFDOUI7YUFDSjtTQUNKO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQU1ELHNCQUFJLEdBQUosVUFBSyxJQUFZLEVBQUUsT0FBMEk7UUFDekosSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQUEsS0FBSztZQUNwQixJQUFJLEtBQUssRUFBRTtnQkFDUCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLEdBQUcsMEJBQTBCLEVBQUUsS0FBSyxDQUFDLENBQUM7YUFDdEU7aUJBQU07Z0JBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxHQUFHLDBCQUEwQixDQUFDLENBQUM7YUFDL0Q7WUFDRCxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLElBQUksS0FBSyx3QkFBd0IsSUFBSSxJQUFJLEtBQUssdUJBQXVCLEVBQUU7WUFDdkUsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQztZQUdsQyxLQUFLLElBQU0sWUFBWSxJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtnQkFDL0MsSUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFDeEQsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsSUFBSSxHQUFHLENBQUMsUUFBUSxFQUFFO29CQUMzQyxHQUFHLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztpQkFDbEM7YUFDSjtTQUNKO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQU1ELHFCQUFHLEdBQUgsVUFBSSxJQUFZLEVBQUUsT0FBMkk7UUFFekosSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNWLElBQUksQ0FBQyxFQUFFLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDcEM7YUFBTTtZQUNILElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztTQUM5QjtRQUVELElBQUksSUFBSSxLQUFLLHdCQUF3QixJQUFJLElBQUksS0FBSyx1QkFBdUIsRUFBRTtZQUN2RSxJQUFJLENBQUMscUJBQXFCLEdBQUcsS0FBSyxDQUFDO1lBR25DLEtBQUssSUFBTSxZQUFZLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUMvQyxJQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLENBQUMsTUFBTSxDQUFDO2dCQUN4RCxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUU7b0JBQzVCLEdBQUcsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO2lCQUMvQjthQUNKO1NBQ0o7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBUUQscUNBQW1CLEdBQW5CLFVBQW9CLFFBQTJCO1FBQS9DLGlCQVlDO1FBVkcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQzthQUU5QixJQUFJLENBQUMsVUFBQSxVQUFVO1lBQ1osT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLEdBQUcsUUFBUSxDQUFDLEVBQUUsR0FBRyxxQ0FBcUMsQ0FBQyxDQUFDO1FBQ3RGLENBQUMsQ0FBQzthQUNELEtBQUssQ0FBQyxVQUFBLGFBQWE7WUFDaEIsSUFBTSxVQUFVLEdBQUcsSUFBSSx1QkFBVSxDQUFDLEtBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNsRCxLQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLFVBQVUsQ0FBQztZQUNqRCxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLElBQUksaUNBQWUsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLG1CQUFtQixFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEgsQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBS0QsbUNBQWlCLEdBQWpCLFVBQWtCLEdBQUc7UUFBckIsaUJBb0JDO1FBbkJHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLG9CQUFvQixHQUFHLEdBQUcsQ0FBQyxJQUFJLEdBQUcscUNBQXFDO1lBQ3RHLCtCQUErQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO2FBRXJGLElBQUksQ0FBQyxVQUFBLFVBQVU7WUFDWixJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFO2dCQUNyQixJQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDO2dCQUVqQyxJQUFNLFdBQVcsR0FBRyxJQUFJLHlCQUFXLENBQUMsSUFBSSxFQUFFLEtBQUksRUFBRSxpQkFBaUIsRUFBRSxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUN2RixLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7Z0JBQ3BELFdBQVcsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO2dCQUVuQyxPQUFPLEtBQUksQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDckQ7WUFDRCxPQUFPLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdkQsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxJQUFJLGlDQUFlLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSxxQkFBcUIsRUFBRSxVQUFVLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoSSxDQUFDLENBQUM7YUFDRCxLQUFLLENBQUMsVUFBQSxhQUFhO1lBQ2hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDakMsQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBS0Qsd0NBQXNCLEdBQXRCLFVBQXVCLFFBQTJCO1FBQWxELGlCQW1DQztRQWpDRyxJQUFNLG9CQUFvQixHQUFHLFVBQUMsVUFBVTtZQUNwQyxLQUFJLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxHQUFHLFVBQVUsQ0FBQztZQUU3RCxJQUFJLENBQUMsS0FBSSxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUU7Z0JBS3hELEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxDQUFDLElBQUkseUJBQVcsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLGVBQWUsRUFBRSxVQUFVLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUM5RztZQUVELEtBQUksQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQztRQUNqRSxDQUFDLENBQUM7UUFJRixJQUFJLFVBQXNCLENBQUM7UUFDM0IsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUUscUJBQXFCLEdBQUcsUUFBUSxDQUFDLEVBQUUsR0FBRywyQ0FBMkM7WUFDbkgsK0JBQStCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7YUFFckYsSUFBSSxDQUFDLFVBQUEsR0FBRztZQUVMLFVBQVUsR0FBRyxHQUFHLENBQUM7WUFDakIsUUFBUSxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO1lBQzdCLFVBQVUsQ0FBQyxPQUFPLEdBQUcsUUFBUSxDQUFDO1lBQzlCLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDL0Msb0JBQW9CLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDckMsQ0FBQyxDQUFDO2FBQ0QsS0FBSyxDQUFDLFVBQUEsYUFBYTtZQUVoQixVQUFVLEdBQUcsSUFBSSx1QkFBVSxDQUFDLEtBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztZQUM1QyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNyQyxDQUFDLENBQUMsQ0FBQztJQUNYLENBQUM7SUFLRCwwQ0FBd0IsR0FBeEIsVUFBeUIsR0FBRztRQUE1QixpQkFrQkM7UUFqQkcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUscUJBQXFCLEdBQUcsR0FBRyxDQUFDLElBQUksR0FBRyw2Q0FBNkM7WUFDL0csK0JBQStCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7YUFFckYsSUFBSSxDQUFDLFVBQUEsVUFBVTtZQUVaLElBQU0sV0FBVyxHQUFHLElBQUkseUJBQVcsQ0FBQyxJQUFJLEVBQUUsS0FBSSxFQUFFLGlCQUFpQixFQUFFLFVBQVUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2xHLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGlCQUFpQixFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztZQUNwRCxXQUFXLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztZQUduQyxJQUFNLFFBQVEsR0FBVyxVQUFVLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztZQUNwRCxPQUFPLEtBQUksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMzQyxVQUFVLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQzthQUNELEtBQUssQ0FBQyxVQUFBLGFBQWE7WUFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztJQUNYLENBQUM7SUFLRCxzQ0FBb0IsR0FBcEIsVUFBcUIsR0FBRztJQXFCeEIsQ0FBQztJQUtELDhCQUFZLEdBQVosVUFBYSxHQUFHO1FBQWhCLGlCQWNDO1FBWkcsT0FBTyxDQUFDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRW5ELElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxjQUFjLEdBQUcsR0FBRyxDQUFDLElBQUksR0FBRyw2REFBNkQ7Y0FDaEgsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEdBQUcsK0JBQStCLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUM7YUFFdEgsSUFBSSxDQUFDLFVBQUEsVUFBVTtZQUNaLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxDQUFDLElBQUkseUJBQVcsQ0FBQyxLQUFJLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNyRixLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLElBQUkseUJBQVcsQ0FBQyxLQUFJLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNyRyxDQUFDLENBQUM7YUFDRCxLQUFLLENBQUMsVUFBQSxhQUFhO1lBQ2hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDakMsQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBS0Qsa0NBQWdCLEdBQWhCLFVBQWlCLEdBQUc7UUFDaEIsSUFBTSxTQUFTLEdBQUc7WUFDZCxTQUFTLEVBQUUsR0FBRyxDQUFDLFNBQVM7WUFDeEIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNO1lBQ2xCLGFBQWEsRUFBRSxHQUFHLENBQUMsYUFBYTtZQUNoQyxNQUFNLEVBQUU7Z0JBQ0osT0FBTyxFQUFFLFNBQVMsRUFBRSxHQUFHLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDeEMsQ0FBQztTQUNKLENBQUM7UUFDRixJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsb0NBQW9DLEdBQUcsR0FBRyxDQUFDLFlBQVksR0FBRyxtQ0FBbUMsR0FBRyxTQUFTLENBQUM7YUFDMUksSUFBSSxDQUFDLFVBQUEsVUFBVTtZQUNaLElBQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7WUFDakMsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBQSxLQUFLO2dCQUN6RCxPQUFPLENBQUMsS0FBSyxDQUFDLDZCQUE2QixHQUFHLE1BQU0sQ0FBQyxRQUFRO3NCQUN2RCxzQkFBc0IsR0FBRyxHQUFHLENBQUMsWUFBWSxHQUFHLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQztZQUNwRSxDQUFDLENBQUMsQ0FBQztRQUNQLENBQUMsQ0FBQzthQUNELEtBQUssQ0FBQyxVQUFBLGFBQWE7WUFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztJQUNYLENBQUM7SUFLRCxpQ0FBZSxHQUFmLFVBQWdCLEdBQUc7UUFDZixPQUFPLENBQUMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN2RCxJQUFNLENBQUMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ25CLElBQUksQ0FBQyxLQUFLLFNBQVMsRUFBRTtZQUNqQixJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO29CQUNqQyxPQUFPLEVBQUUsQ0FBQztpQkFDYixDQUFDLENBQUMsQ0FBQztTQUNQO2FBQU07WUFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLHFDQUFxQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQzVEO0lBQ0wsQ0FBQztJQUtELGtDQUFnQixHQUFoQjtRQWFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsNkJBQTZCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRTtZQUMvQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1NBQ3pDO0lBQ0wsQ0FBQztJQUtELDhCQUFZLEdBQVosVUFBYSxNQUFNO1FBRWYsT0FBTyxDQUFDLEtBQUssQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3hELElBQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7UUFDekIsSUFBSSxHQUFHLEVBQUU7WUFDTCxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztvQkFDOUIsS0FBSyxFQUFFLEdBQUc7aUJBQ2IsQ0FBQyxDQUFDLENBQUM7U0FDUDthQUFNO1lBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyx5Q0FBeUMsRUFBRSxNQUFNLENBQUMsQ0FBQztTQUNuRTtJQUNMLENBQUM7SUFLRCxvQ0FBa0IsR0FBbEIsVUFBbUIsUUFBUTtRQUN2QixJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLElBQUksK0JBQWMsQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RILENBQUM7SUFLRCxvQ0FBa0IsR0FBbEIsVUFBbUIsUUFBUTtRQUN2QixJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLElBQUksK0JBQWMsQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RILENBQUM7SUFLRCwyQkFBUyxHQUFULFVBQVUsSUFBWSxFQUFFLFVBQWlCO1FBQ3JDLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBS0QsdUJBQUssR0FBTCxVQUFNLE1BQWUsRUFBRSxNQUFjO1FBQXJDLGlCQW1DQztRQWpDRyxNQUFNLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztRQUNsQixPQUFPLENBQUMsSUFBSSxDQUFDLDBCQUEwQixHQUFHLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQztRQUV4RCxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDdEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLFVBQUMsS0FBSyxFQUFFLFFBQVE7b0JBQ25ELElBQUksS0FBSyxFQUFFO3dCQUNQLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7cUJBQ3hCO29CQUNELEtBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQzVCLENBQUMsQ0FBQyxDQUFDO2FBQ047aUJBQU07Z0JBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQzthQUMzQjtZQUVELElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFO2dCQUUxQixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO2dCQUMzQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLHNCQUFzQixFQUFFO29CQUUvQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLHNDQUFzQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztpQkFDekY7YUFDSjtZQUVELElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRTtnQkFFM0IsSUFBTSxzQkFBc0IsR0FBRyxJQUFJLG1EQUF3QixDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDMUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUM7Z0JBQ25FLHNCQUFzQixDQUFDLG9CQUFvQixFQUFFLENBQUM7YUFDakQ7U0FDSjthQUFNO1lBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyx3Q0FBd0MsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDM0U7SUFDTCxDQUFDO0lBS08sNEJBQVUsR0FBbEIsVUFBbUIsS0FBYTtRQUFoQyxpQkE0REM7UUEzREcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQy9CLEtBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFVBQUMsS0FBSztnQkFDeEIsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFO29CQUNULE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDakI7cUJBQU07b0JBRUgsSUFBTSxVQUFVLEdBQUc7d0JBQ2YsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUU7d0JBQzdCLE9BQU8sRUFBRSxLQUFJLENBQUMsU0FBUzt3QkFDdkIsUUFBUSxFQUFFLENBQUMsQ0FBQyxLQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUU7d0JBQzlELE1BQU0sRUFBRSxLQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRTt3QkFDakMsUUFBUSxFQUFFLEtBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFO3FCQUN4QyxDQUFDO29CQUVGLEtBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBQyxLQUFLLEVBQUUsUUFBUTt3QkFDOUQsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFOzRCQUNULE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQzt5QkFDakI7NkJBQU07NEJBR0gsS0FBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLHVCQUFVLENBQUMsS0FBSSxDQUFDLENBQUM7NEJBQ3ZDLEtBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxHQUFHLFFBQVEsQ0FBQyxFQUFFLENBQUM7NEJBQzNDLEtBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUM7NEJBR3pDLElBQU0sUUFBTSxHQUFHO2dDQUNYLFdBQVcsRUFBRSxJQUFJLEtBQUssRUFBYztnQ0FDcEMsT0FBTyxFQUFFLElBQUksS0FBSyxFQUFVOzZCQUMvQixDQUFDOzRCQUNGLElBQU0sb0JBQW9CLEdBQXdCLFFBQVEsQ0FBQyxLQUFLLENBQUM7NEJBQ2pFLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxVQUFBLFdBQVc7Z0NBQ3BDLElBQU0sVUFBVSxHQUFHLElBQUksdUJBQVUsQ0FBQyxLQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7Z0NBQ3JELEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLEdBQUcsVUFBVSxDQUFDO2dDQUM3RCxRQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztnQ0FDcEMsSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRTtvQ0FDckIsS0FBSSxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsSUFBSSxDQUFDO29DQUM3RCxRQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7aUNBQzFDOzRCQUNMLENBQUMsQ0FBQyxDQUFDOzRCQUdILEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLG1CQUFtQixFQUFFLENBQUMsSUFBSSxpQ0FBZSxDQUFDLEtBQUssRUFBRSxLQUFJLEVBQUUsbUJBQW1CLEVBQUUsS0FBSSxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7NEJBR3JILFFBQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLFVBQUEsVUFBVTtnQ0FDakMsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxJQUFJLGlDQUFlLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSxtQkFBbUIsRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDOzRCQUNwSCxDQUFDLENBQUMsQ0FBQzs0QkFHSCxRQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxVQUFBLE1BQU07Z0NBQ3pCLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxDQUFDLElBQUkseUJBQVcsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLGVBQWUsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDOzRCQUNwRyxDQUFDLENBQUMsQ0FBQzs0QkFFSCxPQUFPLEVBQUUsQ0FBQzt5QkFDYjtvQkFDTCxDQUFDLENBQUMsQ0FBQztpQkFDTjtZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sc0NBQW9CLEdBQTVCLFVBQTZCLFFBQWE7UUFDdEMsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLEVBQUU7WUFDOUIsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ25DO2FBQU07WUFDSCxPQUFPLFFBQVEsQ0FBQztTQUNuQjtJQUNMLENBQUM7SUFFTywrQkFBYSxHQUFyQixVQUFzQixZQUFvQixFQUFFLFlBQW9CO1FBQWhFLGlCQWdCQztRQWZHLE9BQU8sSUFBSSxPQUFPLENBQWEsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUMzQyxJQUFNLFVBQVUsR0FBRyxLQUFJLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDeEQsSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFO2dCQUVkLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUN2QjtpQkFBTTtnQkFDSCxJQUFJLEtBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxLQUFLLFlBQVksRUFBRTtvQkFFL0MsT0FBTyxDQUFDLEtBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztpQkFDNUI7cUJBQU07b0JBRUgsTUFBTSxDQUFDLElBQUksNkJBQWEsQ0FBQyxpQ0FBaUIsQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztpQkFDNUU7YUFDSjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLHFDQUFtQixHQUEzQixVQUE0QixZQUFvQixFQUFFLFlBQW9CO1FBQXRFLGlCQVdDO1FBVkcsT0FBTyxJQUFJLE9BQU8sQ0FBYSxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQzNDLElBQU0sVUFBVSxHQUFHLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN4RCxJQUFJLENBQUMsQ0FBQyxVQUFVLEVBQUU7Z0JBRWQsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ3ZCO2lCQUFNO2dCQUVILE1BQU0sQ0FBQyxJQUFJLDZCQUFhLENBQUMsaUNBQWlCLENBQUMsYUFBYSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7YUFDNUU7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFTyw4QkFBWSxHQUFwQixVQUFxQixLQUFhO1FBQzlCLElBQU0sR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyxTQUFTLEdBQVcsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDM0QsSUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUMsSUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbEQsSUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDMUQsSUFBTSxjQUFjLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUM5RCxJQUFNLElBQUksR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUUxQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUU7WUFDVixJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7U0FDakM7UUFDRCxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUU7WUFDWixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7U0FDakM7UUFDRCxJQUFJLENBQUMsQ0FBQyxZQUFZLElBQUksQ0FBQyxDQUFDLGNBQWMsRUFBRTtZQUNwQyxJQUFNLE9BQU8sR0FBRyxPQUFPLEdBQUcsR0FBRyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7WUFDakQsSUFBTSxRQUFRLEdBQUcsT0FBTyxHQUFHLEdBQUcsQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1lBQ2xELElBQU0sUUFBUSxHQUFHLFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQztZQUM3QyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsR0FBRztnQkFDdkIsRUFBRSxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRTtnQkFDbkIsRUFBRSxJQUFJLEVBQUUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUFFO2FBQ3JGLENBQUM7WUFDRixPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixHQUFHLFlBQVksR0FBRyxHQUFHLEdBQUcsY0FBYyxHQUFHLEdBQUcsQ0FBQyxDQUFBO1NBQ3JGO1FBQ0QsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFO1lBQ1IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1NBQzdCO1FBRUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEdBQUcsUUFBUSxHQUFHLEdBQUcsQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDO0lBQzVELENBQUM7SUFFTCxjQUFDO0FBQUQsQ0FwNUJBLEFBbzVCQyxJQUFBO0FBcDVCWSwwQkFBTzs7Ozs7QUN6QnBCLHdFQUFtSTtBQUNuSSwyRUFBMEU7QUFDMUUsNEZBQTJGO0FBRTNGLG1EQUFzRDtBQUN0RCwyQkFBOEI7QUFROUI7SUE4RUksZ0JBQVksT0FBZ0IsRUFBRSxPQUEwRDtRQUF4RixpQkFrQ0M7UUF2RUQsT0FBRSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFNaEIsd0JBQW1CLEdBQUcsS0FBSyxDQUFDO1FBS3BDLGdDQUEyQixHQUFHLEtBQUssQ0FBQztRQUlwQywyQkFBc0IsR0FBRyxLQUFLLENBQUM7UUF3QjNCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBRXZCLElBQUksT0FBTyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUU5QixJQUFJLENBQUMsaUJBQWlCLEdBQXlCLE9BQU8sQ0FBQztZQUN2RCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7WUFDMUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsU0FBUyxDQUFDO1lBQ2pELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQztZQUNqRCxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsQ0FBQztZQUMxRyxJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUM7U0FDN0c7YUFBTTtZQUVILElBQUksQ0FBQyxrQkFBa0IsR0FBMEIsT0FBTyxDQUFDO1lBRXpELElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFO2dCQUNwQixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFBRTtvQkFDckIsSUFBSSxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUM7aUJBQy9CO3FCQUFNO29CQUNILElBQUksQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUFDO2lCQUMvQjtnQkFDRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUM7YUFDMUU7aUJBQU07Z0JBQ0gsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO2FBQzNCO1lBQ0QsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDdEM7UUFFRCxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRTtZQUM5QixLQUFJLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUFDLEtBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN2RCxPQUFPLENBQUMsS0FBSyxDQUFDLG1CQUFtQixHQUFHLEtBQUksQ0FBQyxXQUFXLEdBQUcsdUJBQXVCLEdBQUcsS0FBSSxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUMxRyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFRRCwrQkFBYyxHQUFkO1FBQ0ksT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO0lBQzVCLENBQUM7SUFLRCwrQkFBYyxHQUFkLFVBQWUsV0FBd0I7UUFDbkMsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7SUFDbkMsQ0FBQztJQUtELDBDQUF5QixHQUF6QjtRQUNJLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLHFCQUFxQixDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUtELDhCQUFhLEdBQWI7UUFDSSxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDM0IsQ0FBQztJQUtELHFDQUFvQixHQUFwQjtRQUNJLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUtELG9DQUFtQixHQUFuQixVQUFvQixLQUFjO1FBQzlCLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxLQUFLLENBQUM7SUFDckMsQ0FBQztJQUtELHlDQUF3QixHQUF4QixVQUF5QixrQkFBeUM7UUFDOUQsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGtCQUFrQixDQUFDO0lBQ2pELENBQUM7SUFLRCwwQkFBUyxHQUFUO1FBQUEsaUJBVUM7UUFURyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsS0FBSSxDQUFDLHFCQUFxQixFQUFFO2lCQUN2QixJQUFJLENBQUM7Z0JBQ0YsT0FBTyxFQUFFLENBQUM7WUFDZCxDQUFDLENBQUM7aUJBQ0QsS0FBSyxDQUFDLFVBQUEsS0FBSztnQkFDUixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbEIsQ0FBQyxDQUFDLENBQUM7UUFDWCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFLRCx3QkFBTyxHQUFQO1FBQUEsaUJBc0JDO1FBckJHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUMvQixJQUFJLEtBQUksQ0FBQywyQkFBMkIsRUFBRTtnQkFDbEMsS0FBSSxDQUFDLGtCQUFrQixFQUFFO3FCQUNwQixJQUFJLENBQUM7b0JBQ0YsT0FBTyxFQUFFLENBQUM7Z0JBQ2QsQ0FBQyxDQUFDO3FCQUNELEtBQUssQ0FBQyxVQUFBLEtBQUs7b0JBQ1IsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNsQixDQUFDLENBQUMsQ0FBQzthQUNWO2lCQUFNO2dCQUNILEtBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLHlCQUF5QixFQUFFO29CQUNwQyxLQUFJLENBQUMsT0FBTyxFQUFFO3lCQUNULElBQUksQ0FBQzt3QkFDRixPQUFPLEVBQUUsQ0FBQztvQkFDZCxDQUFDLENBQUM7eUJBQ0QsS0FBSyxDQUFDLFVBQUEsS0FBSzt3QkFDUixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ2xCLENBQUMsQ0FBQyxDQUFDO2dCQUNYLENBQUMsQ0FBQyxDQUFDO2FBQ047UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFLRCxrQ0FBaUIsR0FBakI7UUFDSSxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDakIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUM3QjtRQUNELElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNsQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1NBQzNCO1FBRUQsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRXZCLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLG9DQUFvQyxHQUFHLElBQUksQ0FBQyxRQUFRLEdBQUcsaUJBQWlCLENBQUMsQ0FBQztJQUNwSixDQUFDO0lBS0QsbUNBQWtCLEdBQWxCO1FBQ0ksSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ2xCLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQUMsS0FBSztnQkFDNUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2pCLENBQUMsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBQyxLQUFLO2dCQUM1QyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDakIsQ0FBQyxDQUFDLENBQUM7WUFDSCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7U0FDM0I7UUFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxxQ0FBcUMsR0FBRyxJQUFJLENBQUMsUUFBUSxHQUFHLG1CQUFtQixDQUFDLENBQUM7SUFDbkosQ0FBQztJQUtELGdDQUFlLEdBQWY7UUFDSSxPQUFPLElBQUksQ0FBQyxtQkFBbUIsQ0FBQztJQUNwQyxDQUFDO0lBS0QsNEJBQVcsR0FBWDtRQUNJLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQjtZQUM3QixJQUFJLENBQUMsa0JBQWtCLENBQUMsbUJBQW1CLENBQUMsV0FBVyxLQUFLLElBQUk7WUFDaEUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLFdBQVcsS0FBSyxLQUFLLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBS0QsNEJBQVcsR0FBWDtRQUNJLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQjtZQUM3QixJQUFJLENBQUMsa0JBQWtCLENBQUMsbUJBQW1CLENBQUMsV0FBVyxLQUFLLElBQUk7WUFDaEUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLFdBQVcsS0FBSyxLQUFLLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBS0QsNkJBQVksR0FBWjtRQUNJLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQjtZQUM3QixJQUFJLENBQUMsa0JBQWtCLENBQUMsbUJBQW1CLENBQUMsV0FBVyxLQUFLLFFBQVEsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFLRCwwQ0FBeUIsR0FBekI7UUFDSSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNuQixJQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyw4QkFBOEIsSUFBSSxFQUFFLENBQUM7WUFDckcsV0FBVyxDQUFDLFFBQVEsR0FBRyxDQUFDLE9BQU8sV0FBVyxDQUFDLFFBQVEsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzlGLFdBQVcsQ0FBQyxTQUFTLEdBQUcsQ0FBQyxPQUFPLFdBQVcsQ0FBQyxTQUFTLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBRWxHLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDMUQ7SUFDTCxDQUFDO0lBS0QscUNBQW9CLEdBQXBCO1FBQUEsaUJBUUM7UUFQRyxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztRQUNqQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUU7WUFDNUIsS0FBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxJQUFJLCtDQUFzQixDQUFDLEtBQUksQ0FBQyxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsS0FBSSxDQUFDLFVBQVUsRUFBRSxLQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNKLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsa0JBQWtCLEVBQUU7WUFDcEMsS0FBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsdUJBQXVCLEVBQUUsQ0FBQyxJQUFJLCtDQUFzQixDQUFDLEtBQUksQ0FBQyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsS0FBSSxDQUFDLFVBQVUsRUFBRSxLQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3pKLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUtELHlDQUF3QixHQUF4QjtRQUFBLGlCQVVDO1FBVEcsSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFO1lBQzVCLEtBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLHdCQUF3QixFQUFFLENBQUMsSUFBSSwrQ0FBc0IsQ0FBQyxLQUFJLENBQUMsT0FBTyxFQUFFLHdCQUF3QixFQUFFLEtBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN2SixLQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLGtCQUFrQixFQUFFO1lBQ3BDLEtBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLHVCQUF1QixFQUFFLENBQUMsSUFBSSwrQ0FBc0IsQ0FBQyxLQUFJLENBQUMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLEtBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNySixLQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFLRCxzQ0FBcUIsR0FBckI7UUFDSSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDO0lBQ2pDLENBQUM7SUFLRCx3QkFBTyxHQUFQO1FBRUksT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBS0Qsd0NBQXVCLEdBQXZCO1FBQUEsaUJBTUM7UUFMRyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsS0FBSSxDQUFDLFdBQVcsQ0FBQywyQkFBMkIsRUFBRTtpQkFDekMsSUFBSSxDQUFDLFVBQUEsTUFBTSxJQUFJLE9BQUEsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFmLENBQWUsQ0FBQztpQkFDL0IsS0FBSyxDQUFDLFVBQUEsS0FBSyxJQUFJLE9BQUEsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFiLENBQWEsQ0FBQyxDQUFDO1FBQ3ZDLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUtELDBDQUF5QixHQUF6QjtRQUNJLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQztJQUNqRCxDQUFDO0lBS0QseUNBQXdCLEdBQXhCO1FBQ0ksT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLG9CQUFvQixDQUFDO0lBQ2hELENBQUM7SUFJTyxtQ0FBa0IsR0FBMUI7UUFBQSxpQkE2REM7UUE1REcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBRS9CLElBQU0sb0JBQW9CLEdBQUc7Z0JBQ3pCLEtBQUssRUFBRSxLQUFJLENBQUMsV0FBVyxFQUFFO2dCQUN6QixLQUFLLEVBQUUsS0FBSSxDQUFDLFdBQVcsRUFBRTthQUM1QixDQUFDO1lBRUYsSUFBTSxPQUFPLEdBQUc7Z0JBQ1osV0FBVyxFQUFFLEtBQUksQ0FBQyxXQUFXO2dCQUM3QixnQkFBZ0IsRUFBRSxvQkFBb0I7Z0JBQ3RDLGNBQWMsRUFBRSxLQUFJLENBQUMsVUFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFJLENBQUMsVUFBVSxDQUFDO2dCQUN0RSxVQUFVLEVBQUUsS0FBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUNwQyxTQUFTLEVBQUUsS0FBSzthQUNuQixDQUFDO1lBRUYsSUFBTSxlQUFlLEdBQUcsVUFBQyxhQUFhO2dCQUNsQyxPQUFPLENBQUMsS0FBSyxDQUFDLGtDQUFrQztzQkFDMUMsS0FBSSxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQztnQkFFcEMsS0FBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRTtvQkFDOUMsUUFBUSxFQUFFLGFBQWE7b0JBQ3ZCLFVBQVUsRUFBRSxLQUFJLENBQUMsZUFBZSxFQUFFLElBQUksS0FBSztvQkFDM0MsV0FBVyxFQUFFLEtBQUksQ0FBQyxXQUFXLEVBQUU7b0JBQy9CLFdBQVcsRUFBRSxLQUFJLENBQUMsV0FBVyxFQUFFO29CQUMvQixXQUFXLEVBQUUsQ0FBQyxDQUFDLEtBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO29CQUN0RixTQUFTLEVBQUUsQ0FBQyxDQUFDLEtBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEtBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDcEQsRUFBRSxVQUFDLEtBQUssRUFBRSxRQUFRO29CQUNmLElBQUksS0FBSyxFQUFFO3dCQUNQLE1BQU0sQ0FBQyx5QkFBeUIsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7cUJBQzdEO3lCQUFNO3dCQUNILEtBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7NkJBQzVDLElBQUksQ0FBQzs0QkFDRixLQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxFQUFFLENBQUM7NEJBQzVCLEtBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLENBQUM7NEJBQ25DLElBQUksS0FBSSxDQUFDLGVBQWUsRUFBRSxFQUFFO2dDQUN4QixLQUFJLENBQUMsZ0NBQWdDLEVBQUUsQ0FBQzs2QkFDM0M7NEJBQ0QsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsNkJBQTZCLENBQUMsQ0FBQzs0QkFDakQsS0FBSSxDQUFDLGVBQWUsRUFBRSxDQUFDOzRCQUN2QixPQUFPLEVBQUUsQ0FBQzt3QkFDZCxDQUFDLENBQUM7NkJBQ0QsS0FBSyxDQUFDLFVBQUEsS0FBSzs0QkFDUixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7d0JBQ2xCLENBQUMsQ0FBQyxDQUFDO3dCQUNQLE9BQU8sQ0FBQyxJQUFJLENBQUMsK0NBQStDLENBQUMsQ0FBQztxQkFDakU7Z0JBQ0wsQ0FBQyxDQUFDLENBQUM7WUFDUCxDQUFDLENBQUM7WUFFRixJQUFJLEtBQUksQ0FBQyxlQUFlLEVBQUUsRUFBRTtnQkFDeEIsS0FBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLCtCQUFrQixDQUFDLE9BQU8sQ0FBQyxDQUFDO2FBQ3JEO2lCQUFNO2dCQUNILEtBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSwrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQzthQUNyRDtZQUNELEtBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQUEsS0FBSztnQkFDdEMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzNCLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFBLEtBQUs7Z0JBQ1YsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLDZCQUE2QixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdFLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sc0NBQXFCLEdBQTdCO1FBQUEsaUJBOENDO1FBN0NHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUUvQixJQUFNLGdCQUFnQixHQUFHO2dCQUNyQixLQUFLLEVBQUUsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVM7Z0JBQ3ZDLEtBQUssRUFBRSxLQUFJLENBQUMsaUJBQWlCLENBQUMsU0FBUzthQUMxQyxDQUFDO1lBQ0YsT0FBTyxDQUFDLEtBQUssQ0FBQyx1RUFBdUUsRUFDakYsZ0JBQWdCLENBQUMsQ0FBQztZQUN0QixJQUFNLE9BQU8sR0FBRztnQkFDWixjQUFjLEVBQUUsS0FBSSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSSxDQUFDLFVBQVUsQ0FBQztnQkFDdEUsZ0JBQWdCLEVBQUUsZ0JBQWdCO2dCQUNsQyxVQUFVLEVBQUUsS0FBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUNwQyxTQUFTLEVBQUUsS0FBSzthQUNuQixDQUFDO1lBRUYsSUFBTSxlQUFlLEdBQUcsVUFBQyxhQUFhO2dCQUNsQyxPQUFPLENBQUMsS0FBSyxDQUFDLG9DQUFvQztzQkFDNUMsS0FBSSxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsQ0FBQztnQkFDcEMsS0FBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLGtCQUFrQixFQUFFO29CQUNsRCxNQUFNLEVBQUUsS0FBSSxDQUFDLFFBQVE7b0JBQ3JCLFFBQVEsRUFBRSxhQUFhO2lCQUMxQixFQUFFLFVBQUMsS0FBSyxFQUFFLFFBQVE7b0JBQ2YsSUFBSSxLQUFLLEVBQUU7d0JBQ1AsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLDBCQUEwQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO3FCQUN6RTt5QkFBTTt3QkFDSCxLQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSSxDQUFDOzRCQUNuRCxLQUFJLENBQUMsZ0NBQWdDLEVBQUUsQ0FBQzs0QkFDeEMsS0FBSSxDQUFDLGVBQWUsRUFBRSxDQUFDOzRCQUN2QixPQUFPLEVBQUUsQ0FBQzt3QkFDZCxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBQSxLQUFLOzRCQUNWLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQzt3QkFDbEIsQ0FBQyxDQUFDLENBQUM7cUJBQ047Z0JBQ0wsQ0FBQyxDQUFDLENBQUM7WUFDUCxDQUFDLENBQUM7WUFFRixLQUFJLENBQUMsVUFBVSxHQUFHLElBQUksK0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbEQsS0FBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUU7aUJBQzFCLElBQUksQ0FBQyxVQUFBLEtBQUs7Z0JBQ1AsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzNCLENBQUMsQ0FBQztpQkFDRCxLQUFLLENBQUMsVUFBQSxLQUFLO2dCQUNSLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQywrQkFBK0IsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMvRSxDQUFDLENBQUMsQ0FBQztRQUNYLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLGlEQUFnQyxHQUF4QztRQUNJLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1RCxPQUFPLENBQUMsS0FBSyxDQUFDLG9CQUFvQixFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUV0RCxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ3BCLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFO2dCQUN6RyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQzthQUMvQjtTQUNKO0lBQ0wsQ0FBQztJQUVPLGdDQUFlLEdBQXZCO1FBQ0ksSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLHlCQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUN2QyxDQUFDO0lBRU8sZ0NBQWUsR0FBdkI7UUFDSSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDcEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxlQUFlLEVBQUUsQ0FBQztTQUN0QztJQUNMLENBQUM7SUFFTyxrQ0FBaUIsR0FBekI7UUFDSSxJQUFJLFdBQVcsQ0FBQztRQUNoQixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyxVQUFVLEVBQUU7WUFDMUQsV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLHFCQUFxQixDQUFDLFVBQVUsS0FBSyxTQUFTLENBQUMsQ0FBQztnQkFDaEYsU0FBUyxDQUFDLENBQUM7Z0JBQ1gsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMscUJBQXFCLENBQUMsVUFBVSxDQUFDO1NBQzlEO2FBQU0sSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUU7WUFDekMsV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQztTQUNsRDthQUFNO1lBQ0gsV0FBVyxHQUFHLFNBQVMsQ0FBQztTQUMzQjtRQUNELE9BQU8sV0FBVyxDQUFDO0lBQ3ZCLENBQUM7SUFFTCxhQUFDO0FBQUQsQ0F6ZkEsQUF5ZkMsSUFBQTtBQXpmWSx3QkFBTTs7Ozs7QUNkbkIsb0ZBQW1GO0FBQ25GLGtGQUFpRjtBQUNqRiw2RUFBNEU7QUFFNUUsbURBQXNEO0FBWXREO0lBMERJLHVCQUFZLE1BQWMsRUFBRSxhQUFvQztRQUFoRSxpQkFzQ0M7UUF0RkQsV0FBTSxHQUF5QixFQUFFLENBQUM7UUE4QmxDLHVDQUFrQyxHQUFHLEtBQUssQ0FBQztRQVFqQyxPQUFFLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQVc5QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7UUFDakMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFckMsSUFBSSxDQUFDLENBQUMsYUFBYSxFQUFFO1lBQ2pCLElBQUksTUFBTSxTQUFBLENBQUM7WUFDWCxJQUFJLE9BQU8sYUFBYSxLQUFLLFFBQVEsRUFBRTtnQkFDbkMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7YUFDbkQ7aUJBQU0sSUFBSSxhQUFhLFlBQVksV0FBVyxFQUFFO2dCQUM3QyxNQUFNLEdBQUcsYUFBYSxDQUFDO2FBQzFCO1lBRUQsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFO2dCQUNWLElBQUksQ0FBQyxpQkFBaUIsR0FBRztvQkFDckIsYUFBYSxFQUFFLE1BQU07b0JBQ3JCLEtBQUssRUFBRSxRQUFRLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQztvQkFDdEMsRUFBRSxFQUFFLEVBQUU7aUJBQ1QsQ0FBQztnQkFDRixJQUFJLENBQUMsYUFBYSxHQUFHLE1BQU0sQ0FBQztnQkFDNUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7YUFDekI7U0FDSjtRQUNELElBQUksQ0FBQyxlQUFlLEdBQUc7WUFDbkIsSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUN2QixJQUFJLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsRUFBRTtvQkFDaEMsT0FBTyxDQUFDLElBQUksQ0FBQywrQkFBK0IsR0FBRyxLQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsR0FBRyx3QkFBd0IsQ0FBQyxDQUFDO29CQUNoRyxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxJQUFJLHFDQUFpQixDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQzFHO3FCQUFNO29CQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsb0NBQW9DLEdBQUcsS0FBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsd0JBQXdCLENBQUMsQ0FBQztvQkFDckcsS0FBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxJQUFJLHFDQUFpQixDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLEtBQUksRUFBRSxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDdEg7YUFDSjtpQkFBTTtnQkFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLDJCQUEyQixHQUFHLEtBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxHQUFHLHdCQUF3QixDQUFDLENBQUM7Z0JBQzVGLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUMxRztZQUNELEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRSxDQUFDLElBQUksdUNBQWtCLENBQUMsS0FBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLENBQUMsQ0FBQztJQUNOLENBQUM7SUFLRCwwQkFBRSxHQUFGLFVBQUcsSUFBWSxFQUFFLE9BQStCO1FBQzVDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxVQUFBLEtBQUs7WUFDbEIsSUFBSSxLQUFLLEVBQUU7Z0JBQ1AsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxHQUFHLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQzthQUN6RDtpQkFBTTtnQkFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLEdBQUcsYUFBYSxDQUFDLENBQUM7YUFDbEQ7WUFDRCxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLElBQUksS0FBSyxxQkFBcUIsRUFBRTtZQUNoQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxrQ0FBa0MsRUFBRTtnQkFDMUQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxJQUFJLHFDQUFpQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDckgsSUFBSSxDQUFDLGtDQUFrQyxHQUFHLEtBQUssQ0FBQzthQUNuRDtTQUNKO1FBQ0QsSUFBSSxJQUFJLEtBQUssZUFBZSxJQUFJLElBQUksS0FBSyxjQUFjLEVBQUU7WUFDckQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSztnQkFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsV0FBVyxHQUFHLENBQUM7Z0JBQ3BDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sS0FBSyxLQUFLO2dCQUNyQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssS0FBSztnQkFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBVSxLQUFLLENBQUMsRUFBRTtnQkFDdkMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFLENBQUMsSUFBSSx1Q0FBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ25FLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUMxRztTQUNKO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUtELDRCQUFJLEdBQUosVUFBSyxJQUFZLEVBQUUsT0FBK0I7UUFDOUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQUEsS0FBSztZQUNwQixJQUFJLEtBQUssRUFBRTtnQkFDUCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLEdBQUcsa0JBQWtCLEVBQUUsS0FBSyxDQUFDLENBQUM7YUFDOUQ7aUJBQU07Z0JBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxHQUFHLGtCQUFrQixDQUFDLENBQUM7YUFDdkQ7WUFDRCxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLElBQUksS0FBSyxxQkFBcUIsRUFBRTtZQUNoQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxrQ0FBa0MsRUFBRTtnQkFDMUQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxJQUFJLHFDQUFpQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN4SDtTQUNKO1FBQ0QsSUFBSSxJQUFJLEtBQUssZUFBZSxJQUFJLElBQUksS0FBSyxjQUFjLEVBQUU7WUFDckQsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSztnQkFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsV0FBVyxHQUFHLENBQUM7Z0JBQ3BDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sS0FBSyxLQUFLO2dCQUNyQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssS0FBSztnQkFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsVUFBVSxLQUFLLENBQUMsRUFBRTtnQkFDdkMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFLENBQUMsSUFBSSx1Q0FBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ25FLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUMxRztTQUNKO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUtELDJCQUFHLEdBQUgsVUFBSSxJQUFZLEVBQUUsT0FBZ0M7UUFDOUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNWLElBQUksQ0FBQyxFQUFFLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDcEM7YUFBTTtZQUNILElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztTQUM5QjtRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFhRCx1Q0FBZSxHQUFmLFVBQWdCLEtBQXVCO1FBRW5DLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUd0QyxLQUFnQixVQUFXLEVBQVgsS0FBQSxJQUFJLENBQUMsTUFBTSxFQUFYLGNBQVcsRUFBWCxJQUFXLEVBQUU7WUFBeEIsSUFBTSxDQUFDLFNBQUE7WUFDUixJQUFJLENBQUMsQ0FBQyxLQUFLLEtBQUssS0FBSyxFQUFFO2dCQUNuQixPQUFPLENBQUMsQ0FBQzthQUNaO1NBQ0o7UUFFRCxJQUFJLFlBQVksR0FBRyxDQUFDLENBQUM7UUFFckIsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXRDLEtBQTRCLFVBQWtDLEVBQWxDLEtBQUEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFsQyxjQUFrQyxFQUFsQyxJQUFrQyxFQUFFO1lBQTNELElBQU0sYUFBYSxTQUFBO1lBQ3BCLElBQUksYUFBYSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUN4QyxZQUFZLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xCLE1BQU07YUFDVDtTQUNKO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxVQUFBLGFBQWE7WUFDcEQsYUFBYSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNDLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLHlCQUF5QixDQUFDO1lBQzNCLEtBQUssT0FBQTtZQUNMLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRTtTQUNmLENBQUMsQ0FBQztRQUVILE9BQU8sQ0FBQyxJQUFJLENBQUMsa0NBQWtDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFFdkQsT0FBTyxZQUFZLENBQUM7SUFDeEIsQ0FBQztJQVlELDBDQUFrQixHQUFsQixVQUFtQixhQUFvQyxFQUFFLFVBQTRCO1FBQ2pGLElBQUksTUFBTSxDQUFDO1FBQ1gsSUFBSSxPQUFPLGFBQWEsS0FBSyxRQUFRLEVBQUU7WUFDbkMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDVCxNQUFNLElBQUksS0FBSyxDQUFDLHlFQUF5RSxHQUFHLGFBQWEsQ0FBQyxDQUFDO2FBQzlHO1NBQ0o7YUFBTSxJQUFJLGFBQWEsWUFBWSxXQUFXLEVBQUU7WUFDN0MsTUFBTSxHQUFHLGFBQWEsQ0FBQztTQUMxQjthQUFNO1lBQ0gsTUFBTSxJQUFJLEtBQUssQ0FBQyx5RUFBeUUsR0FBRyxhQUFhLENBQUMsQ0FBQztTQUM5RztRQUVELElBQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDOUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXRDLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsaUNBQWUsQ0FBQyxNQUFNLENBQUM7UUFDakUsUUFBUSxPQUFPLEVBQUU7WUFDYixLQUFLLGlDQUFlLENBQUMsS0FBSztnQkFDdEIsTUFBTSxDQUFDLFVBQVksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDNUQsTUFBTTtZQUNWLEtBQUssaUNBQWUsQ0FBQyxNQUFNO2dCQUN2QixNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMxQixNQUFNO1lBQ1YsS0FBSyxpQ0FBZSxDQUFDLE1BQU07Z0JBQ3ZCLE1BQU0sQ0FBQyxVQUFZLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDaEQsTUFBTTtZQUNWLEtBQUssaUNBQWUsQ0FBQyxPQUFPO2dCQUN4QixNQUFNLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pELE1BQU07WUFDVixLQUFLLGlDQUFlLENBQUMsT0FBTztnQkFDeEIsTUFBTSxDQUFDLFVBQVksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUNoRCxNQUFNO1lBQ1Y7Z0JBQ0ksT0FBTyxHQUFHLGlDQUFlLENBQUMsTUFBTSxDQUFDO2dCQUNqQyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMxQixNQUFNO1NBQ2I7UUFFRCxJQUFNLENBQUMsR0FBdUI7WUFDMUIsYUFBYSxFQUFFLE1BQU07WUFDckIsS0FBSyxPQUFBO1lBQ0wsVUFBVSxFQUFFLE9BQU87WUFDbkIsRUFBRSxFQUFFLEtBQUssQ0FBQyxFQUFFO1NBQ2YsQ0FBQztRQUNGLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVsQyxJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLElBQUkscUNBQWlCLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFeEcsSUFBSSxDQUFDLGtDQUFrQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUM7UUFFbkUsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUtELGlEQUF5QixHQUF6QixVQUEwQixLQUF1QjtRQUM3QyxLQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDL0MsS0FBSyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDdEIsS0FBSyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUU7WUFDWCxLQUFLLENBQUMsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7WUFFbEYsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUU7Z0JBQ2xDLElBQUksQ0FBQyxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQzthQUN0QjtTQUNKO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxFQUFFO1lBQ2hELEtBQUssQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1lBQ25CLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUU7Z0JBQzNELElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDM0I7U0FDSjtJQUNMLENBQUM7SUFLRCx1Q0FBZSxHQUFmO1FBQUEsaUJBcUJDO1FBcEJHLEtBQUssSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRTtZQUNyRSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQ2hELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2FBQ25EO1NBQ0o7UUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFDLGtCQUFrQixFQUFFLEtBQUssRUFBRSxNQUFNO1lBRXBFLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLEVBQUUsS0FBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQzlFLElBQUksQ0FBQyxDQUFDLGtCQUFrQixDQUFDLGFBQWEsRUFBRTtnQkFHcEMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLFVBQVcsQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQzNFLEtBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLHVCQUF1QixFQUFFLENBQUMsSUFBSSxxQ0FBaUIsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsS0FBSSxFQUFFLHVCQUF1QixDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUM3SCxLQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7YUFDcEQ7aUJBQU07Z0JBRUgsa0JBQWtCLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7YUFDN0M7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFLRCx5Q0FBaUIsR0FBakIsVUFBa0IsS0FBdUI7UUFDckMsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQzFCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN6QyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLEtBQUssRUFBRTtnQkFDaEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUN6QixhQUFhLEdBQUcsSUFBSSxDQUFDO2dCQUNyQixPQUFPLENBQUMsSUFBSSxDQUFDLG1DQUFtQyxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUN4RCxNQUFNO2FBQ1Q7U0FDSjtRQUNELE9BQU8sYUFBYSxDQUFDO0lBQ3pCLENBQUM7SUFLRCxnREFBd0IsR0FBeEI7UUFDSSxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxLQUFLLElBQUksQ0FBQyxFQUFFO1lBQzdGLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7U0FDMUU7SUFDTCxDQUFDO0lBS0QseUNBQWlCLEdBQWpCLFVBQWtCLFdBQXdCO1FBQ3RDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQUEsa0JBQWtCO1lBQ2xDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsV0FBVyxDQUFDO1FBQ3JELENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLGlEQUF5QixHQUFqQyxVQUFrQyxrQkFBc0M7UUFDcEUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUNyQyxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztRQUNoQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7WUFDekQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUNqRDtJQUNMLENBQUM7SUFFTyxtQ0FBVyxHQUFuQixVQUFvQixLQUFLO1FBQ3JCLEtBQUssQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLGlCQUFpQixDQUFDO1FBQzFDLEtBQUssQ0FBQyxLQUFLLENBQUMsZUFBZSxHQUFHLGlCQUFpQixDQUFDO0lBQ3BELENBQUM7SUFFTCxvQkFBQztBQUFELENBelhBLEFBeVhDLElBQUE7QUF6WFksc0NBQWE7Ozs7Ozs7Ozs7Ozs7OztBQ25CMUIsaURBQWdEO0FBT2hEO0lBQWdDLDhCQUFhO0lBT3pDLG9CQUFZLE1BQWMsRUFBRSxNQUE0QixFQUFFLFVBQWdDO1FBQTFGLFlBQ0ksa0JBQU0sTUFBTSxFQUFFLE1BQU0sQ0FBQyxTQUl4QjtRQUhHLEtBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQztRQUNsQyxLQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixLQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQzs7SUFDakMsQ0FBQztJQU1ELHFDQUFnQixHQUFoQixVQUFpQixLQUFjO1FBQzNCLElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUMsY0FBYyxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQUMsS0FBSztZQUN4RCxLQUFLLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztRQUMxQixDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxDQUFDO1FBQzFHLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFNRCxxQ0FBZ0IsR0FBaEIsVUFBaUIsS0FBYztRQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDLGNBQWMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFDLEtBQUs7WUFDeEQsS0FBSyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDMUIsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLG1CQUFtQixHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLG1CQUFtQixDQUFDLEdBQUcsbUJBQW1CLENBQUMsQ0FBQztRQUMxRyxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUwsaUJBQUM7QUFBRCxDQXRDQSxBQXNDQyxDQXRDK0IsNkJBQWEsR0FzQzVDO0FBdENZLGdDQUFVOzs7OztBQ1J2QixJQUFZLGtCQUtYO0FBTEQsV0FBWSxrQkFBa0I7SUFDMUIscUNBQWUsQ0FBQTtJQUNmLDZDQUF1QixDQUFBO0lBQ3ZCLHVDQUFpQixDQUFBO0lBQ2pCLDJDQUFxQixDQUFBO0FBQ3pCLENBQUMsRUFMVyxrQkFBa0IsR0FBbEIsMEJBQWtCLEtBQWxCLDBCQUFrQixRQUs3Qjs7Ozs7QUNGRCxJQUFZLGlCQTZFWDtBQTdFRCxXQUFZLGlCQUFpQjtJQU16QixvRUFBK0MsQ0FBQTtJQU0vQyxrRUFBNkMsQ0FBQTtJQU03QyxvRUFBK0MsQ0FBQTtJQU0vQyxrRkFBNkQsQ0FBQTtJQU03RCxzRkFBaUUsQ0FBQTtJQU1qRSw0RUFBdUQsQ0FBQTtJQU12RCxrRkFBNkQsQ0FBQTtJQU03RCxrRkFBNkQsQ0FBQTtJQU03RCxnRUFBMkMsQ0FBQTtJQU8zQyw4RUFBeUQsQ0FBQTtJQUt6RCw4RUFBeUQsQ0FBQTtJQUt6RCxzRUFBaUQsQ0FBQTtJQUtqRCxvREFBK0IsQ0FBQTtBQUNuQyxDQUFDLEVBN0VXLGlCQUFpQixHQUFqQix5QkFBaUIsS0FBakIseUJBQWlCLFFBNkU1QjtBQUtEO0lBUUksdUJBQVksSUFBdUIsRUFBRSxPQUFlO1FBQ2hELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQzNCLENBQUM7SUFFTCxvQkFBQztBQUFELENBYkEsQUFhQyxJQUFBO0FBYlksc0NBQWE7Ozs7O0FDbEYxQixJQUFZLGVBdUJYO0FBdkJELFdBQVksZUFBZTtJQUt2QixrQ0FBZSxDQUFBO0lBSWYsb0NBQWlCLENBQUE7SUFJakIsb0NBQWlCLENBQUE7SUFJakIsc0NBQW1CLENBQUE7SUFJbkIsc0NBQW1CLENBQUE7QUFFdkIsQ0FBQyxFQXZCVyxlQUFlLEdBQWYsdUJBQWUsS0FBZix1QkFBZSxRQXVCMUI7Ozs7Ozs7Ozs7Ozs7OztBQzFCRCxpQ0FBZ0M7QUFVaEM7SUFBcUMsbUNBQUs7SUFtQnRDLHlCQUFZLFVBQW1CLEVBQUUsTUFBZSxFQUFFLElBQVksRUFBRSxVQUFzQixFQUFFLE1BQWM7UUFBdEcsWUFDSSxrQkFBTSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxTQUdsQztRQUZHLEtBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLEtBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDOztJQUN6QixDQUFDO0lBTUQsOENBQW9CLEdBQXBCLGNBQXlCLENBQUM7SUFFOUIsc0JBQUM7QUFBRCxDQS9CQSxBQStCQyxDQS9Cb0MsYUFBSyxHQStCekM7QUEvQlksMENBQWU7Ozs7O0FDUDVCO0lBc0JJLGVBQVksVUFBbUIsRUFBRSxNQUErQixFQUFFLElBQVk7UUFMdEUscUJBQWdCLEdBQUcsS0FBSyxDQUFDO1FBTTdCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ3JCLENBQUM7SUFLRCxrQ0FBa0IsR0FBbEI7UUFDSSxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztJQUNqQyxDQUFDO0lBZ0JELDhCQUFjLEdBQWQ7UUFFSSxJQUFJLENBQUMsb0JBQW9CLEdBQUcsY0FBUSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztJQUNqQyxDQUFDO0lBSUwsWUFBQztBQUFELENBekRBLEFBeURDLElBQUE7QUF6RHFCLHNCQUFLOzs7Ozs7Ozs7Ozs7Ozs7QUNIM0IsaUNBQWdDO0FBZ0JoQztJQUE0QywwQ0FBSztJQWU3QyxnQ0FBWSxNQUFlLEVBQUUsSUFBWSxFQUFFLFVBQXNCLEVBQUUsUUFBZ0I7UUFBbkYsWUFDSSxrQkFBTSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxTQUk3QjtRQUhHLEtBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLEtBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLEtBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDOztJQUM3QixDQUFDO0lBTUQscURBQW9CLEdBQXBCLGNBQXlCLENBQUM7SUFFOUIsNkJBQUM7QUFBRCxDQTVCQSxBQTRCQyxDQTVCMkMsYUFBSyxHQTRCaEQ7QUE1Qlksd0RBQXNCOzs7Ozs7Ozs7Ozs7Ozs7QUNoQm5DLGlDQUFnQztBQVNoQztJQUFvQyxrQ0FBSztJQW9CckMsd0JBQVksTUFBZSxFQUFFLElBQVksRUFBRSxFQUFVLEVBQUUsSUFBWTtRQUFuRSxZQUNJLGtCQUFNLEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLFNBSzdCO1FBSkcsS0FBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7UUFDYixJQUFJLElBQUksS0FBSyxFQUFFLEVBQUU7WUFDYixLQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztTQUNwQjs7SUFDTCxDQUFDO0lBTUQsNkNBQW9CLEdBQXBCLGNBQXlCLENBQUM7SUFFOUIscUJBQUM7QUFBRCxDQWxDQSxBQWtDQyxDQWxDbUMsYUFBSyxHQWtDeEM7QUFsQ1ksd0NBQWM7Ozs7Ozs7Ozs7Ozs7OztBQ1QzQixpQ0FBZ0M7QUFPaEM7SUFBOEMsNENBQUs7SUFXL0Msa0NBQVksTUFBZSxFQUFFLE1BQWM7UUFBM0MsWUFDSSxrQkFBTSxJQUFJLEVBQUUsTUFBTSxFQUFFLHFCQUFxQixDQUFDLFNBRTdDO1FBREcsS0FBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7O0lBQ3pCLENBQUM7SUFLRCx1REFBb0IsR0FBcEI7UUFFSSxPQUFPLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsaUNBQWlDLENBQUMsQ0FBQztRQUVqRyxJQUFNLE9BQU8sR0FBWSxJQUFJLENBQUMsTUFBTSxDQUFDO1FBR3JDLEtBQUssSUFBTSxZQUFZLElBQUksT0FBTyxDQUFDLGlCQUFpQixFQUFFO1lBQ2xELElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLEVBQUU7Z0JBQ2xELE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztnQkFDbkUsT0FBTyxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO2dCQUNwRSxJQUFJLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFO29CQUM5RCxPQUFPLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxlQUFlLEVBQUUsQ0FBQztpQkFDbEY7Z0JBQ0QsT0FBTyxPQUFPLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDN0YsT0FBTyxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO2FBQ3JEO1lBQ0QsT0FBTyxPQUFPLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDbEQ7SUFDTCxDQUFDO0lBRUwsK0JBQUM7QUFBRCxDQXhDQSxBQXdDQyxDQXhDNkMsYUFBSyxHQXdDbEQ7QUF4Q1ksNERBQXdCOzs7Ozs7Ozs7Ozs7Ozs7QUNQckMsaUNBQWdDO0FBVWhDO0lBQWlDLCtCQUFLO0lBd0JsQyxxQkFBWSxNQUFlLEVBQUUsSUFBWSxFQUFFLElBQVksRUFBRSxJQUFnQjtRQUF6RSxZQUNJLGtCQUFNLEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLFNBSTdCO1FBSEcsS0FBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsS0FBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsS0FBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7O0lBQ3JCLENBQUM7SUFNRCwwQ0FBb0IsR0FBcEIsY0FBeUIsQ0FBQztJQUU5QixrQkFBQztBQUFELENBckNBLEFBcUNDLENBckNnQyxhQUFLLEdBcUNyQztBQXJDWSxrQ0FBVzs7Ozs7Ozs7Ozs7Ozs7O0FDVnhCLGlDQUFnQztBQUNoQyxzREFBcUQ7QUFDckQsa0RBQWlEO0FBU2pEO0lBQWlDLCtCQUFLO0lBb0JsQyxxQkFBWSxVQUFtQixFQUFFLE1BQTJCLEVBQUUsSUFBWSxFQUFFLE1BQWMsRUFBRSxNQUFjO1FBQTFHLFlBQ0ksa0JBQU0sVUFBVSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FHbEM7UUFGRyxLQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixLQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQzs7SUFDekIsQ0FBQztJQUtELDBDQUFvQixHQUFwQjtRQUNJLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxpQkFBaUIsRUFBRTtZQUVqQyxJQUFJLElBQUksQ0FBQyxNQUFNLFlBQVksaUJBQU8sRUFBRTtnQkFFaEMsT0FBTyxDQUFDLElBQUksQ0FBQyxrQ0FBa0MsR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLGlDQUFpQyxDQUFDLENBQUM7Z0JBQ2pHLElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLEVBQUUsQ0FBQzthQUNuQztpQkFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLFlBQVkscUJBQVMsRUFBRTtnQkFFekMsT0FBTyxDQUFDLElBQUksQ0FBQyxrQ0FBa0MsR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLG1DQUFtQyxDQUFDLENBQUM7Z0JBQ25HLElBQUksQ0FBQyxNQUFNLENBQUMsMkJBQTJCLEdBQUcsS0FBSyxDQUFDO2FBQ25EO1lBR0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBSWpDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhO2dCQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBRzNFLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUd0RSxJQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3BHLElBQUksQ0FBQyxDQUFDLGdCQUFnQixJQUFJLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUU7Z0JBQ2xELElBQU0sbUJBQW1CLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztnQkFDN0QsS0FBSyxJQUFJLENBQUMsR0FBRyxtQkFBbUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUU7b0JBQ3RELElBQUksbUJBQW1CLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO3dCQUNwRCxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO3FCQUNwQztpQkFDSjthQUNKO1NBRUo7SUFDTCxDQUFDO0lBRUwsa0JBQUM7QUFBRCxDQWxFQSxBQWtFQyxDQWxFZ0MsYUFBSyxHQWtFckM7QUFsRVksa0NBQVc7Ozs7Ozs7Ozs7Ozs7OztBQ1h4QixpQ0FBZ0M7QUFPaEM7SUFBd0Msc0NBQUs7SUFLekMsNEJBQVksTUFBcUI7ZUFDN0Isa0JBQU0sS0FBSyxFQUFFLE1BQU0sRUFBRSxlQUFlLENBQUM7SUFDekMsQ0FBQztJQU1ELGlEQUFvQixHQUFwQixjQUF5QixDQUFDO0lBRTlCLHlCQUFDO0FBQUQsQ0FmQSxBQWVDLENBZnVDLGFBQUssR0FlNUM7QUFmWSxnREFBa0I7Ozs7Ozs7Ozs7Ozs7OztBQ1AvQixpQ0FBZ0M7QUFVaEM7SUFBdUMscUNBQUs7SUFVeEMsMkJBQVksT0FBeUIsRUFBRSxNQUFxQixFQUFFLElBQVk7UUFBMUUsWUFDSSxrQkFBTSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxTQUU3QjtRQURHLEtBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDOztJQUMzQixDQUFDO0lBTUQsZ0RBQW9CLEdBQXBCLGNBQXlCLENBQUM7SUFFOUIsd0JBQUM7QUFBRCxDQXJCQSxBQXFCQyxDQXJCc0MsYUFBSyxHQXFCM0M7QUFyQlksOENBQWlCOzs7QUMzQjlCO0lBRUUsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO0lBR2pCLElBQUksQ0FBQyxPQUFPLEdBQUcsVUFBUyxRQUFRO1FBRTlCLEtBQUksSUFBSSxHQUFHLElBQUksT0FBTyxFQUN0QjtZQUNFLElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUUxQixLQUFJLElBQUksSUFBSSxJQUFJLE1BQU07Z0JBQ3BCLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztTQUMxQjtRQUFBLENBQUM7SUFDSixDQUFDLENBQUM7SUFFRixJQUFJLENBQUMsR0FBRyxHQUFHLFVBQVMsRUFBRSxFQUFFLE1BQU07UUFFNUIsSUFBSSxHQUFHLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFCLElBQUcsR0FBRyxJQUFJLFNBQVM7WUFDakIsT0FBTyxTQUFTLENBQUM7UUFFbkIsT0FBTyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDakIsQ0FBQyxDQUFDO0lBRUYsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFTLEVBQUUsRUFBRSxNQUFNO1FBRS9CLElBQUksR0FBRyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMxQixJQUFHLEdBQUcsSUFBSSxTQUFTO1lBQ2pCLE9BQU87UUFFVCxPQUFPLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUdmLEtBQUksSUFBSSxDQUFDLElBQUksR0FBRyxFQUFDO1lBQUMsT0FBTyxLQUFLLENBQUE7U0FBQztRQUUvQixPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QixDQUFDLENBQUM7SUFFRixJQUFJLENBQUMsR0FBRyxHQUFHLFVBQVMsS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNO1FBRW5DLElBQUcsS0FBSyxJQUFJLFNBQVM7WUFDbkIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUVqQyxJQUFJLEdBQUcsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDMUIsSUFBRyxHQUFHLElBQUksU0FBUztZQUNqQixPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUU3QixHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQ2xCLENBQUMsQ0FBQztBQUNKLENBQUM7QUFBQSxDQUFDO0FBR0YsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEdBQUcsVUFBUyxFQUFFLEVBQUUsTUFBTTtJQUV4QyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNqQyxJQUFHLEtBQUssSUFBSSxTQUFTO1FBQ25CLE9BQU8sU0FBUyxDQUFDO0lBRW5CLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBRXhCLE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyxDQUFDO0FBR0YsTUFBTSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7OztBQ2hEeEIsSUFBSSxhQUFhLEdBQUksT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7QUFHaEQsT0FBTyxDQUFDLGFBQWEsR0FBSSxhQUFhLENBQUM7OztBQ0h2QyxJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDaEMsSUFBSSx5QkFBeUIsR0FBRyxPQUFPLENBQUMsd0NBQXdDLENBQUMsQ0FBQztBQUVsRixJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUk7SUFDbkIsT0FBTyxDQUFDLElBQUksSUFBSSxDQUFDO0FBQ3JCLENBQUMsQ0FBQztBQUVGLElBQUksYUFBYSxHQUFHLElBQUksQ0FBQztBQUV6QixJQUFJLFlBQVksR0FBRyxjQUFjLENBQUM7QUFDbEMsSUFBSSxTQUFTLEdBQUcsV0FBVyxDQUFDO0FBQzVCLElBQUksWUFBWSxHQUFHLGNBQWMsQ0FBQztBQUVsQyxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUM7QUF1QnJCLHVCQUF1QixhQUFhO0lBRWhDLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQztJQUVoQixJQUFJLFFBQVEsR0FBRyxhQUFhLENBQUMsRUFBRSxDQUFDO0lBRWhDLElBQUkseUJBQXlCLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFbkMsSUFBSSxXQUFXLEdBQUcsQ0FBQyxDQUFDO0lBQ3BCLElBQUksWUFBWSxHQUFHLElBQUksQ0FBQztJQUN4QixJQUFJLGVBQWUsR0FBRyxLQUFLLENBQUM7SUFDNUIsSUFBSSxZQUFZLENBQUM7SUFFakIsSUFBSSxNQUFNLEdBQUcsWUFBWSxDQUFDO0lBRTFCLElBQUksY0FBYyxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUM7SUFDN0MsSUFBSSxhQUFhLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQztJQUMzQyxJQUFJLFdBQVcsR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDO0lBQ3ZDLElBQUksT0FBTyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUM7SUFFL0IsYUFBYSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsVUFBUyxNQUFNLEVBQUUsT0FBTztRQUM3QyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNoQyxDQUFDLENBQUE7SUFFRCxRQUFRLENBQUMsY0FBYyxHQUFHO1FBQ3RCLE1BQU0sQ0FBQyxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztRQUNyRCxJQUFJLE1BQU0sS0FBSyxZQUFZLEVBQUU7WUFDekIsTUFBTSxDQUFDLEtBQUssQ0FBQyxrR0FBa0csQ0FBQyxDQUFDO1lBQ2pILE9BQU87U0FDVjtRQUVELE1BQU0sR0FBRyxZQUFZLENBQUM7UUFDdEIsSUFBSSxjQUFjLEVBQUU7WUFDaEIsY0FBYyxFQUFFLENBQUM7U0FDcEI7SUFDTCxDQUFDLENBQUE7SUFFRCxRQUFRLENBQUMsYUFBYSxHQUFHO1FBQ3JCLE1BQU0sQ0FBQyxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQztRQUNwRCxJQUFJLE1BQU0sS0FBSyxTQUFTLEVBQUU7WUFDdEIsTUFBTSxDQUFDLEtBQUssQ0FBQyw4RkFBOEYsQ0FBQyxDQUFDO1lBQzdHLE9BQU87U0FDVjtRQUNELE1BQU0sR0FBRyxTQUFTLENBQUM7UUFFbkIsWUFBWSxHQUFHLElBQUksQ0FBQztRQUNwQiw0QkFBNEIsRUFBRSxDQUFDO1FBQy9CLE9BQU8sRUFBRSxDQUFDO1FBRVYsSUFBSSxhQUFhLEVBQUU7WUFDZixhQUFhLEVBQUUsQ0FBQztTQUNuQjtJQUNMLENBQUMsQ0FBQTtJQUVELFFBQVEsQ0FBQyxXQUFXLEdBQUc7UUFDbkIsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1FBQ2xELElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtZQUN0QixNQUFNLENBQUMsS0FBSyxDQUFDLDRGQUE0RixDQUFDLENBQUM7WUFDM0csT0FBTztTQUNWO1FBQ0QsTUFBTSxHQUFHLFNBQVMsQ0FBQztRQUVuQixZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ3BCLE9BQU8sRUFBRSxDQUFDO1FBRVYsSUFBSSxXQUFXLEVBQUU7WUFDYixXQUFXLEVBQUUsQ0FBQztTQUNqQjtJQUNMLENBQUMsQ0FBQTtJQUVELFFBQVEsQ0FBQyxPQUFPLEdBQUcsVUFBUyxLQUFLO1FBQzdCLE1BQU0sQ0FBQyxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUU5QyxNQUFNLEdBQUcsWUFBWSxDQUFDO1FBRXRCLElBQUksT0FBTyxFQUFFO1lBQ1QsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ2xCO0lBQ0wsQ0FBQyxDQUFBO0lBRUQsSUFBSSxFQUFFLEdBQUcsSUFBSSx5QkFBeUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUVqRCxNQUFNLENBQUMsS0FBSyxDQUFDLCtCQUErQixHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUU3RCxJQUFJLGlCQUFpQixHQUFHO1FBQ3BCLGVBQWUsRUFBRSxhQUFhLENBQUMsR0FBRyxDQUFDLGNBQWM7UUFDakQsb0JBQW9CLEVBQUUsYUFBYSxDQUFDLEdBQUcsQ0FBQyx1QkFBdUI7S0FDbEUsQ0FBQztJQUVGLElBQUksR0FBRyxHQUFHLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLEVBQUUsRUFDdEUsVUFBUyxPQUFPO1FBRVosTUFBTSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFFN0QsSUFBSTtZQUNBLElBQUksSUFBSSxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRTdDLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRTtnQkFDcEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLE1BQU0sR0FBRywyQkFBMkIsQ0FBQyxDQUFDO2FBQzFFO2lCQUFNO2dCQUNILElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO2FBQ2pDO1NBQ0o7UUFBQyxPQUFPLEdBQUcsRUFBRTtZQUNWLE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0NBQWdDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ3pFLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDckI7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVQLElBQUksQ0FBQyxJQUFJLEdBQUcsVUFBUyxNQUFNLEVBQUUsTUFBTSxFQUFFLFFBQVE7UUFDekMsSUFBSSxNQUFNLEtBQUssTUFBTSxFQUFFO1lBQ25CLE1BQU0sQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEdBQUcsTUFBTSxHQUFHLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7U0FDbkY7UUFFRCxJQUFJLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFN0IsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFVBQVMsS0FBSyxFQUFFLE1BQU07WUFDN0MsSUFBSSxLQUFLLEVBQUU7Z0JBQ1AsSUFBSTtvQkFDQSxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsT0FBTyxHQUFHLHNCQUFzQjt3QkFDMUQsTUFBTSxHQUFHLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLFdBQVc7d0JBQzFELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDbkIsSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFO3dCQUNaLE1BQU0sQ0FBQyxLQUFLLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7cUJBQzVEO2lCQUNKO2dCQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUU7Z0JBQ2QsS0FBSyxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7YUFDbkM7WUFDRCxJQUFJLFFBQVEsRUFBRTtnQkFDVixJQUFJLE1BQU0sSUFBSSxTQUFTLElBQUksTUFBTSxDQUFDLEtBQUssS0FBSyxNQUFNLEVBQUU7b0JBQ2hELE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztpQkFDdkQ7Z0JBQ0QsUUFBUSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQzthQUMzQjtRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQyxDQUFBO0lBRUQ7UUFDSSxNQUFNLENBQUMsS0FBSyxDQUFDLDhCQUE4QixHQUFHLFdBQVcsR0FBRyxRQUFRO1lBQ2hFLHlCQUF5QixHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ3JDLHlCQUF5QixHQUFHLFdBQVcsQ0FBQztJQUM1QyxDQUFDO0lBRUQ7UUFDSSxJQUFJLFlBQVksRUFBRTtZQUNkLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQztZQUNsQixJQUFJLFdBQVcsSUFBSSxDQUFDLElBQUksV0FBVyxJQUFJLHlCQUF5QixFQUFFO2dCQUM5RCxNQUFNLEdBQUc7b0JBQ0wsUUFBUSxFQUFFLGFBQWEsQ0FBQyxTQUFTLElBQUksYUFBYTtpQkFDckQsQ0FBQzthQUNMO1lBQ0QsV0FBVyxFQUFFLENBQUM7WUFFZCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxVQUFTLE9BQU87Z0JBQ3ZDLE9BQU8sVUFBUyxLQUFLLEVBQUUsTUFBTTtvQkFDekIsSUFBSSxLQUFLLEVBQUU7d0JBQ1AsTUFBTSxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxPQUFPLEdBQUcsSUFBSTs0QkFDbkQsS0FBSyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsQ0FBQzt3QkFDekIsSUFBSSxPQUFPLEdBQUcseUJBQXlCLEVBQUU7NEJBQ3JDLFlBQVksR0FBRyxLQUFLLENBQUM7NEJBQ3JCLDRCQUE0QixFQUFFLENBQUM7NEJBQy9CLE1BQU0sQ0FBQyxLQUFLLENBQUMsMENBQTBDO2dDQUNuRCxPQUFPLEdBQUcsb0JBQW9CLENBQUMsQ0FBQzs0QkFDcEMsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO3lCQUNwQjtxQkFDSjtnQkFDTCxDQUFDLENBQUE7WUFDTCxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1NBQ3BCO2FBQU07WUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7U0FDaEU7SUFDTCxDQUFDO0lBTUQ7UUFDSSxJQUFJLENBQUMsZUFBZSxFQUFFO1lBQ2xCLE1BQU0sQ0FBQyxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQTtZQUM3QyxlQUFlLEdBQUcsSUFBSSxDQUFDO1lBRXZCLElBQUksYUFBYSxDQUFDLFNBQVMsSUFBSSxTQUFTLEVBQUU7Z0JBQ3RDLFlBQVksR0FBRyxXQUFXLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDOUQsUUFBUSxFQUFFLENBQUM7YUFDZDtTQUNKO0lBQ0wsQ0FBQztJQUVELElBQUksQ0FBQyxLQUFLLEdBQUc7UUFDVCxNQUFNLENBQUMsS0FBSyxDQUFDLDRDQUE0QyxDQUFDLENBQUM7UUFFM0QsSUFBSSxZQUFZLElBQUksU0FBUyxFQUFFO1lBQzNCLE1BQU0sQ0FBQyxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztZQUN2QyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDL0I7UUFDRCxlQUFlLEdBQUcsS0FBSyxDQUFDO1FBQ3hCLFlBQVksR0FBRyxLQUFLLENBQUM7UUFFckIsSUFBSSxhQUFhLENBQUMsZ0JBQWdCLEVBQUU7WUFDaEMsTUFBTSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFBO1lBQ3JDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLElBQUksRUFBRSxVQUFTLEtBQUssRUFBRSxNQUFNO2dCQUNsRCxJQUFJLEtBQUssRUFBRTtvQkFDUCxNQUFNLENBQUMsS0FBSyxDQUFDLCtCQUErQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDekU7Z0JBQ0QsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2YsQ0FBQyxDQUFDLENBQUM7U0FDTjthQUFNO1lBQ1osRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ0w7SUFDTCxDQUFDLENBQUE7SUFHRCxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVMsTUFBTTtRQUM3QixFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFCLENBQUMsQ0FBQTtJQUVELElBQUksQ0FBQyxTQUFTLEdBQUc7UUFDYixFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDckIsQ0FBQyxDQUFBO0FBQ0wsQ0FBQztBQUdELE1BQU0sQ0FBQyxPQUFPLEdBQUcsYUFBYSxDQUFDOzs7QUNsUS9CLElBQUkseUJBQXlCLEdBQUksT0FBTyxDQUFDLDZCQUE2QixDQUFDLENBQUM7QUFHeEUsT0FBTyxDQUFDLHlCQUF5QixHQUFJLHlCQUF5QixDQUFDOzs7O0FDSi9ELFlBQVksQ0FBQztBQUViLElBQUksZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLFNBQVMsSUFBSSxNQUFNLENBQUMsWUFBWSxDQUFDO0FBRS9ELElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQztBQWlCckIsSUFBSSxXQUFXLEdBQUcsSUFBSSxDQUFDO0FBQ3ZCLElBQUksYUFBYSxHQUFHLElBQUksQ0FBQztBQUV6QixJQUFJLFVBQVUsR0FBRyxDQUFDLENBQUM7QUFDbkIsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO0FBQ2IsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO0FBQ2hCLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztBQVlmLG1DQUFtQyxNQUFNO0lBRXJDLElBQUksT0FBTyxHQUFHLEtBQUssQ0FBQztJQUNwQixJQUFJLHNCQUFzQixDQUFDO0lBQzNCLElBQUksS0FBSyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUM7SUFDdkIsSUFBSSxTQUFTLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQztJQUNqQyxJQUFJLFlBQVksR0FBRyxLQUFLLENBQUM7SUFFekIsSUFBSSxvQkFBb0IsR0FBRyxLQUFLLENBQUM7SUFFakMsSUFBSSxFQUFFLENBQUM7SUFFUCxJQUFJLFNBQVMsRUFBRTtRQUNYLEVBQUUsR0FBRyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztLQUMxQjtTQUFNO1FBQ0gsRUFBRSxHQUFHLElBQUksU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQzdCO0lBRUQsRUFBRSxDQUFDLE1BQU0sR0FBRztRQUNSLFlBQVksQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEIsSUFBSSxNQUFNLENBQUMsV0FBVyxFQUFFO1lBQ3BCLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztTQUN4QjtJQUNMLENBQUMsQ0FBQztJQUVGLEVBQUUsQ0FBQyxPQUFPLEdBQUcsVUFBUyxLQUFLO1FBQ3ZCLE1BQU0sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEdBQUcsS0FBSyxHQUFHLGdDQUFnQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3hGLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRTtZQUNoQixNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ3pCO0lBQ0wsQ0FBQyxDQUFDO0lBRUYsc0JBQXNCLEVBQUUsRUFBRSxLQUFLO1FBQzNCLElBQUk7WUFDQSxNQUFNLENBQUMsS0FBSyxDQUFDLHlCQUF5QixHQUFHLEtBQUssQ0FBQyxDQUFDO1NBQ25EO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDUixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ25CO0lBQ0wsQ0FBQztJQUVELElBQUksbUJBQW1CLEdBQUc7UUFDdEIsSUFBSSxFQUFFLENBQUMsVUFBVSxLQUFLLE1BQU0sRUFBRTtZQUMxQixJQUFJLE9BQU8sRUFBRTtnQkFDVCxNQUFNLENBQUMsS0FBSyxDQUFDLDJCQUEyQixDQUFDLENBQUM7YUFDN0M7aUJBQU07Z0JBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxpREFBaUQsQ0FBQyxDQUFDO2dCQUNoRSxrQkFBa0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7YUFDdEM7U0FDSjthQUFNO1lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO1NBQ3ZFO0lBQ0wsQ0FBQyxDQUFDO0lBRUYsRUFBRSxDQUFDLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQztJQUVqQyw0QkFBNEIsVUFBVSxFQUFFLFVBQVU7UUFDOUMsTUFBTSxDQUFDLEtBQUssQ0FBQywrQkFBK0IsR0FBRyxVQUFVLEdBQUcsUUFBUSxHQUFHLFVBQVUsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUV6RixJQUFJLFVBQVUsS0FBSyxDQUFDLEVBQUU7WUFDbEIsSUFBSSxZQUFZLEVBQUU7Z0JBQ2QsTUFBTSxDQUFDLElBQUksQ0FBQyw4RUFBOEUsQ0FBQyxDQUFBO2dCQUMzRixPQUFPO2FBQ1Y7aUJBQU07Z0JBQ0gsWUFBWSxHQUFHLElBQUksQ0FBQzthQUN2QjtZQUVELElBQUksTUFBTSxDQUFDLGNBQWMsRUFBRTtnQkFDdkIsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO2FBQzNCO1NBQ0o7UUFFRCxJQUFJLG9CQUFvQixFQUFFO1lBQ3RCLGlCQUFpQixDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FFcEQ7YUFBTTtZQUNILElBQUksTUFBTSxDQUFDLHNCQUFzQixFQUFFO2dCQUMvQixNQUFNLENBQUMsc0JBQXNCLENBQUMsVUFBUyxLQUFLLEVBQUUsUUFBUTtvQkFFbEQsSUFBSSxLQUFLLEVBQUU7d0JBQ1AsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQzt3QkFDcEIsVUFBVSxDQUFDOzRCQUNQLGtCQUFrQixDQUFDLFVBQVUsRUFBRSxVQUFVLEdBQUcsQ0FBQyxDQUFDLENBQUM7d0JBQ25ELENBQUMsRUFBRSxhQUFhLENBQUMsQ0FBQztxQkFDckI7eUJBQU07d0JBQ0gsaUJBQWlCLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQztxQkFDdkQ7Z0JBQ0wsQ0FBQyxDQUFDLENBQUE7YUFDTDtpQkFBTTtnQkFDSCxpQkFBaUIsQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQ3BEO1NBQ0o7SUFDTCxDQUFDO0lBR0QsMkJBQTJCLFVBQVUsRUFBRSxVQUFVLEVBQUUsY0FBYztRQUM3RCxNQUFNLENBQUMsS0FBSyxDQUFDLHdCQUF3QixHQUFHLFVBQVUsQ0FBQyxDQUFDO1FBRXBELEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVYLEtBQUssR0FBRyxjQUFjLElBQUksS0FBSyxDQUFDO1FBRWhDLElBQUksS0FBSyxDQUFDO1FBQ1YsSUFBSSxTQUFTLEVBQUU7WUFDWCxLQUFLLEdBQUcsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDN0I7YUFBTTtZQUNILEtBQUssR0FBRyxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUNoQztRQUVELEtBQUssQ0FBQyxNQUFNLEdBQUc7WUFDWCxNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixHQUFHLFVBQVUsR0FBRyxjQUFjLENBQUMsQ0FBQztZQUNqRSxZQUFZLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQzNCLFlBQVksR0FBRyxLQUFLLENBQUM7WUFDckIsc0JBQXNCLEVBQUUsQ0FBQztZQUN6QixJQUFJLE1BQU0sQ0FBQyxhQUFhLEVBQUUsRUFBRTtnQkFDeEIsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDO2FBQzFCO1lBRUQsS0FBSyxDQUFDLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQztRQUN4QyxDQUFDLENBQUM7UUFFRixJQUFJLGNBQWMsR0FBRyxVQUFTLEtBQUs7WUFDL0IsTUFBTSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUUzQyxJQUFJLFVBQVUsS0FBSyxVQUFVLEVBQUU7Z0JBQzNCLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRTtvQkFDckIsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2lCQUN6QjthQUNKO2lCQUFNO2dCQUNILFVBQVUsQ0FBQztvQkFDUCxrQkFBa0IsQ0FBQyxVQUFVLEVBQUUsVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNuRCxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7YUFDckI7UUFDTCxDQUFDLENBQUM7UUFFRixLQUFLLENBQUMsT0FBTyxHQUFHLGNBQWMsQ0FBQztRQUUvQixFQUFFLEdBQUcsS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELElBQUksQ0FBQyxLQUFLLEdBQUc7UUFDVCxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ2YsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2YsQ0FBQyxDQUFDO0lBSUYsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFTLE1BQU07UUFDN0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBRS9DLElBQUksTUFBTSxFQUFFO1lBQ1IsTUFBTSxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsR0FBRyxNQUFNLEdBQUcsaUNBQWlDLENBQUMsQ0FBQztZQUN4RixJQUFJLFNBQVMsR0FBRyxLQUFLLENBQUM7WUFDdEIsS0FBSyxHQUFHLDJCQUEyQixDQUFDO1lBRXBDLG9CQUFvQixHQUFHLElBQUksQ0FBQztZQUU1QixVQUFVLENBQUM7Z0JBQ1AsTUFBTSxDQUFDLEtBQUssQ0FBQyw4QkFBOEIsR0FBRyxTQUFTLENBQUMsQ0FBQztnQkFDekQsS0FBSyxHQUFHLFNBQVMsQ0FBQztnQkFFbEIsb0JBQW9CLEdBQUcsS0FBSyxDQUFDO1lBRWpDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztTQUNkO1FBRUQsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2YsQ0FBQyxDQUFDO0lBRUYsSUFBSSxDQUFDLFdBQVcsR0FBRztRQUNmLE1BQU0sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDNUIsa0JBQWtCLENBQUMsV0FBVyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM5QyxDQUFDLENBQUM7SUFFRixJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVMsT0FBTztRQUN4QixFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3JCLENBQUMsQ0FBQztJQUVGLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxVQUFTLElBQUksRUFBRSxRQUFRO1FBQzNDLHNCQUFzQixHQUFHO1lBQ3JCLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDeEMsQ0FBQyxDQUFDO1FBRUYsc0JBQXNCLEVBQUUsQ0FBQztJQUM3QixDQUFDLENBQUM7QUFDTixDQUFDO0FBRUQsTUFBTSxDQUFDLE9BQU8sR0FBRyx5QkFBeUIsQ0FBQzs7Ozs7QUMvTjNDLElBQUksa0JBQWtCLEdBQUcsS0FBSyxDQUFBO0FBQzlCLElBQUcsTUFBTSxDQUFDLGNBQWMsRUFDeEI7SUFDRSxJQUNBO1FBQ0UsTUFBTSxDQUFDLGNBQWMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQ3BDO0lBQ0QsT0FBTSxDQUFDLEVBQ1A7UUFDRSxrQkFBa0IsR0FBRyxJQUFJLENBQUE7S0FDMUI7Q0FDRjtBQUdELElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRTtJQUM1QixRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksR0FBRyxVQUFTLEtBQUs7UUFDdEMsSUFBSSxPQUFPLElBQUksS0FBSyxVQUFVLEVBQUU7WUFHOUIsTUFBTSxJQUFJLFNBQVMsQ0FBQyxzRUFBc0UsQ0FBQyxDQUFDO1NBQzdGO1FBRUQsSUFBSSxLQUFLLEdBQUssS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsRUFDbEQsT0FBTyxHQUFHLElBQUksRUFDZCxJQUFJLEdBQU0sY0FBWSxDQUFDLEVBQ3ZCLE1BQU0sR0FBSTtZQUNSLE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLFlBQVksSUFBSSxJQUFJLEtBQUs7Z0JBQzNDLENBQUMsQ0FBQyxJQUFJO2dCQUNOLENBQUMsQ0FBQyxLQUFLLEVBQ1AsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlELENBQUMsQ0FBQztRQUVOLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUNoQyxNQUFNLENBQUMsU0FBUyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFFOUIsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQyxDQUFDO0NBQ0g7QUFHRCxJQUFJLFlBQVksR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsWUFBWSxDQUFDO0FBRWxELElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUVuQyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDbkMsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBR2pDLElBQUksWUFBWSxHQUFHLElBQUksQ0FBQztBQUd4Qiw4QkFBOEIsZUFBZTtJQUUzQyxJQUFHLENBQUMsZUFBZTtRQUFFLE9BQU8sRUFBRSxDQUFDO0lBRS9CLEtBQUksSUFBSSxHQUFHLElBQUksZUFBZSxFQUM5QjtRQUNFLElBQUksS0FBSyxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVqQyxJQUFHLE9BQU8sS0FBSyxJQUFJLFFBQVE7WUFDekIsZUFBZSxDQUFDLEdBQUcsQ0FBQztnQkFDcEI7b0JBQ0UsUUFBUSxFQUFFLEtBQUs7aUJBQ2hCLENBQUE7S0FDSjtJQUFBLENBQUM7SUFFRixPQUFPLGVBQWUsQ0FBQztBQUN6QixDQUFDO0FBQUEsQ0FBQztBQUVGLHdCQUF3QixTQUFTO0lBRS9CLElBQUcsQ0FBQyxTQUFTO1FBQUUsT0FBTztJQUd0QixJQUFHLFNBQVMsWUFBWSxRQUFRO1FBQzlCLE9BQU8sRUFBQyxJQUFJLEVBQUUsU0FBUyxFQUFDLENBQUM7SUFHM0IsSUFBRyxTQUFTLENBQUMsSUFBSSxZQUFZLFFBQVE7UUFDbkMsT0FBTyxTQUFTLENBQUM7SUFHbkIsSUFBRyxTQUFTLENBQUMsV0FBVyxZQUFZLFFBQVEsRUFDNUM7UUFDRSxTQUFTLENBQUMsSUFBSSxHQUFHLFNBQVMsQ0FBQyxXQUFXLENBQUM7UUFDdkMsT0FBTyxTQUFTLENBQUM7S0FDbEI7SUFHRCxJQUFHLFNBQVMsQ0FBQyxLQUFLLFlBQVksUUFBUSxFQUN0QztRQUNFLFNBQVMsQ0FBQyxJQUFJLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQztRQUNqQyxPQUFPLFNBQVMsQ0FBQztLQUNsQjtJQUdELElBQUcsU0FBUyxDQUFDLFNBQVMsS0FBSyxTQUFTO1FBQUUsT0FBTztJQUM3QyxJQUFHLFNBQVMsQ0FBQyxLQUFLLFlBQVksUUFBUTtRQUFFLE9BQU87SUFFL0MsTUFBTSxJQUFJLFdBQVcsQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO0FBQzFFLENBQUM7QUFBQSxDQUFDO0FBYUYseUJBQXlCLE1BQU0sRUFBRSxNQUFNO0lBRXJDLElBQUcsa0JBQWtCLEVBQ3JCO1FBQ0UsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFDcEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7S0FDckI7U0FFRDtRQUNFLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBQyxDQUFDLENBQUM7UUFDekUsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQztLQUMxRTtBQUNILENBQUM7QUFBQSxDQUFDO0FBZ0JGLG9CQUFvQixNQUFNLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTO0lBRXZELElBQUksSUFBSSxHQUFHLElBQUksQ0FBQztJQUVoQixJQUFHLENBQUMsTUFBTTtRQUNSLE1BQU0sSUFBSSxXQUFXLENBQUMsdUJBQXVCLENBQUMsQ0FBQztJQUVqRCxJQUFHLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNO1FBQy9CLE1BQU0sSUFBSSxXQUFXLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUU3QyxJQUFJLGVBQWUsR0FBRyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7SUFHbkUsSUFBRyxPQUFPLFlBQVksUUFBUSxFQUM5QjtRQUNFLElBQUcsU0FBUyxJQUFJLFNBQVM7WUFDdkIsTUFBTSxJQUFJLFdBQVcsQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1FBRXJFLFNBQVMsR0FBRyxPQUFPLENBQUM7UUFDcEIsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUN0QixPQUFPLEdBQUssU0FBUyxDQUFDO0tBQ3ZCO0lBQUEsQ0FBQztJQUVGLElBQUcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxJQUFJLFlBQVksUUFBUSxFQUM5QztRQUNFLElBQUcsU0FBUyxJQUFJLENBQUMsQ0FBQyxTQUFTLFlBQVksUUFBUSxDQUFDO1lBQzlDLE1BQU0sSUFBSSxXQUFXLENBQUMsd0NBQXdDLENBQUMsQ0FBQztRQUVsRSxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQ3RCLFNBQVMsR0FBRyxPQUFPLENBQUM7UUFDcEIsT0FBTyxHQUFLLFNBQVMsQ0FBQztLQUN2QjtJQUFBLENBQUM7SUFFRixJQUFHLFNBQVMsWUFBWSxRQUFRLEVBQ2hDO1FBQ0UsSUFBRyxTQUFTLElBQUksU0FBUztZQUN2QixNQUFNLElBQUksV0FBVyxDQUFDLDJDQUEyQyxDQUFDLENBQUM7UUFFckUsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUN0QixTQUFTLEdBQUcsU0FBUyxDQUFDO0tBQ3ZCO0lBQUEsQ0FBQztJQUVGLElBQUcsU0FBUyxJQUFJLFNBQVMsQ0FBQyxJQUFJLFlBQVksUUFBUTtRQUNoRCxJQUFHLFNBQVMsSUFBSSxDQUFDLENBQUMsU0FBUyxZQUFZLFFBQVEsQ0FBQztZQUM5QyxNQUFNLElBQUksV0FBVyxDQUFDLHdDQUF3QyxDQUFDLENBQUM7SUFFcEUsT0FBTyxHQUFHLE9BQU8sSUFBSSxFQUFFLENBQUM7SUFHeEIsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUV4QixJQUFHLFNBQVM7UUFDVixJQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUdoQyxJQUFHLGtCQUFrQjtRQUNuQixJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUE7O1FBRTVCLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFDLENBQUMsQ0FBQztJQUVqRSxJQUFJLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxJQUFJLENBQUMsQ0FBQztJQUczQywwQkFBMEIsS0FBSztRQUU3QixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUFBLENBQUM7SUFFRixJQUFJLENBQUMsWUFBWSxHQUFHO1FBRWxCLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUMsQ0FBQTtJQUNELElBQUksQ0FBQyxZQUFZLEdBQUcsVUFBUyxLQUFLO1FBR2hDLElBQUcsU0FBUyxFQUNaO1lBRUUsSUFBRyxTQUFTLENBQUMsbUJBQW1CO2dCQUM5QixTQUFTLENBQUMsbUJBQW1CLENBQUMsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7aUJBR3hELElBQUcsU0FBUyxDQUFDLGNBQWM7Z0JBQzlCLFNBQVMsQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLGdCQUFnQixDQUFDLENBQUM7U0FDdEQ7UUFBQSxDQUFDO1FBR0YsSUFBRyxLQUFLLEVBQ1I7WUFFRSxJQUFHLEtBQUssQ0FBQyxnQkFBZ0I7Z0JBQ3ZCLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztpQkFHakQsSUFBRyxLQUFLLENBQUMsV0FBVztnQkFDdkIsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztTQUMvQztRQUFBLENBQUM7UUFFRixTQUFTLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3BDLENBQUMsQ0FBQTtJQUVELElBQUcsQ0FBQyxrQkFBa0I7UUFDcEIsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUN2QztZQUNFLEdBQUcsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFDakMsR0FBRyxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztTQUNsQyxDQUFDLENBQUE7SUFFSixJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRzdCLElBQUksZUFBZSxHQUFRLE9BQU8sQ0FBQyxlQUFlLElBQVMsWUFBWSxDQUFDO0lBQ3hFLElBQUksb0JBQW9CLEdBQUcsT0FBTyxDQUFDLG9CQUFvQixJQUFJLGVBQWUsQ0FBQztJQUMzRSxJQUFJLGdCQUFnQixHQUFPLE9BQU8sQ0FBQyxnQkFBZ0IsSUFBUSxZQUFZLENBQUM7SUFDeEUsSUFBSSxrQkFBa0IsR0FBSyxPQUFPLENBQUMsa0JBQWtCLElBQU0sWUFBWSxDQUFDO0lBR3hFLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQztJQUVsQixJQUFJLFFBQVEsR0FBSSxJQUFJLE1BQU0sRUFBRSxDQUFDO0lBQzdCLElBQUksU0FBUyxHQUFHLElBQUksTUFBTSxFQUFFLENBQUM7SUFDN0IsSUFBSSxrQkFBa0IsR0FBRyxJQUFJLE1BQU0sRUFBRSxDQUFDO0lBRXRDLElBQUksV0FBVyxHQUFHLEVBQUUsQ0FBQztJQU1yQix1QkFBdUIsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJO1FBRXRDLElBQUksUUFBUSxHQUNaO1lBQ0UsT0FBTyxFQUFFLE9BQU87WUFFaEIsT0FBTyxFQUFFLFVBQVUsQ0FBQztnQkFFbEIsU0FBUyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDN0IsQ0FBQyxFQUNELGdCQUFnQixDQUFDO1NBQ2xCLENBQUM7UUFFRixTQUFTLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUFBLENBQUM7SUFLRixnQ0FBZ0MsR0FBRyxFQUFFLElBQUk7UUFFdkMsSUFBSSxPQUFPLEdBQUcsVUFBVSxDQUFDO1lBRXZCLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDdkMsQ0FBQyxFQUNELGtCQUFrQixDQUFDLENBQUM7UUFFcEIsa0JBQWtCLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUFBLENBQUM7SUFnQkYsb0JBQW9CLE1BQU0sRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTO1FBRXJELGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUUzQyxJQUFJLENBQUMsWUFBWSxHQUFHO1lBRWxCLE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUMsQ0FBQTtRQUNELElBQUksQ0FBQyxZQUFZLEdBQUcsVUFBUyxLQUFLO1lBRWhDLFNBQVMsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEMsQ0FBQyxDQUFBO1FBRUQsSUFBRyxDQUFDLGtCQUFrQjtZQUNwQixNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQ3ZDO2dCQUNFLEdBQUcsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7Z0JBQ2pDLEdBQUcsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7YUFDbEMsQ0FBQyxDQUFBO1FBRUosSUFBSSxRQUFRLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFLdkMsSUFBRyxDQUFDLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxFQUN0QztZQUNFLElBQUcsa0JBQWtCO2dCQUNuQixJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTs7Z0JBRW5DLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLFlBQVksRUFDeEM7b0JBQ0UsS0FBSyxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUM7aUJBQ3pCLENBQUMsQ0FBQztTQUNOO1FBRUQsSUFBSSxjQUFjLEdBQUcsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTdDLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQTtRQVU5QyxJQUFJLENBQUMsS0FBSyxHQUFHLFVBQVMsS0FBSyxFQUFFLE1BQU0sRUFBRSxTQUFTO1lBRzVDLElBQUcsS0FBSyxZQUFZLFFBQVEsSUFBSSxLQUFLLElBQUksS0FBSyxDQUFDLElBQUksWUFBWSxRQUFRLEVBQ3ZFO2dCQUNFLElBQUcsTUFBTSxJQUFJLFNBQVM7b0JBQ3BCLE1BQU0sSUFBSSxXQUFXLENBQUMsMENBQTBDLENBQUMsQ0FBQztnQkFFcEUsU0FBUyxHQUFHLEtBQUssQ0FBQztnQkFDbEIsTUFBTSxHQUFHLElBQUksQ0FBQztnQkFDZCxLQUFLLEdBQUcsU0FBUyxDQUFDO2FBQ25CO2lCQUVJLElBQUcsTUFBTSxZQUFZLFFBQVE7bUJBQy9CLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxZQUFZLFFBQVEsRUFDNUM7Z0JBQ0UsSUFBRyxTQUFTLElBQUksU0FBUztvQkFDdkIsTUFBTSxJQUFJLFdBQVcsQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO2dCQUVwRSxTQUFTLEdBQUcsTUFBTSxDQUFDO2dCQUNuQixNQUFNLEdBQUcsSUFBSSxDQUFDO2FBQ2Y7WUFBQSxDQUFDO1lBRUYsU0FBUyxHQUFHLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUd0QyxJQUFHLFFBQVE7Z0JBQ1QsWUFBWSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUVqQyxJQUFHLElBQUksSUFBSSxTQUFTLEVBQ3BCO2dCQUNFLElBQUcsS0FBSztvQkFDTixLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztnQkFFcEIsSUFBRyxNQUFNO29CQUNQLE1BQU0sQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO2FBQ3RCO1lBQUEsQ0FBQztZQUVGLElBQUksT0FBTyxDQUFDO1lBR1osSUFBRyxLQUFLLElBQUksTUFBTSxJQUFJLFNBQVMsRUFDL0I7Z0JBQ0UsSUFBRyxJQUFJLENBQUMsTUFBTSxJQUFJLFNBQVMsRUFDM0I7b0JBQ0UsSUFBRyxLQUFLO3dCQUNOLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQzs7d0JBRXpCLE1BQU0sQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztpQkFDN0I7Z0JBR0QsSUFBRyxjQUFjLEVBQ2pCO29CQUNFLElBQUcsY0FBYyxDQUFDLEtBQUssSUFBSSxTQUFTLElBQUksS0FBSzt3QkFDM0MsT0FBTzs0QkFDUDtnQ0FDRSxLQUFLLEVBQUUsS0FBSzs2QkFDYixDQUFDO3lCQUdKO3dCQUNFLElBQUksTUFBTSxHQUFHLEtBQUs7NEJBQ1AsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxLQUFLOzRCQUN0QixDQUFDLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQzt3QkFFckMsT0FBTzs0QkFDUDtnQ0FDRSxNQUFNLEVBQUUsTUFBTTtnQ0FDZCxNQUFNLEVBQUUsS0FBSyxJQUFJLE1BQU07NkJBQ3hCLENBQUM7cUJBQ0g7aUJBQ0Y7O29CQUVDLE9BQU87d0JBQ1A7NEJBQ0UsS0FBSyxFQUFHLEtBQUs7NEJBQ2IsTUFBTSxFQUFFLE1BQU07eUJBQ2YsQ0FBQztnQkFFSixPQUFPLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7YUFDcEM7aUJBR0ksSUFBRyxRQUFRO2dCQUNkLE9BQU8sR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDOztnQkFJM0IsT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFHNUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFHakMsU0FBUyxHQUFHLFNBQVMsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBRXBFLElBQUcsU0FBUztnQkFDVixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFakMsT0FBTyxPQUFPLENBQUM7UUFDakIsQ0FBQyxDQUFBO0lBQ0gsQ0FBQztJQUFBLENBQUM7SUFDRixRQUFRLENBQUMsVUFBVSxFQUFFLGVBQWUsQ0FBQyxDQUFDO0lBR3RDLGdCQUFnQixPQUFPO1FBRXJCLElBQUksR0FBRyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQixJQUFHLENBQUMsR0FBRztZQUFFLE9BQU87UUFFaEIsT0FBTyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFNUIsSUFBSSxPQUFPLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QyxJQUFHLENBQUMsT0FBTztZQUFFLE9BQU87UUFFcEIsWUFBWSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUc5QixzQkFBc0IsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBQUEsQ0FBQztJQU9GLElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBUyxPQUFPO1FBRTVCLElBQUcsT0FBTztZQUFFLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRW5DLEtBQUksSUFBSSxPQUFPLElBQUksV0FBVztZQUM1QixNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDcEIsQ0FBQyxDQUFDO0lBR0YsSUFBSSxDQUFDLEtBQUssR0FBRztRQUdYLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNwQyxJQUFHLFNBQVMsSUFBSSxTQUFTLENBQUMsS0FBSztZQUM1QixTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7UUFHckIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBRWQsa0JBQWtCLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBR3pDLFNBQVMsQ0FBQyxPQUFPLENBQUMsVUFBUyxRQUFRO1lBRWpDLFlBQVksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUM7SUFlRixJQUFJLENBQUMsTUFBTSxHQUFHLFVBQVMsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLFFBQVE7UUFHOUQsSUFBRyxNQUFNLFlBQVksUUFBUSxFQUM3QjtZQUNFLElBQUcsSUFBSSxJQUFJLFNBQVM7Z0JBQ2xCLE1BQU0sSUFBSSxXQUFXLENBQUMsMENBQTBDLENBQUMsQ0FBQztZQUVwRSxRQUFRLEdBQUksTUFBTSxDQUFDO1lBQ25CLFNBQVMsR0FBRyxTQUFTLENBQUM7WUFDdEIsSUFBSSxHQUFRLFNBQVMsQ0FBQztZQUN0QixNQUFNLEdBQU0sU0FBUyxDQUFDO1NBQ3ZCO2FBRUksSUFBRyxJQUFJLFlBQVksUUFBUSxFQUNoQztZQUNFLElBQUcsU0FBUyxJQUFJLFNBQVM7Z0JBQ3ZCLE1BQU0sSUFBSSxXQUFXLENBQUMsMENBQTBDLENBQUMsQ0FBQztZQUVwRSxRQUFRLEdBQUksSUFBSSxDQUFDO1lBQ2pCLFNBQVMsR0FBRyxTQUFTLENBQUM7WUFDdEIsSUFBSSxHQUFRLFNBQVMsQ0FBQztTQUN2QjthQUVJLElBQUcsU0FBUyxZQUFZLFFBQVEsRUFDckM7WUFDRSxJQUFHLFFBQVEsSUFBSSxTQUFTO2dCQUN0QixNQUFNLElBQUksV0FBVyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7WUFFcEUsUUFBUSxHQUFJLFNBQVMsQ0FBQztZQUN0QixTQUFTLEdBQUcsU0FBUyxDQUFDO1NBQ3ZCO1FBQUEsQ0FBQztRQUVGLElBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxTQUFTLEVBQzNCO1lBQ0UsTUFBTSxHQUFHLE1BQU0sSUFBSSxFQUFFLENBQUM7WUFFdEIsTUFBTSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1NBQzNCO1FBQUEsQ0FBQztRQUVGLElBQUcsSUFBSSxJQUFJLFNBQVMsRUFDcEI7WUFDRSxNQUFNLEdBQUcsTUFBTSxJQUFJLEVBQUUsQ0FBQztZQUV0QixNQUFNLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztTQUNwQjtRQUFBLENBQUM7UUFHRixJQUFJLE9BQU8sR0FDWDtZQUNFLE1BQU0sRUFBRSxNQUFNO1lBQ2QsTUFBTSxFQUFFLE1BQU07U0FDZixDQUFDO1FBRUYsSUFBRyxRQUFRLEVBQ1g7WUFDRSxJQUFJLEVBQUUsR0FBRyxTQUFTLEVBQUUsQ0FBQztZQUNyQixJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7WUFFaEIsT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBRW5DLDBCQUEwQixLQUFLLEVBQUUsTUFBTTtnQkFFckMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFFckIsUUFBUSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztZQUMxQixDQUFDO1lBQUEsQ0FBQztZQUVGLElBQUksT0FBTyxHQUNYO2dCQUNFLE9BQU8sRUFBVSxPQUFPO2dCQUN4QixRQUFRLEVBQVMsZ0JBQWdCO2dCQUNqQyxlQUFlLEVBQUUsZUFBZSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUU7YUFDL0MsQ0FBQztZQUVGLElBQUksZ0JBQWdCLEdBQUcsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBRWpELHFCQUFxQixTQUFTO2dCQUU1QixJQUFJLEVBQUUsR0FBRyxDQUFDLE1BQU0sS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFDdEUsT0FBTyxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsR0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pFLFdBQVcsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBQyxDQUFDO2dCQUM1QyxRQUFRLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBRWhDLFNBQVMsR0FBRyxTQUFTLElBQUksZ0JBQWdCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNqRSxJQUFHLFNBQVM7b0JBQ1YsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUVqQyxPQUFPLE9BQU8sQ0FBQztZQUNqQixDQUFDO1lBQUEsQ0FBQztZQUVGLGVBQWUsU0FBUztnQkFFdEIsU0FBUyxHQUFHLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFFdEMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUMsNkJBQTZCLEVBQUMsT0FBTyxDQUFDLENBQUM7Z0JBRTVELElBQUksT0FBTyxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQy9DLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFFdEIsT0FBTyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDaEMsQ0FBQztZQUFBLENBQUM7WUFFRjtnQkFFRSxJQUFHLE9BQU8sR0FBRyxXQUFXO29CQUN0QixPQUFPLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFFMUIsSUFBSSxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztnQkFDM0MsS0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7Z0JBRTVCLEtBQUssQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO2dCQUVwQixnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUN6QixDQUFDO1lBQUEsQ0FBQztZQUVGLE9BQU8sV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQy9CO1FBQUEsQ0FBQztRQUdGLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRS9CLFNBQVMsR0FBRyxTQUFTLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzdDLElBQUcsU0FBUztZQUNWLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVqQyxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDLENBQUM7SUFhRixJQUFJLENBQUMsTUFBTSxHQUFHLFVBQVMsT0FBTyxFQUFFLFNBQVM7UUFFdkMsSUFBRyxDQUFDLE9BQU87WUFDVCxNQUFNLElBQUksU0FBUyxDQUFDLHdCQUF3QixDQUFDLENBQUM7UUFFaEQsSUFDQTtZQUNFLE9BQU8sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQ2xDO1FBQ0QsT0FBTSxDQUFDLEVBQ1A7WUFFRSxPQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1NBQ2xDO1FBQUEsQ0FBQztRQUVGLElBQUksRUFBRSxHQUFPLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDeEIsSUFBSSxHQUFHLEdBQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztRQUN6QixJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBQzVCLElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDO1FBRWxDLElBQUksSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFDdkIsSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQztRQUd2QixJQUFHLElBQUksQ0FBQyxNQUFNLElBQUksU0FBUyxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU87UUFHM0QsSUFBRyxFQUFFLElBQUksU0FBUyxJQUFJLEdBQUcsSUFBSSxTQUFTLEVBQ3RDO1lBQ0UsSUFBSSxZQUFZLEdBQUcsSUFBSSxlQUFlLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBRXZELElBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDO2dCQUFFLE9BQU87WUFDOUMsT0FBTyxZQUFZLENBQUM7U0FDckI7UUFBQSxDQUFDO1FBR0Y7WUFHRSxTQUFTLEdBQUcsY0FBYyxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUM3RCxJQUFHLFNBQVMsRUFDWjtnQkFDRSxJQUFJLFFBQVEsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDdkMsSUFBRyxRQUFRO29CQUNULE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7YUFDM0M7WUFBQSxDQUFDO1lBRUYsSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBQ3pDLElBQUksT0FBTyxHQUFHLElBQUksVUFBVSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztZQUVyRSxJQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQztnQkFBRSxPQUFPO1lBQ3pDLE9BQU8sT0FBTyxDQUFDO1FBQ2pCLENBQUM7UUFBQSxDQUFDO1FBRUYseUJBQXlCLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTTtZQUU3QyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNsQyxDQUFDO1FBQUEsQ0FBQztRQUVGLDRCQUE0QixPQUFPO1lBRWpDLE9BQU8sQ0FBQyxJQUFJLENBQUMsNEJBQTRCLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFHcEQsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3RCLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNwQyxDQUFDO1FBQUEsQ0FBQztRQUlGLElBQUcsTUFBTSxFQUNUO1lBRUUsSUFBRyxJQUFJLElBQUksU0FBUyxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTSxFQUMzQztnQkFDRSxJQUFJLE9BQU8sR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDdEMsSUFBRyxPQUFPLEVBQ1Y7b0JBQ0UsSUFBSSxlQUFlLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQztvQkFFOUMsSUFBRyxNQUFNLElBQUksZUFBZSxDQUFDLEtBQUs7d0JBQ2hDLE9BQU8sZUFBZSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztvQkFFMUMsSUFBRyxNQUFNLElBQUksZUFBZSxDQUFDLFFBQVE7d0JBQ25DLE9BQU8sZUFBZSxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7b0JBRWhELE9BQU8sY0FBYyxFQUFFLENBQUM7aUJBQ3pCO2dCQUVELElBQUksU0FBUyxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ2xELElBQUcsU0FBUztvQkFDVixPQUFPLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQ3hDO1lBR0QsT0FBTyxjQUFjLEVBQUUsQ0FBQztTQUN6QjtRQUFBLENBQUM7UUFFRixJQUFJLEtBQUssR0FBSSxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQzNCLElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFHNUIsSUFBRyxLQUFLLElBQUssS0FBSyxDQUFDLElBQUksSUFBSyxLQUFLLENBQUMsSUFBSSxJQUFLLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTztRQUMvRCxJQUFHLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBRy9ELElBQUksT0FBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3RDLElBQUcsQ0FBQyxPQUFPLEVBQ1g7WUFDRSxJQUFJLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ2xELElBQUcsU0FBUztnQkFDVixPQUFPLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBRXZDLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQywwQ0FBMEMsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUMxRTtRQUFBLENBQUM7UUFHRixlQUFlLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMxQyxDQUFDLENBQUM7QUFDSixDQUFDO0FBQUEsQ0FBQztBQUNGLFFBQVEsQ0FBQyxVQUFVLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFHbkMsVUFBVSxDQUFDLGVBQWUsR0FBRyxlQUFlLENBQUM7QUFHN0MsTUFBTSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUM7QUFFNUIsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQ25DLElBQUksVUFBVSxHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0FBRWpELFVBQVUsQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0FBQzdCLFVBQVUsQ0FBQyxPQUFPLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztBQUMzQyxVQUFVLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQzs7O0FDenlCN0IsY0FBYyxPQUFPLEVBQUUsRUFBRTtJQUV2QixJQUFJLE1BQU0sR0FDVjtRQUNFLE9BQU8sRUFBRSxLQUFLO0tBQ2YsQ0FBQztJQUdGLElBQUcsT0FBTyxDQUFDLE1BQU0sRUFDakI7UUFDRSxNQUFNLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFFL0IsSUFBRyxPQUFPLENBQUMsTUFBTTtZQUNmLE1BQU0sQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztRQUdqQyxJQUFHLEVBQUUsSUFBSSxTQUFTO1lBQ2hCLE1BQU0sQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO0tBQ2xCO1NBR0ksSUFBRyxFQUFFLElBQUksU0FBUyxFQUN2QjtRQUNFLElBQUcsT0FBTyxDQUFDLEtBQUssRUFDaEI7WUFDRSxJQUFHLE9BQU8sQ0FBQyxNQUFNLEtBQUssU0FBUztnQkFDN0IsTUFBTSxJQUFJLFNBQVMsQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1lBRTNELE1BQU0sQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztTQUM5QjthQUNJLElBQUcsT0FBTyxDQUFDLE1BQU0sS0FBSyxTQUFTO1lBQ2xDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQzs7WUFFL0IsTUFBTSxJQUFJLFNBQVMsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBRXZELE1BQU0sQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO0tBQ2hCO0lBQUEsQ0FBQztJQUVGLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNoQyxDQUFDO0FBQUEsQ0FBQztBQVdGLGdCQUFnQixPQUFPO0lBRXJCLElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQztJQUVyQixJQUFHLE9BQU8sT0FBTyxLQUFLLFFBQVEsSUFBSSxPQUFPLFlBQVksTUFBTSxFQUFFO1FBQzNELE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0tBQzlCO0lBSUQsSUFBSSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQztJQUM3QixJQUFHLE9BQU8sS0FBSyxLQUFLO1FBQ2xCLE1BQU0sSUFBSSxTQUFTLENBQUMsMkJBQTJCLEdBQUcsT0FBTyxHQUFHLEtBQUssR0FBRyxPQUFPLENBQUMsQ0FBQztJQUcvRSxJQUFHLE1BQU0sQ0FBQyxNQUFNLElBQUksU0FBUyxFQUM3QjtRQUNFLElBQUcsTUFBTSxDQUFDLEVBQUUsSUFBSSxTQUFTO1lBQ3ZCLE1BQU0sSUFBSSxTQUFTLENBQUMsbUJBQW1CLEdBQUMsT0FBTyxDQUFDLENBQUM7UUFFbkQsSUFBSSxjQUFjLEdBQUcsTUFBTSxDQUFDLE1BQU0sS0FBSyxTQUFTLENBQUM7UUFDakQsSUFBSSxhQUFhLEdBQUksTUFBTSxDQUFDLEtBQUssS0FBTSxTQUFTLENBQUM7UUFHakQsSUFBRyxjQUFjLElBQUksYUFBYTtZQUNoQyxNQUFNLElBQUksU0FBUyxDQUFDLHFDQUFxQyxHQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXJFLElBQUcsQ0FBQyxjQUFjLElBQUksQ0FBQyxhQUFhO1lBQ2xDLE1BQU0sSUFBSSxTQUFTLENBQUMsaUNBQWlDLEdBQUMsT0FBTyxDQUFDLENBQUM7UUFFakUsTUFBTSxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sTUFBTSxDQUFDLEVBQUUsQ0FBQztLQUNsQjtJQUdELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFBQSxDQUFDO0FBR0YsT0FBTyxDQUFDLElBQUksR0FBSyxJQUFJLENBQUM7QUFDdEIsT0FBTyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7OztBQ3RHeEIsY0FBYyxPQUFPO0lBRW5CLE1BQU0sSUFBSSxTQUFTLENBQUMscUJBQXFCLENBQUMsQ0FBQztBQUM3QyxDQUFDO0FBQUEsQ0FBQztBQUVGLGdCQUFnQixPQUFPO0lBRXJCLE1BQU0sSUFBSSxTQUFTLENBQUMscUJBQXFCLENBQUMsQ0FBQztBQUM3QyxDQUFDO0FBQUEsQ0FBQztBQUdGLE9BQU8sQ0FBQyxJQUFJLEdBQUssSUFBSSxDQUFDO0FBQ3RCLE9BQU8sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDOzs7QUNaeEIsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQ25DLElBQUksTUFBTSxHQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUdsQyxPQUFPLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztBQUMxQixPQUFPLENBQUMsTUFBTSxHQUFJLE1BQU0sQ0FBQzs7O0FDb0J6QixNQUFNLENBQUMsV0FBVyxHQUFHLFVBQVUsUUFBUSxFQUFFLGdCQUFnQjtJQUNyRCxJQUFJLFNBQVMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBRXhHLFFBQVEsQ0FBQztZQUNMLEtBQUssRUFBRSxJQUFJO1NBQ2QsQ0FBQyxDQUFDO1FBQ0gsT0FBTztLQUNWO0lBS0QsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLGVBQWUsRUFBRTtRQUM3QixRQUFRLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRTtZQUN0QixLQUFLLEVBQUU7Z0JBQ0gsY0FBYyxFQUFFLFFBQVE7Z0JBQ3hCLFdBQVcsRUFBRSxRQUFRO2FBQ3hCO1NBQ0osQ0FBQyxDQUFDO1FBQ0gsT0FBTztLQUNWO0lBRUQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO0lBRXJELDBCQUEwQixLQUFLO1FBQzNCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSTtZQUFFLE9BQU87UUFFeEIsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFO1lBQ2hDLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsS0FBSyx1QkFBdUIsRUFBRTtnQkFDNUQsUUFBUSxDQUFDLG1CQUFtQixDQUFDLENBQUM7YUFDakM7aUJBQU07Z0JBQ0gsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLG9CQUFvQixDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDO2FBQy9JO1lBR0QsTUFBTSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1NBQzNEO1FBRUQsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFO1lBQ2xDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLElBQUksRUFBRSxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztZQUd6RyxNQUFNLENBQUMsbUJBQW1CLENBQUMsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7U0FDM0Q7SUFDTCxDQUFDO0lBRUQsSUFBSSxDQUFDLGdCQUFnQixFQUFFO1FBQ25CLFVBQVUsQ0FBQyxzQkFBc0IsRUFBRSxHQUFHLENBQUMsQ0FBQztLQUMzQztTQUNJO1FBQ0QsVUFBVSxDQUFDO1lBQ1Asc0JBQXNCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUM3QyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7S0FDWDtBQUNMLENBQUMsQ0FBQztBQUVGLDhCQUE4QixLQUFLLEVBQUUsUUFBUSxFQUFFLG9CQUFvQjtJQUMvRCxJQUFJLGtCQUFrQixHQUFHO1FBQ3JCLEtBQUssRUFBRSxLQUFLO1FBQ1osS0FBSyxFQUFFO1lBQ0gsU0FBUyxFQUFFO2dCQUNQLGlCQUFpQixFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTO2dCQUMvQyxRQUFRLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDakUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUk7YUFDdkU7WUFDRCxRQUFRLEVBQUUsRUFBRTtTQUNmO0tBQ0osQ0FBQztJQUVGLElBQUksQ0FBQyxDQUFDLG9CQUFvQixFQUFFO1FBQ3hCLGtCQUFrQixDQUFDLEtBQUssR0FBRztZQUN2QixTQUFTLEVBQUU7Z0JBQ1AsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVM7YUFFbEQ7WUFDRCxRQUFRLEVBQUUsRUFBRTtTQUNmLENBQUM7S0FDTDtJQUVELElBQUksUUFBUSxFQUFFO1FBQ1Ysa0JBQWtCLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsR0FBRyxRQUFRLENBQUM7UUFFbEUsSUFBSSxrQkFBa0IsQ0FBQyxLQUFLLElBQUksa0JBQWtCLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRTtZQUNoRSxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLG1CQUFtQixHQUFHLFFBQVEsQ0FBQztTQUNyRTtLQUNKO0lBRUQsT0FBTyxrQkFBa0IsQ0FBQztBQUM5QixDQUFDO0FBRUQsZ0NBQWdDLGdCQUFnQjtJQUM1QyxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1QsVUFBVSxDQUFDO1lBQ1Asc0JBQXNCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUM3QyxDQUFDLENBQUMsQ0FBQztRQUNILE9BQU87S0FDVjtJQUVELElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO1FBQ2xCLFVBQVUsQ0FBQztZQUNQLHNCQUFzQixDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDN0MsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ1IsT0FBTztLQUNWO0lBRUQsSUFBSSxDQUFDLGdCQUFnQixFQUFFO1FBQ25CLE1BQU0sQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDO1lBQzdCLGVBQWUsRUFBRSxJQUFJO1NBQ3hCLEVBQUUsR0FBRyxDQUFDLENBQUM7S0FDWDtTQUNJLElBQUksQ0FBQyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRTtRQUNqQyxNQUFNLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQztZQUM3QixxQkFBcUIsRUFBRSxnQkFBZ0I7U0FDMUMsRUFBRSxHQUFHLENBQUMsQ0FBQztLQUNYO1NBQ0k7UUFDRCxNQUFNLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQztZQUM3Qix3QkFBd0IsRUFBRSxJQUFJO1NBQ2pDLEVBQUUsR0FBRyxDQUFDLENBQUM7S0FDWDtBQUNMLENBQUM7QUFFRCxJQUFJLE1BQU0sQ0FBQztBQUdYLE1BQU0sQ0FBQyxvQkFBb0IsR0FBRyxVQUFVLFFBQVE7SUFDNUMsVUFBVSxDQUFDO1FBQ1AsV0FBVyxDQUFDLFVBQVUsS0FBSyxFQUFFLFFBQVEsRUFBRSxrQkFBa0I7WUFDckQsSUFBSSxDQUFDLGtCQUFrQixFQUFFO2dCQUNyQixrQkFBa0IsR0FBRztvQkFDakIsS0FBSyxFQUFFLElBQUk7aUJBQ2QsQ0FBQzthQUNMO1lBRUQsUUFBUSxDQUFDLEtBQUssRUFBRSxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5QyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFDO0FBRUYsb0JBQW9CLFlBQVk7SUFDNUIsSUFBSSxNQUFNLEVBQUU7UUFDUixZQUFZLEVBQUUsQ0FBQztRQUNmLE9BQU87S0FDVjtJQUVELE1BQU0sR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzFDLE1BQU0sQ0FBQyxNQUFNLEdBQUc7UUFDWixNQUFNLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUN2QixZQUFZLEVBQUUsQ0FBQztJQUNuQixDQUFDLENBQUM7SUFDRixNQUFNLENBQUMsR0FBRyxHQUFHLHNFQUFzRSxDQUFDO0lBQ3BGLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztJQUM5QixDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNwRSxDQUFDO0FBRUQsTUFBTSxDQUFDLHdCQUF3QixHQUFHLFVBQVUsUUFBUTtJQUVoRCxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsZUFBZSxFQUFFO1FBQzdCLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQzlCLE9BQU87S0FDVjtJQUVELE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUVyRCwwQkFBMEIsS0FBSztRQUMzQixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUk7WUFBRSxPQUFPO1FBRXhCLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsRUFBRTtZQUNsQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBRzNDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztTQUMzRDtJQUNMLENBQUM7SUFFRCxVQUFVLENBQUMsbUNBQW1DLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDekQsQ0FBQyxDQUFDO0FBRUY7SUFDSSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1QsVUFBVSxDQUFDLG1DQUFtQyxDQUFDLENBQUM7UUFDaEQsT0FBTztLQUNWO0lBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUU7UUFDbEIsVUFBVSxDQUFDLG1DQUFtQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3JELE9BQU87S0FDVjtJQUVELE1BQU0sQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDO1FBQzdCLHdCQUF3QixFQUFFLElBQUk7S0FDakMsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUNaLENBQUM7QUFFRCxPQUFPLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQzs7O0FDMU5sQyxJQUFJLGlCQUFpQixHQUFHLFFBQVEsQ0FBQztBQUNqQyxJQUFJLFFBQVEsQ0FBQztBQUNiLElBQUksY0FBYyxDQUFDO0FBQ25CLElBQUksU0FBUyxHQUFHLE9BQU8sTUFBTSxDQUFDLGNBQWMsS0FBSyxXQUFXLENBQUM7QUFDN0QsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzFFLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDO0FBRTNDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsVUFBVSxLQUFLO0lBQzlDLElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRTtRQUN4QyxPQUFPO0tBQ1Y7SUFDRCxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDbEMsQ0FBQyxDQUFDLENBQUM7QUFHSCwyQkFBMkIsSUFBSTtJQUUzQixJQUFJLElBQUksSUFBSSx1QkFBdUIsRUFBRTtRQUNqQyxJQUFJLGNBQWM7WUFDZCxPQUFPLGNBQWMsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDOztZQUUvQyxNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7S0FDaEQ7SUFFRCxJQUFJLElBQUksSUFBSSxxQ0FBcUMsRUFBRTtRQUMvQyxpQkFBaUIsR0FBRyxTQUFTLENBQUM7S0FDakM7SUFFRCxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksY0FBYyxFQUFFO1FBQ2pDLGNBQWMsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsb0JBQW9CLEtBQUssSUFBSSxDQUFDLENBQUM7S0FDaEY7QUFDTCxDQUFDO0FBR0Qsb0NBQW9DLFFBQVE7SUFDeEMsSUFBSSxDQUFDLFFBQVE7UUFBRSxPQUFPO0lBQ3RCLElBQUksaUJBQWlCLElBQUksU0FBUztRQUFFLE9BQU8sUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRzFELE1BQU0sQ0FBQyxXQUFXLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pDLFVBQVUsQ0FBQztRQUNQLElBQUksaUJBQWlCLElBQUksUUFBUSxFQUFFO1lBQy9CLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUNuQjs7WUFBTSxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDMUIsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ2IsQ0FBQztBQUdELHFCQUFxQixRQUFRO0lBQ3pCLElBQUksQ0FBQyxRQUFRO1FBQ1QsTUFBTSxvQ0FBb0MsQ0FBQztJQUMvQyxJQUFJLFFBQVE7UUFDUixPQUFPLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5QixjQUFjLEdBQUcsUUFBUSxDQUFDO0lBQzFCLE1BQU0sQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzVDLENBQUM7QUFHRCwyQkFBMkIsR0FBRyxFQUFFLFFBQVE7SUFDcEMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPO1FBQUUsTUFBTSx1REFBdUQsQ0FBQztJQUN4RixJQUFJLENBQUMsUUFBUTtRQUFFLE1BQU0sb0NBQW9DLENBQUM7SUFFMUQsSUFBSSxRQUFRO1FBQUUsT0FBTyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFeEMsY0FBYyxHQUFHLFFBQVEsQ0FBQztJQUMxQixNQUFNLENBQUMsV0FBVyxDQUFDO1FBQ2YscUJBQXFCLEVBQUUsR0FBRztLQUM3QixFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ1osQ0FBQztBQUdELDhCQUE4QixRQUFRO0lBQ2xDLElBQUksQ0FBQyxRQUFRO1FBQUUsTUFBTSxvQ0FBb0MsQ0FBQztJQUMxRCxJQUFJLFFBQVE7UUFBRSxPQUFPLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUV4QyxjQUFjLEdBQUcsUUFBUSxDQUFDO0lBQzFCLE1BQU0sQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDOUMsQ0FBQztBQUVELGtDQUFrQyxXQUFXLEVBQUUsUUFBUTtJQUNuRCxJQUFJLFNBQVM7UUFDVCxPQUFPLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNsQyxJQUFJLFNBQVMsQ0FBQyxNQUFNLElBQUksQ0FBQyxFQUFFO1FBQ3ZCLFFBQVEsR0FBRyxXQUFXLENBQUM7UUFDdkIsV0FBVyxHQUFHLGtDQUFrQyxDQUFDO0tBQ3BEO0lBQ0QsSUFBSSxLQUFLLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQyxLQUFLLENBQUMsR0FBRyxHQUFHLHFCQUFxQixHQUFHLFdBQVcsR0FBRyxXQUFXLENBQUM7SUFDOUQsS0FBSyxDQUFDLE1BQU0sR0FBRztRQUNYLGlCQUFpQixHQUFHLFFBQVEsQ0FBQztRQUM3QixNQUFNLENBQUMsV0FBVyxDQUFDLGVBQWUsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUN6QyxVQUFVLENBQUM7WUFDUCxJQUFJLGlCQUFpQixJQUFJLFFBQVEsRUFBRTtnQkFDL0IsUUFBUSxDQUFDLG9CQUFvQixDQUFDLENBQUM7YUFDbEM7O2dCQUNHLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3RDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNiLENBQUMsQ0FBQztJQUNGLEtBQUssQ0FBQyxPQUFPLEdBQUc7UUFDWixRQUFRLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDOUIsQ0FBQyxDQUFDO0FBQ04sQ0FBQztBQUVELHVDQUF1QyxRQUFRO0lBQzNDLG9CQUFvQixDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBR0QsOEJBQThCLFFBQVEsRUFBRSx3QkFBd0I7SUFDNUQsUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUNkLElBQUksd0JBQXdCLEdBQUc7UUFDM0IsY0FBYyxFQUFFLFFBQVE7UUFDeEIsV0FBVyxFQUFFLFFBQVE7S0FDeEIsQ0FBQztJQUNGLElBQUksU0FBUztRQUNULE9BQU8sUUFBUSxDQUFDLElBQUksRUFBRSx3QkFBd0IsQ0FBQyxDQUFDO0lBR3BELElBQUksa0JBQWtCLEdBQUc7UUFDckIsU0FBUyxFQUFFO1lBQ1AsaUJBQWlCLEVBQUUsaUJBQWlCO1lBQ3BDLFFBQVEsRUFBRSxNQUFNLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSTtZQUNuRCxTQUFTLEVBQUUsTUFBTSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUk7U0FDekQ7UUFDRCxRQUFRLEVBQUUsRUFBRTtLQUNmLENBQUM7SUFJRixJQUFJLGlCQUFpQixJQUFJLFNBQVMsSUFBSSxDQUFDLFFBQVEsRUFBRTtRQUM3QyxJQUFJLHdCQUF3QixFQUFFO1lBQzFCLG9CQUFvQixDQUFDLFVBQVUsUUFBUSxFQUFFLG9CQUFvQjtnQkFDekQsa0JBQWtCLENBQUMsU0FBUyxDQUFDLG1CQUFtQixHQUFHLFFBQVEsQ0FBQztnQkFFNUQsSUFBSSxvQkFBb0IsRUFBRTtvQkFDdEIsa0JBQWtCLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxDQUFDO2lCQUNsRDtnQkFDRCxRQUFRLENBQUMsUUFBUSxJQUFJLHVCQUF1QixDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1lBQ3hGLENBQUMsQ0FBQyxDQUFDO1NBQ047YUFDSTtZQUNELFdBQVcsQ0FBQyxVQUFVLFFBQVE7Z0JBQzFCLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsR0FBRyxRQUFRLENBQUM7Z0JBQzVELFFBQVEsQ0FBQyxRQUFRLElBQUksdUJBQXVCLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLGtCQUFrQixDQUFDLENBQUM7WUFDeEYsQ0FBQyxDQUFDLENBQUM7U0FDTjtRQUNELE9BQU87S0FDVjtJQUdELElBQUksaUJBQWlCLElBQUksU0FBUyxFQUFFO1FBQ2hDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsR0FBRyxRQUFRLENBQUM7S0FDL0Q7SUFHRCxRQUFRLENBQUMsSUFBSSxFQUFFLGtCQUFrQixDQUFDLENBQUM7QUFDdkMsQ0FBQztBQUVELE9BQU8sQ0FBQyxvQkFBb0IsR0FBRyxvQkFBb0IsQ0FBQztBQUNwRCxPQUFPLENBQUMsNkJBQTZCLEdBQUcsNkJBQTZCLENBQUM7QUFDdEUsT0FBTyxDQUFDLDBCQUEwQixHQUFHLDBCQUEwQixDQUFDO0FBQ2hFLE9BQU8sQ0FBQyx3QkFBd0IsR0FBRyx3QkFBd0IsQ0FBQztBQUM1RCxPQUFPLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7O0FDbEpsQyxpQ0FBb0M7QUFDcEMsMkJBQThCO0FBQzlCLG1DQUFzQztBQWdCdEM7SUFXSSxvQkFBb0IsYUFBc0M7UUFBMUQsaUJBMEJDO1FBMUJtQixrQkFBYSxHQUFiLGFBQWEsQ0FBeUI7UUFQMUQsMEJBQXFCLEdBQXNCLEVBQUUsQ0FBQztRQUM5Qyx5QkFBb0IsR0FBc0IsRUFBRSxDQUFDO1FBRTdDLHFCQUFnQixHQUFzQixFQUFFLENBQUM7UUFFakMsMkJBQXNCLEdBQUcsS0FBSyxDQUFDO1FBR25DLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRTFKLElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBRTVELElBQUksQ0FBQyxFQUFFLENBQUMsY0FBYyxHQUFHLFVBQUEsS0FBSztZQUMxQixJQUFNLFNBQVMsR0FBb0IsS0FBSyxDQUFDLFNBQVMsQ0FBQztZQUNuRCxJQUFJLFNBQVMsRUFBRTtnQkFDWCxLQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFrQixFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztnQkFDcEYsS0FBSSxDQUFDLHNCQUFzQixHQUFHLEtBQUssQ0FBQztnQkFDcEMsS0FBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQ3REO2lCQUFNLElBQUksQ0FBQyxLQUFJLENBQUMsc0JBQXNCLEVBQUU7Z0JBQ3JDLEtBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLENBQUM7YUFDdEM7UUFDTCxDQUFDLENBQUM7UUFFRixJQUFJLENBQUMsRUFBRSxDQUFDLHNCQUFzQixHQUFHO1lBQzdCLElBQUksS0FBSSxDQUFDLEVBQUUsQ0FBQyxjQUFjLEtBQUssUUFBUSxFQUFFO2dCQUNyQyxPQUFPLEtBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO29CQUNyQyxLQUFJLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBa0IsS0FBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7aUJBQzNFO2FBQ0o7UUFDTCxDQUFDLENBQUM7UUFFRixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDakIsQ0FBQztJQVNELDBCQUFLLEdBQUw7UUFBQSxpQkFpQkM7UUFoQkcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQy9CLElBQUksS0FBSSxDQUFDLEVBQUUsQ0FBQyxjQUFjLEtBQUssUUFBUSxFQUFFO2dCQUNyQyxNQUFNLENBQUMsa0pBQWtKLENBQUMsQ0FBQzthQUM5SjtZQUNELElBQUksQ0FBQyxDQUFDLEtBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFO2dCQUNsQyxLQUFJLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDO2FBQ3JEO1lBR0QsSUFBSSxLQUFJLENBQUMsYUFBYSxDQUFDLElBQUksS0FBSyxVQUFVO2dCQUN0QyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssUUFBUSxJQUFJLFFBQVEsQ0FBQyxPQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsRUFBRTtnQkFDdkYsS0FBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDO2FBQ3hDO1lBRUQsT0FBTyxFQUFFLENBQUM7UUFDZCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFLRCw0QkFBTyxHQUFQO1FBQUEsaUJBdUJDO1FBdEJHLE9BQU8sQ0FBQyxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUN0QyxJQUFJO1lBQ0EsSUFBSSxJQUFJLENBQUMsRUFBRSxFQUFFO2dCQUNULElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQyxjQUFjLEtBQUssUUFBUSxFQUFFO29CQUNyQyxPQUFPO2lCQUNWO2dCQUNELElBQUksQ0FBQyxxQkFBcUIsR0FBRyxFQUFFLENBQUM7Z0JBQ2hDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxFQUFFLENBQUM7Z0JBRS9CLElBQUksQ0FBQyxFQUFFLENBQUMsZUFBZSxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQUEsR0FBRztvQkFDakMsS0FBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDekIsQ0FBQyxDQUFDLENBQUM7Z0JBTUgsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUNuQjtTQUNKO1FBQUMsT0FBTyxHQUFHLEVBQUU7WUFDVixPQUFPLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO1NBQzFEO0lBQ0wsQ0FBQztJQU1ELGtDQUFhLEdBQWI7UUFBQSxpQkFnQ0M7UUEvQkcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQy9CLElBQUksVUFBVSxFQUFFLFVBQVUsR0FBRyxJQUFJLENBQUM7WUFHbEMsSUFBSSxDQUFDLENBQUMsS0FBSSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRTtnQkFDdkMsVUFBVSxHQUFHLENBQUMsT0FBTyxLQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDO29CQUMzRSxLQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNyRCxVQUFVLEdBQUcsQ0FBQyxPQUFPLEtBQUksQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUM7b0JBQzNFLEtBQUksQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7YUFDeEQ7WUFFRCxJQUFNLFdBQVcsR0FBb0I7Z0JBQ2pDLG1CQUFtQixFQUFFLENBQUUsQ0FBQyxLQUFJLENBQUMsYUFBYSxDQUFDLElBQUksS0FBSyxVQUFVLElBQUksVUFBVSxDQUFDO2dCQUM3RSxtQkFBbUIsRUFBRSxDQUFFLENBQUMsS0FBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEtBQUssVUFBVSxJQUFJLFVBQVUsQ0FBQzthQUNoRixDQUFDO1lBRUYsT0FBTyxDQUFDLEtBQUssQ0FBQyxpQ0FBaUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7WUFFL0UsS0FBSSxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQUEsS0FBSztnQkFDdkMsT0FBTyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO2dCQUNuQyxPQUFPLEtBQUksQ0FBQyxFQUFFLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDOUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNKLElBQU0sZ0JBQWdCLEdBQUcsS0FBSSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQztnQkFDbEQsSUFBSSxDQUFDLENBQUMsZ0JBQWdCLEVBQUU7b0JBQ3BCLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEVBQUUsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQzdELE9BQU8sQ0FBUyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDekM7cUJBQU07b0JBQ0gsTUFBTSxDQUFDLGtDQUFrQyxDQUFDLENBQUM7aUJBQzlDO1lBQ0wsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUEsS0FBSyxJQUFJLE9BQUEsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFiLENBQWEsQ0FBQyxDQUFDO1FBQ3JDLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQU1ELGlDQUFZLEdBQVosVUFBYSxRQUFnQjtRQUE3QixpQkE2QkM7UUE1QkcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBQy9CLElBQU0sS0FBSyxHQUE4QjtnQkFDckMsSUFBSSxFQUFFLE9BQU87Z0JBQ2IsR0FBRyxFQUFFLFFBQVE7YUFDaEIsQ0FBQztZQUVGLE9BQU8sQ0FBQyxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztZQUVoRSxJQUFJLEtBQUksQ0FBQyxFQUFFLENBQUMsY0FBYyxLQUFLLFFBQVEsRUFBRTtnQkFDckMsTUFBTSxDQUFDLDBCQUEwQixDQUFDLENBQUM7YUFDdEM7WUFFRCxLQUFJLENBQUMsRUFBRSxDQUFDLG9CQUFvQixDQUFDLEtBQUssQ0FBQztpQkFDOUIsSUFBSSxDQUFDO2dCQUNGLE9BQU8sS0FBSSxDQUFDLEVBQUUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNsQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBQSxNQUFNO2dCQUNWLE9BQU8sQ0FBQyxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQztnQkFDcEMsT0FBTyxLQUFJLENBQUMsRUFBRSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQy9DLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDSixJQUFNLGdCQUFnQixHQUFHLEtBQUksQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLENBQUM7Z0JBQ2xELElBQUksQ0FBQyxDQUFDLGdCQUFnQixFQUFFO29CQUNwQixPQUFPLENBQUMsS0FBSyxDQUFDLHVCQUF1QixFQUFFLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUM3RCxPQUFPLENBQVMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUM7aUJBQ3pDO3FCQUFNO29CQUNILE1BQU0sQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO2lCQUM5QztZQUNMLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFBLEtBQUssSUFBSSxPQUFBLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBYixDQUFhLENBQUMsQ0FBQztRQUN6QyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFNRCxrQ0FBYSxHQUFiLFVBQWMsU0FBaUI7UUFBL0IsaUJBZ0JDO1FBZkcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFDLE9BQU8sRUFBRSxNQUFNO1lBRS9CLElBQU0sTUFBTSxHQUE4QjtnQkFDdEMsSUFBSSxFQUFFLFFBQVE7Z0JBQ2QsR0FBRyxFQUFFLFNBQVM7YUFDakIsQ0FBQztZQUVGLE9BQU8sQ0FBQyxLQUFLLENBQUMsaURBQWlELENBQUMsQ0FBQztZQUVqRSxJQUFJLEtBQUksQ0FBQyxFQUFFLENBQUMsY0FBYyxLQUFLLFFBQVEsRUFBRTtnQkFDckMsTUFBTSxDQUFDLDZCQUE2QixDQUFDLENBQUM7YUFDekM7WUFFRCxLQUFJLENBQUMsRUFBRSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFNLE9BQUEsT0FBTyxFQUFFLEVBQVQsQ0FBUyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUEsS0FBSyxJQUFJLE9BQUEsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFiLENBQWEsQ0FBQyxDQUFDO1FBQzdGLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUtELG9DQUFlLEdBQWYsVUFBZ0IsWUFBNkI7UUFBN0MsaUJBa0JDO1FBakJHLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBQyxPQUFPLEVBQUUsTUFBTTtZQUMvQixPQUFPLENBQUMsS0FBSyxDQUFDLCtCQUErQixFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQzdELEtBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDOUMsUUFBUSxLQUFJLENBQUMsRUFBRSxDQUFDLGNBQWMsRUFBRTtnQkFDNUIsS0FBSyxRQUFRO29CQUNULE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3JELE1BQU07Z0JBQ1YsS0FBSyxRQUFRO29CQUNULElBQUksQ0FBQyxDQUFDLEtBQUksQ0FBQyxFQUFFLENBQUMsaUJBQWlCLEVBQUU7d0JBQzdCLEtBQUksQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFNLE9BQUEsT0FBTyxFQUFFLEVBQVQsQ0FBUyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUEsS0FBSyxJQUFJLE9BQUEsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFiLENBQWEsQ0FBQyxDQUFDO3FCQUM3RjtvQkFDRCxNQUFNO2dCQUNWO29CQUNJLEtBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBQ3pDLE9BQU8sRUFBRSxDQUFDO2FBQ2pCO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sK0JBQVUsR0FBbEIsVUFBbUIsTUFBbUI7UUFDbEMsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFBLEtBQUs7WUFDNUIsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2IsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5QixDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFDTCxpQkFBQztBQUFELENBek5BLEFBeU5DLElBQUE7QUF6TlksZ0NBQVU7QUE0TnZCO0lBQXdDLHNDQUFVO0lBQzlDLDRCQUFZLGFBQXNDO1FBQWxELGlCQUdDO1FBRkcsYUFBYSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUM7UUFDaEMsUUFBQSxrQkFBTSxhQUFhLENBQUMsU0FBQzs7SUFDekIsQ0FBQztJQUNMLHlCQUFDO0FBQUQsQ0FMQSxBQUtDLENBTHVDLFVBQVUsR0FLakQ7QUFMWSxnREFBa0I7QUFPL0I7SUFBd0Msc0NBQVU7SUFDOUMsNEJBQVksYUFBc0M7UUFBbEQsaUJBR0M7UUFGRyxhQUFhLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQztRQUNoQyxRQUFBLGtCQUFNLGFBQWEsQ0FBQyxTQUFDOztJQUN6QixDQUFDO0lBQ0wseUJBQUM7QUFBRCxDQUxBLEFBS0MsQ0FMdUMsVUFBVSxHQUtqRDtBQUxZLGdEQUFrQjtBQU8vQjtJQUF3QyxzQ0FBVTtJQUM5Qyw0QkFBWSxhQUFzQztRQUFsRCxpQkFHQztRQUZHLGFBQWEsQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDO1FBQ2hDLFFBQUEsa0JBQU0sYUFBYSxDQUFDLFNBQUM7O0lBQ3pCLENBQUM7SUFDTCx5QkFBQztBQUFELENBTEEsQUFLQyxDQUx1QyxVQUFVLEdBS2pEO0FBTFksZ0RBQWtCOzs7OztBQ3pQL0IsbUNBQXNDO0FBRXRDO0lBa0NJLHFCQUFvQixNQUFjO1FBQWQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQWhDMUIsdUJBQWtCLEdBQUcsS0FBSyxDQUFDO1FBRTNCLGtCQUFhLEdBQUcsQ0FBQyxDQUFDO1FBQ2xCLFVBQUssR0FBUTtZQUNqQixPQUFPLEVBQUU7Z0JBQ0wsS0FBSyxFQUFFO29CQUNILGFBQWEsRUFBRSxDQUFDO29CQUNoQixlQUFlLEVBQUUsQ0FBQztvQkFDbEIsV0FBVyxFQUFFLENBQUM7aUJBQ2pCO2dCQUNELEtBQUssRUFBRTtvQkFDSCxhQUFhLEVBQUUsQ0FBQztvQkFDaEIsZUFBZSxFQUFFLENBQUM7b0JBQ2xCLFdBQVcsRUFBRSxDQUFDO29CQUNkLGFBQWEsRUFBRSxDQUFDO29CQUNoQixTQUFTLEVBQUUsQ0FBQztpQkFDZjthQUNKO1lBQ0QsUUFBUSxFQUFFO2dCQUNOLEtBQUssRUFBRTtvQkFDSCxTQUFTLEVBQUUsQ0FBQztvQkFDWixXQUFXLEVBQUUsQ0FBQztpQkFDakI7Z0JBQ0QsS0FBSyxFQUFFO29CQUNILFNBQVMsRUFBRSxDQUFDO29CQUNaLFdBQVcsRUFBRSxDQUFDO29CQUNkLGFBQWEsRUFBRSxDQUFDO29CQUNoQixTQUFTLEVBQUUsQ0FBQztpQkFDZjthQUNKO1NBQ0osQ0FBQztJQUVvQyxDQUFDO0lBRWhDLCtCQUFTLEdBQWhCO1FBQ0ksT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDbkMsQ0FBQztJQUVNLHFDQUFlLEdBQXRCO1FBQUEsaUJBd0JDO1FBdEJHLElBQU0sdUJBQXVCLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBRWpGLElBQUksdUJBQXVCLEVBQUU7WUFHekIsT0FBTyxDQUFDLElBQUksQ0FBQyxrQ0FBa0MsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsR0FBRyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUVsSSxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDO1lBRS9CLElBQU0saUJBQWUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7WUFDNUQsSUFBSSxDQUFDLGFBQWEsR0FBRyxpQkFBZSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7WUFFckQsT0FBTyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGlCQUFlLENBQUMsQ0FBQyxDQUFDO1lBRXRFLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxXQUFXLENBQUM7Z0JBQ3JDLEtBQUksQ0FBQyx1QkFBdUIsQ0FBQyxpQkFBZSxDQUFDLENBQUM7WUFDbEQsQ0FBQyxFQUFFLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLENBQUM7WUFFOUIsT0FBTztTQUNWO1FBRUQsT0FBTyxDQUFDLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFTSxxQ0FBZSxHQUF0QjtRQUNJLElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQ3pCLGFBQWEsQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQztZQUMxQyxPQUFPLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxHQUFHLGlCQUFpQixHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQzlJO0lBQ0wsQ0FBQztJQUVNLGlEQUEyQixHQUFsQztRQUFBLGlCQTZEQztRQTVERyxPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsT0FBTyxFQUFFLE1BQU07WUFDL0IsS0FBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsb0JBQW9CLEVBQUUsRUFDcEQsVUFBQyxLQUFLO2dCQUNGLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtvQkFDdkYsSUFBSSxnQkFBZ0IsU0FBQSxFQUFFLGlCQUFpQixTQUFBLEVBQUUsaUJBQWlCLFNBQUEsQ0FBQztvQkFDM0QsSUFBTSxlQUFlLEdBQUcsRUFBRSxDQUFDO29CQUMzQixJQUFNLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztvQkFDNUIsS0FBSyxJQUFNLEdBQUcsSUFBSSxLQUFLLEVBQUU7d0JBQ3JCLElBQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQzt3QkFDeEIsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLGdCQUFnQixFQUFFOzRCQUNoQyxlQUFlLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQzt5QkFDbkM7NkJBQU0sSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLGlCQUFpQixFQUFFOzRCQUN4QyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDO3lCQUNwQzs2QkFBTSxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssbUJBQW1CLElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEtBQUssTUFBTSxDQUFDLEVBQUU7NEJBQ3BGLGlCQUFpQixHQUFHLElBQUksQ0FBQzs0QkFDekIsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDOzRCQUN6QyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUM7eUJBQzlDO3FCQUNKO29CQUNELElBQUkscUJBQW1CLEdBQUcsZUFBZSxDQUFDLGdCQUFnQixDQUFDLENBQUM7b0JBQzVELElBQUksQ0FBQyxDQUFDLHFCQUFtQixFQUFFO3dCQUN2QixJQUFNLFFBQVEsR0FBRyxLQUFJLENBQUMsTUFBTSxDQUFDLHdCQUF3QixFQUFFLENBQUM7d0JBQ3hELElBQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsVUFBQyxDQUFrQjs0QkFDNUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUztnQ0FDakIsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMscUJBQW1CLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQztnQ0FDdkQsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMscUJBQW1CLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQztnQ0FDeEQsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMscUJBQW1CLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7d0JBQ2hFLENBQUMsQ0FBQyxDQUFDO3dCQUNILHFCQUFtQixDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxtRUFBbUUsQ0FBQztxQkFDakk7eUJBQU07d0JBQ0gscUJBQW1CLEdBQUcsc0VBQXNFLENBQUM7cUJBQ2hHO29CQUVELElBQUksc0JBQW9CLEdBQUcsZ0JBQWdCLENBQUMsaUJBQWlCLENBQUMsQ0FBQztvQkFDL0QsSUFBSSxDQUFDLENBQUMsc0JBQW9CLEVBQUU7d0JBQ3hCLElBQU0sUUFBUSxHQUFHLEtBQUksQ0FBQyxNQUFNLENBQUMseUJBQXlCLEVBQUUsQ0FBQzt3QkFDekQsSUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxVQUFDLENBQWtCOzRCQUM1QyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTO2dDQUNqQixDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxzQkFBb0IsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2dDQUN4RCxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxzQkFBb0IsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO2dDQUN6RCxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxzQkFBb0IsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzt3QkFDakUsQ0FBQyxDQUFDLENBQUM7d0JBQ0gsc0JBQW9CLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLHdFQUF3RSxDQUFDO3FCQUN2STt5QkFBTTt3QkFDSCxzQkFBb0IsR0FBRyx1RUFBdUUsQ0FBQztxQkFDbEc7b0JBRUQsT0FBTyxDQUFDO3dCQUNKLGlCQUFpQixtQkFBQTt3QkFDakIsY0FBYyxFQUFFLHFCQUFtQjt3QkFDbkMsZUFBZSxFQUFFLHNCQUFvQjtxQkFDeEMsQ0FBQyxDQUFDO2lCQUNOO3FCQUFNO29CQUNILE1BQU0sQ0FBQyx1REFBdUQsQ0FBQyxDQUFDO2lCQUNuRTtZQUNMLENBQUMsRUFDRCxVQUFDLEtBQUs7Z0JBQ0YsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xCLENBQUMsQ0FBQyxDQUFDO1FBQ1gsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sNkNBQXVCLEdBQS9CLFVBQWdDLGVBQWU7UUFBL0MsaUJBaU5DO1FBL01HLElBQU0sUUFBUSxHQUFHLFVBQUMsSUFBSTtZQUNsQixJQUFNLElBQUksR0FBbUIsSUFBSSxjQUFjLEVBQUUsQ0FBQztZQUNsRCxJQUFNLEdBQUcsR0FBVyxlQUFlLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQztZQUN4RCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFFN0IsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1lBRTFELElBQUksQ0FBQyxrQkFBa0IsR0FBRztnQkFDdEIsSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLEdBQUcsRUFBRTtvQkFDOUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQ0FBb0MsR0FBRyxHQUFHLEdBQUcsY0FBYyxHQUFHLEtBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxHQUFHLGlCQUFpQixHQUFHLEtBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO2lCQUM3SjtZQUNMLENBQUMsQ0FBQztZQUNGLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEIsQ0FBQyxDQUFDO1FBRUYsSUFBTSxDQUFDLEdBQUcsVUFBQyxLQUFLO1lBRVosSUFBSSxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTtnQkFDMUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFDLElBQUk7b0JBRWYsSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFDO29CQUVkLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLGFBQWEsQ0FBQzt3QkFDN0IsQ0FFSSxJQUFJLENBQUMsU0FBUyxLQUFLLElBQUk7NEJBQ3ZCLElBQUksQ0FBQyxRQUFRLEtBQUssS0FBSzs0QkFDdkIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDOzRCQUM3QixJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FDdEMsRUFBRTt3QkFFSCxJQUFNLFFBQVEsR0FBRyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsU0FBUyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO3dCQUN0RSxJQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQzt3QkFFL0IsSUFBTSxPQUFPLEdBQUc7NEJBQ1osYUFBYSxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsYUFBYSxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWE7NEJBQzNHLE1BQU0sRUFBRSxHQUFHOzRCQUNYLGVBQWUsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhOzRCQUNqSCxXQUFXLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLENBQUMsR0FBRyxLQUFJLENBQUMsYUFBYTt5QkFDeEcsQ0FBQzt3QkFDRixJQUFNLEtBQUssR0FBRzs0QkFDVixhQUFhLEVBQUUsT0FBTzs0QkFDdEIsTUFBTSxFQUFFLElBQUk7NEJBQ1osZUFBZSxFQUFFLFNBQVM7NEJBQzFCLFdBQVcsRUFBRSxTQUFTO3lCQUN6QixDQUFDO3dCQUNGLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxPQUFPLEVBQUU7NEJBQzVCLE9BQU8sQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhLENBQUM7NEJBQzlHLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhLENBQUM7NEJBQ2xHLEtBQUssQ0FBQyxlQUFlLENBQUMsR0FBRyxRQUFRLENBQUM7NEJBQ2xDLEtBQUssQ0FBQyxXQUFXLENBQUMsR0FBRyxTQUFTLENBQUM7NEJBRS9CLEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQzs0QkFDNUQsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO3lCQUN2RDt3QkFFRCxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7d0JBQ3RFLEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQzt3QkFDMUUsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO3dCQUVsRSxJQUFJLEdBQUc7NEJBQ0gsWUFBWSxFQUFFLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLEVBQUU7NEJBQ3BELE1BQU0sRUFBRSxlQUFlLENBQUMsSUFBSTs0QkFDNUIsV0FBVyxFQUFFLGVBQWUsQ0FBQyxTQUFTOzRCQUN0QyxRQUFRLEVBQUUsUUFBUTs0QkFDbEIsTUFBTSxFQUFFLFFBQVE7NEJBQ2hCLGFBQWEsRUFBRSxrQkFBa0I7NEJBQ2pDLE9BQU8sRUFBRSxLQUFLO3lCQUNqQixDQUFDO3dCQUNGLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxPQUFPLENBQUM7d0JBRXpCLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7cUJBRWxDO3lCQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLGNBQWMsQ0FBQzt3QkFDckMsQ0FFSSxJQUFJLENBQUMsUUFBUSxLQUFLLEtBQUs7NEJBQ3ZCLElBQUksQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUM3QyxFQUFFO3dCQUVILElBQU0sUUFBUSxHQUFHLGtCQUFrQixHQUFHLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7d0JBRXZFLElBQU0sT0FBTyxHQUFHOzRCQUNaLFNBQVMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhOzRCQUNoRyxXQUFXLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLENBQUMsR0FBRyxLQUFJLENBQUMsYUFBYTt5QkFDekcsQ0FBQzt3QkFDRixJQUFNLEtBQUssR0FBRzs0QkFDVixTQUFTLEVBQUUsT0FBTzs0QkFDbEIsV0FBVyxFQUFFLFNBQVM7eUJBQ3pCLENBQUM7d0JBQ0YsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLE9BQU8sRUFBRTs0QkFDNUIsT0FBTyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQzs0QkFDL0csS0FBSyxDQUFDLGVBQWUsQ0FBQyxHQUFHLFFBQVEsQ0FBQzs0QkFFbEMsS0FBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO3lCQUNoRTt3QkFFRCxLQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7d0JBQy9ELEtBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQzt3QkFFbkUsSUFBSSxHQUFHOzRCQUNILFlBQVksRUFBRSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsV0FBVyxFQUFFOzRCQUNwRCxNQUFNLEVBQUUsZUFBZSxDQUFDLElBQUk7NEJBQzVCLFdBQVcsRUFBRSxlQUFlLENBQUMsU0FBUzs0QkFDdEMsUUFBUSxFQUFFLFFBQVE7NEJBQ2xCLE1BQU0sRUFBRSxRQUFROzRCQUNoQixhQUFhLEVBQUUsa0JBQWtCOzRCQUNqQyxPQUFPLEVBQUUsS0FBSzt5QkFDakIsQ0FBQzt3QkFDRixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsT0FBTyxDQUFDO3dCQUV6QixRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO3FCQUNsQztnQkFDTCxDQUFDLENBQUMsQ0FBQzthQUNOO2lCQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDOUYsS0FBa0IsVUFBa0IsRUFBbEIsS0FBQSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFsQixjQUFrQixFQUFsQixJQUFrQixFQUFFO29CQUFqQyxJQUFNLEdBQUcsU0FBQTtvQkFDVixJQUFNLElBQUksR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQ3hCLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUU7d0JBRXRCLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQzt3QkFFZCxJQUFJLGVBQWUsSUFBSSxJQUFJLElBQUksQ0FDM0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxLQUFLLE9BQU8sSUFBSSxrQkFBa0IsSUFBSSxJQUFJLENBQUM7NEJBQzFELENBQUMsSUFBSSxDQUFDLFNBQVMsS0FBSyxPQUFPLElBQUksT0FBTyxJQUFJLElBQUksQ0FBQyxDQUNsRCxFQUFFOzRCQUVDLElBQU0sUUFBUSxHQUFHLGlCQUFpQixHQUFHLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7NEJBRXRFLElBQU0sT0FBTyxHQUFHO2dDQUNaLGFBQWEsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhO2dDQUMzRyxNQUFNLEVBQUUsSUFBSSxDQUFDLGtCQUFrQjtnQ0FDL0IsZUFBZSxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsZUFBZSxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWE7Z0NBQ2pILFdBQVcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhOzZCQUN4RyxDQUFDOzRCQUNGLElBQU0sS0FBSyxHQUFHO2dDQUNWLGFBQWEsRUFBRSxPQUFPO2dDQUN0QixNQUFNLEVBQUUsSUFBSTtnQ0FDWixlQUFlLEVBQUUsU0FBUztnQ0FDMUIsV0FBVyxFQUFFLFNBQVM7NkJBQ3pCLENBQUM7NEJBQ0YsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLE9BQU8sRUFBRTtnQ0FDNUIsT0FBTyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQztnQ0FDOUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWEsQ0FBQztnQ0FDdEcsS0FBSyxDQUFDLGVBQWUsQ0FBQyxHQUFHLFFBQVEsQ0FBQztnQ0FDbEMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFHLFNBQVMsQ0FBQztnQ0FFL0IsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO2dDQUM1RCxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7NkJBQzNEOzRCQUVELEtBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQzs0QkFDdEUsS0FBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDOzRCQUMxRSxLQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7NEJBRWxFLElBQUksR0FBRztnQ0FDSCxZQUFZLEVBQUUsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsRUFBRTtnQ0FDcEQsTUFBTSxFQUFFLGVBQWUsQ0FBQyxJQUFJO2dDQUM1QixXQUFXLEVBQUUsZUFBZSxDQUFDLFNBQVM7Z0NBQ3RDLFFBQVEsRUFBRSxRQUFRO2dDQUNsQixNQUFNLEVBQUUsUUFBUTtnQ0FDaEIsYUFBYSxFQUFFLGtCQUFrQjtnQ0FDakMsT0FBTyxFQUFFLEtBQUs7NkJBQ2pCLENBQUM7NEJBQ0YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLE9BQU8sQ0FBQzs0QkFFekIsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzt5QkFDbEM7NkJBQU0sSUFBSSxXQUFXLElBQUksSUFBSSxFQUFFOzRCQUU1QixJQUFNLFFBQVEsR0FBRyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsU0FBUyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDOzRCQUV2RSxJQUFNLE9BQU8sR0FBRztnQ0FDWixTQUFTLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxLQUFJLENBQUMsYUFBYTtnQ0FDaEcsV0FBVyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsV0FBVyxDQUFDLEdBQUcsS0FBSSxDQUFDLGFBQWE7NkJBQ3pHLENBQUM7NEJBQ0YsSUFBTSxLQUFLLEdBQUc7Z0NBQ1YsU0FBUyxFQUFFLE9BQU87Z0NBQ2xCLFdBQVcsRUFBRSxTQUFTOzZCQUN6QixDQUFDOzRCQUNGLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxPQUFPLEVBQUU7Z0NBQzVCLE9BQU8sQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEtBQUksQ0FBQyxhQUFhLENBQUM7Z0NBQy9HLEtBQUssQ0FBQyxlQUFlLENBQUMsR0FBRyxRQUFRLENBQUM7Z0NBRWxDLEtBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQzs2QkFDaEU7NEJBRUQsS0FBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDOzRCQUMvRCxLQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7NEJBRW5FLElBQUksR0FBRztnQ0FDSCxZQUFZLEVBQUUsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsRUFBRTtnQ0FDcEQsTUFBTSxFQUFFLGVBQWUsQ0FBQyxJQUFJO2dDQUM1QixXQUFXLEVBQUUsZUFBZSxDQUFDLFNBQVM7Z0NBQ3RDLFFBQVEsRUFBRSxRQUFRO2dDQUNsQixNQUFNLEVBQUUsUUFBUTtnQ0FDaEIsYUFBYSxFQUFFLGtCQUFrQjtnQ0FDakMsT0FBTyxFQUFFLEtBQUs7NkJBQ2pCLENBQUM7NEJBQ0YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLE9BQU8sQ0FBQzs0QkFFekIsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzt5QkFDbEM7cUJBQ0o7aUJBQ0o7YUFDSjtRQUNMLENBQUMsQ0FBQztRQUVGLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLG9CQUFvQixFQUFFLEVBQUUsQ0FBQyxFQUFFLFVBQUMsS0FBSyxJQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRyxDQUFDO0lBRU8sdUNBQWlCLEdBQXpCLFVBQTBCLFFBQVE7UUFDOUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN0QixJQUFNLGNBQWMsR0FBRyxFQUFFLENBQUM7UUFFMUIsSUFBSSxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTtZQUMxQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFBLEdBQUc7Z0JBQzdCLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDL0IsQ0FBQyxDQUFDLENBQUM7WUFDSCxPQUFPLFFBQVEsQ0FBQztTQUNuQjtRQUVELFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBQSxNQUFNO1lBQzVCLElBQU0sYUFBYSxHQUFHO2dCQUNsQixFQUFFLEVBQUUsTUFBTSxDQUFDLEVBQUU7Z0JBQ2IsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTO2dCQUMzQixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7YUFDcEIsQ0FBQztZQUNGLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBQyxJQUFJO2dCQUN4QixhQUFhLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1QyxDQUFDLENBQUMsQ0FBQztZQUNILGNBQWMsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLEdBQUcsYUFBYSxDQUFDO1FBQ3JELENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxjQUFjLENBQUM7SUFDMUIsQ0FBQztJQUVPLHNDQUFnQixHQUF4QixVQUF5QixFQUFFLEVBQUUsU0FBUyxFQUFFLFNBQVM7UUFBakQsaUJBY0M7UUFiRyxJQUFJLFFBQVEsQ0FBQyxJQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO1lBRTFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBQSxRQUFRO2dCQUNsQyxJQUFNLE1BQU0sR0FBRyxLQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ2hELFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN0QixDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7U0FDdkI7YUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFFOUYsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQUMsUUFBUTtnQkFDeEIsSUFBTSxNQUFNLEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztTQUN2QjtJQUNMLENBQUM7SUFFTCxrQkFBQztBQUFELENBcllBLEFBcVlDLElBQUE7QUFyWVksa0NBQVciLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLyohXG4gKiBQbGF0Zm9ybS5qcyA8aHR0cHM6Ly9tdGhzLmJlL3BsYXRmb3JtPlxuICogQ29weXJpZ2h0IDIwMTQtMjAxOCBCZW5qYW1pbiBUYW4gPGh0dHBzOi8vYm5qbW50NG4ubm93LnNoLz5cbiAqIENvcHlyaWdodCAyMDExLTIwMTMgSm9obi1EYXZpZCBEYWx0b24gPGh0dHA6Ly9hbGx5b3VjYW5sZWV0LmNvbS8+XG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbXRocy5iZS9taXQ+XG4gKi9cbjsoZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBCYWNrdXAgcG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIG9sZFJvb3QgPSByb290O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcyBvciBCcm93c2VyaWZpZWQgY29kZSBhbmQgdXNlIGl0IGFzIGByb290YC4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSBmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlICYmIHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSkge1xuICAgIHJvb3QgPSBmcmVlR2xvYmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgdGhlIG1heGltdW0gbGVuZ3RoIG9mIGFuIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgKiBTZWUgdGhlIFtFUzYgc3BlY10oaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGgpXG4gICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAqL1xuICB2YXIgbWF4U2FmZUludGVnZXIgPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuXG4gIC8qKiBSZWd1bGFyIGV4cHJlc3Npb24gdG8gZGV0ZWN0IE9wZXJhLiAqL1xuICB2YXIgcmVPcGVyYSA9IC9cXGJPcGVyYS87XG5cbiAgLyoqIFBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciB0aGlzQmluZGluZyA9IHRoaXM7XG5cbiAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAvKiogVXNlZCB0byBjaGVjayBmb3Igb3duIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LiAqL1xuICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiB2YWx1ZXMuICovXG4gIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDYXBpdGFsaXplcyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgIHN0cmluZyA9IFN0cmluZyhzdHJpbmcpO1xuICAgIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG4gIH1cblxuICAvKipcbiAgICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGNsZWFuIHVwIHRoZSBPUyBuYW1lLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3MgVGhlIE9TIG5hbWUgdG8gY2xlYW4gdXAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVybl0gQSBgUmVnRXhwYCBwYXR0ZXJuIG1hdGNoaW5nIHRoZSBPUyBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhYmVsXSBBIGxhYmVsIGZvciB0aGUgT1MuXG4gICAqL1xuICBmdW5jdGlvbiBjbGVhbnVwT1Mob3MsIHBhdHRlcm4sIGxhYmVsKSB7XG4gICAgLy8gUGxhdGZvcm0gdG9rZW5zIGFyZSBkZWZpbmVkIGF0OlxuICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIC8vIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDgxMTIyMDUzOTUwL2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIHZhciBkYXRhID0ge1xuICAgICAgJzEwLjAnOiAnMTAnLFxuICAgICAgJzYuNCc6ICAnMTAgVGVjaG5pY2FsIFByZXZpZXcnLFxuICAgICAgJzYuMyc6ICAnOC4xJyxcbiAgICAgICc2LjInOiAgJzgnLFxuICAgICAgJzYuMSc6ICAnU2VydmVyIDIwMDggUjIgLyA3JyxcbiAgICAgICc2LjAnOiAgJ1NlcnZlciAyMDA4IC8gVmlzdGEnLFxuICAgICAgJzUuMic6ICAnU2VydmVyIDIwMDMgLyBYUCA2NC1iaXQnLFxuICAgICAgJzUuMSc6ICAnWFAnLFxuICAgICAgJzUuMDEnOiAnMjAwMCBTUDEnLFxuICAgICAgJzUuMCc6ICAnMjAwMCcsXG4gICAgICAnNC4wJzogICdOVCcsXG4gICAgICAnNC45MCc6ICdNRSdcbiAgICB9O1xuICAgIC8vIERldGVjdCBXaW5kb3dzIHZlcnNpb24gZnJvbSBwbGF0Zm9ybSB0b2tlbnMuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwgJiYgL15XaW4vaS50ZXN0KG9zKSAmJiAhL15XaW5kb3dzIFBob25lIC9pLnRlc3Qob3MpICYmXG4gICAgICAgIChkYXRhID0gZGF0YVsvW1xcZC5dKyQvLmV4ZWMob3MpXSkpIHtcbiAgICAgIG9zID0gJ1dpbmRvd3MgJyArIGRhdGE7XG4gICAgfVxuICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgIG9zID0gU3RyaW5nKG9zKTtcblxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGxhYmVsKTtcbiAgICB9XG5cbiAgICBvcyA9IGZvcm1hdChcbiAgICAgIG9zLnJlcGxhY2UoLyBjZSQvaSwgJyBDRScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJocHcvaSwgJ3dlYicpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWNpbnRvc2hcXGIvLCAnTWFjIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL19Qb3dlclBDXFxiL2ksICcgT1MnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKE9TIFgpIFteIFxcZF0rL2ksICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWMgKE9TIFgpXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyhcXGQpLywgJyAkMScpXG4gICAgICAgIC5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgLnJlcGxhY2UoLyg/OiBCZVBDfFsgLl0qZmNbIFxcZC5dKykkL2ksICcnKVxuICAgICAgICAucmVwbGFjZSgvXFxieDg2XFwuNjRcXGIvZ2ksICd4ODZfNjQnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKFdpbmRvd3MgUGhvbmUpIE9TXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihDaHJvbWUgT1MgXFx3KykgW1xcZC5dK1xcYi8sICckMScpXG4gICAgICAgIC5zcGxpdCgnIG9uICcpWzBdXG4gICAgKTtcblxuICAgIHJldHVybiBvcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpdGVyYXRpb24gdXRpbGl0eSBmb3IgYXJyYXlzIGFuZCBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBlYWNoKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gb2JqZWN0ID8gb2JqZWN0Lmxlbmd0aCA6IDA7XG5cbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPiAtMSAmJiBsZW5ndGggPD0gbWF4U2FmZUludGVnZXIpIHtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtpbmRleF0sIGluZGV4LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3JPd24ob2JqZWN0LCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaW0gYW5kIGNvbmRpdGlvbmFsbHkgY2FwaXRhbGl6ZSBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGZvcm1hdChzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSB0cmltKHN0cmluZyk7XG4gICAgcmV0dXJuIC9eKD86d2ViT1N8aSg/Ok9TfFApKS8udGVzdChzdHJpbmcpXG4gICAgICA/IHN0cmluZ1xuICAgICAgOiBjYXBpdGFsaXplKHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZXMgb3ZlciBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgZXhlY3V0aW5nIHRoZSBgY2FsbGJhY2tgIGZvciBlYWNoLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gZXhlY3V0ZWQgcGVyIG93biBwcm9wZXJ0eS5cbiAgICovXG4gIGZ1bmN0aW9uIGZvck93bihvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtrZXldLCBrZXksIG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIGEgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYFtbQ2xhc3NdXWAuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRDbGFzc09mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGxcbiAgICAgID8gY2FwaXRhbGl6ZSh2YWx1ZSlcbiAgICAgIDogdG9TdHJpbmcuY2FsbCh2YWx1ZSkuc2xpY2UoOCwgLTEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvc3Qgb2JqZWN0cyBjYW4gcmV0dXJuIHR5cGUgdmFsdWVzIHRoYXQgYXJlIGRpZmZlcmVudCBmcm9tIHRoZWlyIGFjdHVhbFxuICAgKiBkYXRhIHR5cGUuIFRoZSBvYmplY3RzIHdlIGFyZSBjb25jZXJuZWQgd2l0aCB1c3VhbGx5IHJldHVybiBub24tcHJpbWl0aXZlXG4gICAqIHR5cGVzIG9mIFwib2JqZWN0XCIsIFwiZnVuY3Rpb25cIiwgb3IgXCJ1bmtub3duXCIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBvd25lciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgYSBub24tcHJpbWl0aXZlLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RUeXBlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICB2YXIgdHlwZSA9IG9iamVjdCAhPSBudWxsID8gdHlwZW9mIG9iamVjdFtwcm9wZXJ0eV0gOiAnbnVtYmVyJztcbiAgICByZXR1cm4gIS9eKD86Ym9vbGVhbnxudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZCkkLy50ZXN0KHR5cGUpICYmXG4gICAgICAodHlwZSA9PSAnb2JqZWN0JyA/ICEhb2JqZWN0W3Byb3BlcnR5XSA6IHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmVzIGEgc3RyaW5nIGZvciB1c2UgaW4gYSBgUmVnRXhwYCBieSBtYWtpbmcgaHlwaGVucyBhbmQgc3BhY2VzIG9wdGlvbmFsLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcXVhbGlmeS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBxdWFsaWZ5KHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC8oWyAtXSkoPyEkKS9nLCAnJDE/Jyk7XG4gIH1cblxuICAvKipcbiAgICogQSBiYXJlLWJvbmVzIGBBcnJheSNyZWR1Y2VgIGxpa2UgdXRpbGl0eSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Kn0gVGhlIGFjY3VtdWxhdGVkIHJlc3VsdC5cbiAgICovXG4gIGZ1bmN0aW9uIHJlZHVjZShhcnJheSwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWNjdW11bGF0b3IgPSBudWxsO1xuICAgIGVhY2goYXJyYXksIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBhcnJheSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvXiArfCArJC9nLCAnJyk7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbGF0Zm9ybSBvYmplY3QuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgKiBAcGFyYW0ge09iamVjdHxzdHJpbmd9IFt1YT1uYXZpZ2F0b3IudXNlckFnZW50XSBUaGUgdXNlciBhZ2VudCBzdHJpbmcgb3JcbiAgICogIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBIHBsYXRmb3JtIG9iamVjdC5cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlKHVhKSB7XG5cbiAgICAvKiogVGhlIGVudmlyb25tZW50IGNvbnRleHQgb2JqZWN0LiAqL1xuICAgIHZhciBjb250ZXh0ID0gcm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBhIGN1c3RvbSBjb250ZXh0IGlzIHByb3ZpZGVkLiAqL1xuICAgIHZhciBpc0N1c3RvbUNvbnRleHQgPSB1YSAmJiB0eXBlb2YgdWEgPT0gJ29iamVjdCcgJiYgZ2V0Q2xhc3NPZih1YSkgIT0gJ1N0cmluZyc7XG5cbiAgICAvLyBKdWdnbGUgYXJndW1lbnRzLlxuICAgIGlmIChpc0N1c3RvbUNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB1YTtcbiAgICAgIHVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKiogQnJvd3NlciBuYXZpZ2F0b3Igb2JqZWN0LiAqL1xuICAgIHZhciBuYXYgPSBjb250ZXh0Lm5hdmlnYXRvciB8fCB7fTtcblxuICAgIC8qKiBCcm93c2VyIHVzZXIgYWdlbnQgc3RyaW5nLiAqL1xuICAgIHZhciB1c2VyQWdlbnQgPSBuYXYudXNlckFnZW50IHx8ICcnO1xuXG4gICAgdWEgfHwgKHVhID0gdXNlckFnZW50KTtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBgdGhpc0JpbmRpbmdgIGlzIHRoZSBbTW9kdWxlU2NvcGVdLiAqL1xuICAgIHZhciBpc01vZHVsZVNjb3BlID0gaXNDdXN0b21Db250ZXh0IHx8IHRoaXNCaW5kaW5nID09IG9sZFJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYnJvd3NlciBpcyBsaWtlIENocm9tZS4gKi9cbiAgICB2YXIgbGlrZUNocm9tZSA9IGlzQ3VzdG9tQ29udGV4dFxuICAgICAgPyAhIW5hdi5saWtlQ2hyb21lXG4gICAgICA6IC9cXGJDaHJvbWVcXGIvLnRlc3QodWEpICYmICEvaW50ZXJuYWx8XFxuL2kudGVzdCh0b1N0cmluZy50b1N0cmluZygpKTtcblxuICAgIC8qKiBJbnRlcm5hbCBgW1tDbGFzc11dYCB2YWx1ZSBzaG9ydGN1dHMuICovXG4gICAgdmFyIG9iamVjdENsYXNzID0gJ09iamVjdCcsXG4gICAgICAgIGFpclJ1bnRpbWVDbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1NjcmlwdEJyaWRnaW5nUHJveHlPYmplY3QnLFxuICAgICAgICBlbnZpcm9DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ0Vudmlyb25tZW50JyxcbiAgICAgICAgamF2YUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBjb250ZXh0LmphdmEpID8gJ0phdmFQYWNrYWdlJyA6IGdldENsYXNzT2YoY29udGV4dC5qYXZhKSxcbiAgICAgICAgcGhhbnRvbUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnUnVudGltZU9iamVjdCc7XG5cbiAgICAvKiogRGV0ZWN0IEphdmEgZW52aXJvbm1lbnRzLiAqL1xuICAgIHZhciBqYXZhID0gL1xcYkphdmEvLnRlc3QoamF2YUNsYXNzKSAmJiBjb250ZXh0LmphdmE7XG5cbiAgICAvKiogRGV0ZWN0IFJoaW5vLiAqL1xuICAgIHZhciByaGlubyA9IGphdmEgJiYgZ2V0Q2xhc3NPZihjb250ZXh0LmVudmlyb25tZW50KSA9PSBlbnZpcm9DbGFzcztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYWxwaGEuICovXG4gICAgdmFyIGFscGhhID0gamF2YSA/ICdhJyA6ICdcXHUwM2IxJztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYmV0YS4gKi9cbiAgICB2YXIgYmV0YSA9IGphdmEgPyAnYicgOiAnXFx1MDNiMic7XG5cbiAgICAvKiogQnJvd3NlciBkb2N1bWVudCBvYmplY3QuICovXG4gICAgdmFyIGRvYyA9IGNvbnRleHQuZG9jdW1lbnQgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgT3BlcmEgYnJvd3NlciAoUHJlc3RvLWJhc2VkKS5cbiAgICAgKiBodHRwOi8vd3d3Lmhvd3RvY3JlYXRlLmNvLnVrL29wZXJhU3R1ZmYvb3BlcmFPYmplY3QuaHRtbFxuICAgICAqIGh0dHA6Ly9kZXYub3BlcmEuY29tL2FydGljbGVzL3ZpZXcvb3BlcmEtbWluaS13ZWItY29udGVudC1hdXRob3JpbmctZ3VpZGVsaW5lcy8jb3BlcmFtaW5pXG4gICAgICovXG4gICAgdmFyIG9wZXJhID0gY29udGV4dC5vcGVyYW1pbmkgfHwgY29udGV4dC5vcGVyYTtcblxuICAgIC8qKiBPcGVyYSBgW1tDbGFzc11dYC4gKi9cbiAgICB2YXIgb3BlcmFDbGFzcyA9IHJlT3BlcmEudGVzdChvcGVyYUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBvcGVyYSkgPyBvcGVyYVsnW1tDbGFzc11dJ10gOiBnZXRDbGFzc09mKG9wZXJhKSlcbiAgICAgID8gb3BlcmFDbGFzc1xuICAgICAgOiAob3BlcmEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKiBUZW1wb3JhcnkgdmFyaWFibGUgdXNlZCBvdmVyIHRoZSBzY3JpcHQncyBsaWZldGltZS4gKi9cbiAgICB2YXIgZGF0YTtcblxuICAgIC8qKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZS4gKi9cbiAgICB2YXIgYXJjaCA9IHVhO1xuXG4gICAgLyoqIFBsYXRmb3JtIGRlc2NyaXB0aW9uIGFycmF5LiAqL1xuICAgIHZhciBkZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgLyoqIFBsYXRmb3JtIGFscGhhL2JldGEgaW5kaWNhdG9yLiAqL1xuICAgIHZhciBwcmVyZWxlYXNlID0gbnVsbDtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgdGhhdCBlbnZpcm9ubWVudCBmZWF0dXJlcyBzaG91bGQgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwbGF0Zm9ybS4gKi9cbiAgICB2YXIgdXNlRmVhdHVyZXMgPSB1YSA9PSB1c2VyQWdlbnQ7XG5cbiAgICAvKiogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi4gKi9cbiAgICB2YXIgdmVyc2lvbiA9IHVzZUZlYXR1cmVzICYmIG9wZXJhICYmIHR5cGVvZiBvcGVyYS52ZXJzaW9uID09ICdmdW5jdGlvbicgJiYgb3BlcmEudmVyc2lvbigpO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgT1MgZW5kcyB3aXRoIFwiLyBWZXJzaW9uXCIgKi9cbiAgICB2YXIgaXNTcGVjaWFsQ2FzZWRPUztcblxuICAgIC8qIERldGVjdGFibGUgbGF5b3V0IGVuZ2luZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIGxheW91dCA9IGdldExheW91dChbXG4gICAgICB7ICdsYWJlbCc6ICdFZGdlSFRNTCcsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnVHJpZGVudCcsXG4gICAgICB7ICdsYWJlbCc6ICdXZWJLaXQnLCAncGF0dGVybic6ICdBcHBsZVdlYktpdCcgfSxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdQcmVzdG8nLFxuICAgICAgJ05ldEZyb250JyxcbiAgICAgICdUYXNtYW4nLFxuICAgICAgJ0tIVE1MJyxcbiAgICAgICdHZWNrbydcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgYnJvd3NlciBuYW1lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbmFtZSA9IGdldE5hbWUoW1xuICAgICAgJ0Fkb2JlIEFJUicsXG4gICAgICAnQXJvcmEnLFxuICAgICAgJ0F2YW50IEJyb3dzZXInLFxuICAgICAgJ0JyZWFjaCcsXG4gICAgICAnQ2FtaW5vJyxcbiAgICAgICdFbGVjdHJvbicsXG4gICAgICAnRXBpcGhhbnknLFxuICAgICAgJ0Zlbm5lYycsXG4gICAgICAnRmxvY2snLFxuICAgICAgJ0dhbGVvbicsXG4gICAgICAnR3JlZW5Ccm93c2VyJyxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdJY2V3ZWFzZWwnLFxuICAgICAgJ0stTWVsZW9uJyxcbiAgICAgICdLb25xdWVyb3InLFxuICAgICAgJ0x1bmFzY2FwZScsXG4gICAgICAnTWF4dGhvbicsXG4gICAgICB7ICdsYWJlbCc6ICdNaWNyb3NvZnQgRWRnZScsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnTWlkb3JpJyxcbiAgICAgICdOb29rIEJyb3dzZXInLFxuICAgICAgJ1BhbGVNb29uJyxcbiAgICAgICdQaGFudG9tSlMnLFxuICAgICAgJ1JhdmVuJyxcbiAgICAgICdSZWtvbnEnLFxuICAgICAgJ1JvY2tNZWx0JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NhbXN1bmcgSW50ZXJuZXQnLCAncGF0dGVybic6ICdTYW1zdW5nQnJvd3NlcicgfSxcbiAgICAgICdTZWFNb25rZXknLFxuICAgICAgeyAnbGFiZWwnOiAnU2lsaycsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdTbGVpcG5pcicsXG4gICAgICAnU2xpbUJyb3dzZXInLFxuICAgICAgeyAnbGFiZWwnOiAnU1JXYXJlIElyb24nLCAncGF0dGVybic6ICdJcm9uJyB9LFxuICAgICAgJ1N1bnJpc2UnLFxuICAgICAgJ1N3aWZ0Zm94JyxcbiAgICAgICdXYXRlcmZveCcsXG4gICAgICAnV2ViUG9zaXRpdmUnLFxuICAgICAgJ09wZXJhIE1pbmknLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEgTWluaScsICdwYXR0ZXJuJzogJ09QaU9TJyB9LFxuICAgICAgJ09wZXJhJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhJywgJ3BhdHRlcm4nOiAnT1BSJyB9LFxuICAgICAgJ0Nocm9tZScsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgTW9iaWxlJywgJ3BhdHRlcm4nOiAnKD86Q3JpT1N8Q3JNbyknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94JywgJ3BhdHRlcm4nOiAnKD86RmlyZWZveHxNaW5lZmllbGQpJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCBmb3IgaU9TJywgJ3BhdHRlcm4nOiAnRnhpT1MnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ0lFTW9iaWxlJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdNU0lFJyB9LFxuICAgICAgJ1NhZmFyaSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgcHJvZHVjdHMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0JsYWNrQmVycnknLCAncGF0dGVybic6ICdCQjEwJyB9LFxuICAgICAgJ0JsYWNrQmVycnknLFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMnLCAncGF0dGVybic6ICdHVC1JOTAwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMicsICdwYXR0ZXJuJzogJ0dULUk5MTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMzJywgJ3BhdHRlcm4nOiAnR1QtSTkzMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzQnLCAncGF0dGVybic6ICdHVC1JOTUwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNScsICdwYXR0ZXJuJzogJ1NNLUc5MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYnLCAncGF0dGVybic6ICdTTS1HOTIwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTI1JyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3JywgJ3BhdHRlcm4nOiAnU00tRzkzMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNyBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkzNScgfSxcbiAgICAgICdHb29nbGUgVFYnLFxuICAgICAgJ0x1bWlhJyxcbiAgICAgICdpUGFkJyxcbiAgICAgICdpUG9kJyxcbiAgICAgICdpUGhvbmUnLFxuICAgICAgJ0tpbmRsZScsXG4gICAgICB7ICdsYWJlbCc6ICdLaW5kbGUgRmlyZScsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdOZXh1cycsXG4gICAgICAnTm9vaycsXG4gICAgICAnUGxheUJvb2snLFxuICAgICAgJ1BsYXlTdGF0aW9uIFZpdGEnLFxuICAgICAgJ1BsYXlTdGF0aW9uJyxcbiAgICAgICdUb3VjaFBhZCcsXG4gICAgICAnVHJhbnNmb3JtZXInLFxuICAgICAgeyAnbGFiZWwnOiAnV2lpIFUnLCAncGF0dGVybic6ICdXaWlVJyB9LFxuICAgICAgJ1dpaScsXG4gICAgICAnWGJveCBPbmUnLFxuICAgICAgeyAnbGFiZWwnOiAnWGJveCAzNjAnLCAncGF0dGVybic6ICdYYm94JyB9LFxuICAgICAgJ1hvb20nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG1hbnVmYWN0dXJlcnMuICovXG4gICAgdmFyIG1hbnVmYWN0dXJlciA9IGdldE1hbnVmYWN0dXJlcih7XG4gICAgICAnQXBwbGUnOiB7ICdpUGFkJzogMSwgJ2lQaG9uZSc6IDEsICdpUG9kJzogMSB9LFxuICAgICAgJ0FyY2hvcyc6IHt9LFxuICAgICAgJ0FtYXpvbic6IHsgJ0tpbmRsZSc6IDEsICdLaW5kbGUgRmlyZSc6IDEgfSxcbiAgICAgICdBc3VzJzogeyAnVHJhbnNmb3JtZXInOiAxIH0sXG4gICAgICAnQmFybmVzICYgTm9ibGUnOiB7ICdOb29rJzogMSB9LFxuICAgICAgJ0JsYWNrQmVycnknOiB7ICdQbGF5Qm9vayc6IDEgfSxcbiAgICAgICdHb29nbGUnOiB7ICdHb29nbGUgVFYnOiAxLCAnTmV4dXMnOiAxIH0sXG4gICAgICAnSFAnOiB7ICdUb3VjaFBhZCc6IDEgfSxcbiAgICAgICdIVEMnOiB7fSxcbiAgICAgICdMRyc6IHt9LFxuICAgICAgJ01pY3Jvc29mdCc6IHsgJ1hib3gnOiAxLCAnWGJveCBPbmUnOiAxIH0sXG4gICAgICAnTW90b3JvbGEnOiB7ICdYb29tJzogMSB9LFxuICAgICAgJ05pbnRlbmRvJzogeyAnV2lpIFUnOiAxLCAgJ1dpaSc6IDEgfSxcbiAgICAgICdOb2tpYSc6IHsgJ0x1bWlhJzogMSB9LFxuICAgICAgJ1NhbXN1bmcnOiB7ICdHYWxheHkgUyc6IDEsICdHYWxheHkgUzInOiAxLCAnR2FsYXh5IFMzJzogMSwgJ0dhbGF4eSBTNCc6IDEgfSxcbiAgICAgICdTb255JzogeyAnUGxheVN0YXRpb24nOiAxLCAnUGxheVN0YXRpb24gVml0YSc6IDEgfVxuICAgIH0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBvcGVyYXRpbmcgc3lzdGVtcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgb3MgPSBnZXRPUyhbXG4gICAgICAnV2luZG93cyBQaG9uZScsXG4gICAgICAnQW5kcm9pZCcsXG4gICAgICAnQ2VudE9TJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBPUycsICdwYXR0ZXJuJzogJ0NyT1MnIH0sXG4gICAgICAnRGViaWFuJyxcbiAgICAgICdGZWRvcmEnLFxuICAgICAgJ0ZyZWVCU0QnLFxuICAgICAgJ0dlbnRvbycsXG4gICAgICAnSGFpa3UnLFxuICAgICAgJ0t1YnVudHUnLFxuICAgICAgJ0xpbnV4IE1pbnQnLFxuICAgICAgJ09wZW5CU0QnLFxuICAgICAgJ1JlZCBIYXQnLFxuICAgICAgJ1N1U0UnLFxuICAgICAgJ1VidW50dScsXG4gICAgICAnWHVidW50dScsXG4gICAgICAnQ3lnd2luJyxcbiAgICAgICdTeW1iaWFuIE9TJyxcbiAgICAgICdocHdPUycsXG4gICAgICAnd2ViT1MgJyxcbiAgICAgICd3ZWJPUycsXG4gICAgICAnVGFibGV0IE9TJyxcbiAgICAgICdUaXplbicsXG4gICAgICAnTGludXgnLFxuICAgICAgJ01hYyBPUyBYJyxcbiAgICAgICdNYWNpbnRvc2gnLFxuICAgICAgJ01hYycsXG4gICAgICAnV2luZG93cyA5ODsnLFxuICAgICAgJ1dpbmRvd3MgJ1xuICAgIF0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGxheW91dCBlbmdpbmUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbGF5b3V0IGVuZ2luZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMYXlvdXQoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIG1hbnVmYWN0dXJlciBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gb2JqZWN0IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbWFudWZhY3R1cmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlcihndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgICAvLyBMb29rdXAgdGhlIG1hbnVmYWN0dXJlciBieSBwcm9kdWN0IG9yIHNjYW4gdGhlIFVBIGZvciB0aGUgbWFudWZhY3R1cmVyLlxuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChcbiAgICAgICAgICB2YWx1ZVtwcm9kdWN0XSB8fFxuICAgICAgICAgIHZhbHVlWy9eW2Etel0rKD86ICtbYS16XStcXGIpKi9pLmV4ZWMocHJvZHVjdCldIHx8XG4gICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBxdWFsaWZ5KGtleSkgKyAnKD86XFxcXGJ8XFxcXHcqXFxcXGQpJywgJ2knKS5leGVjKHVhKVxuICAgICAgICApICYmIGtleTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBicm93c2VyIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgYnJvd3NlciBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hbWUoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIE9TIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgT1MgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRPUyhndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/Oi9bXFxcXGQuXSt8WyBcXFxcdy5dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xlYW51cE9TKHJlc3VsdCwgcGF0dGVybiwgZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgcHJvZHVjdCBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHByb2R1Y3QgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRQcm9kdWN0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcZCtbLlxcXFx3X10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcdystW1xcXFx3XSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzo7ICooPzpbYS16XStbXy1dKT9bYS16XStcXFxcZCt8W14gKCk7LV0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAvLyBTcGxpdCBieSBmb3J3YXJkIHNsYXNoIGFuZCBhcHBlbmQgcHJvZHVjdCB2ZXJzaW9uIGlmIG5lZWRlZC5cbiAgICAgICAgICBpZiAoKHJlc3VsdCA9IFN0cmluZygoZ3Vlc3MubGFiZWwgJiYgIVJlZ0V4cChwYXR0ZXJuLCAnaScpLnRlc3QoZ3Vlc3MubGFiZWwpKSA/IGd1ZXNzLmxhYmVsIDogcmVzdWx0KS5zcGxpdCgnLycpKVsxXSAmJiAhL1tcXGQuXSsvLnRlc3QocmVzdWx0WzBdKSkge1xuICAgICAgICAgICAgcmVzdWx0WzBdICs9ICcgJyArIHJlc3VsdFsxXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgICAgICAgZ3Vlc3MgPSBndWVzcy5sYWJlbCB8fCBndWVzcztcbiAgICAgICAgICByZXN1bHQgPSBmb3JtYXQocmVzdWx0WzBdXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgZ3Vlc3MpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJzsgKig/OicgKyBndWVzcyArICdbXy1dKT8nLCAnaScpLCAnICcpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJygnICsgZ3Vlc3MgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCAnJDEgJDInKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2ZXJzaW9uIHVzaW5nIGFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXR0ZXJucyBBbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCB2ZXJzaW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZlcnNpb24ocGF0dGVybnMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UocGF0dGVybnMsIGZ1bmN0aW9uKHJlc3VsdCwgcGF0dGVybikge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChSZWdFeHAocGF0dGVybiArXG4gICAgICAgICAgJyg/Oi1bXFxcXGQuXSsvfCg/OiBmb3IgW1xcXFx3LV0rKT9bIC8tXSkoW1xcXFxkLl0rW14gKCk7L18tXSopJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fCBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIHdoZW4gdGhlIHBsYXRmb3JtIG9iamVjdCBpcyBjb2VyY2VkIHRvIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG5hbWUgdG9TdHJpbmdcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgaWYgYXZhaWxhYmxlLCBlbHNlIGFuIGVtcHR5IHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZ1BsYXRmb3JtKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRpb24gfHwgJyc7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQ29udmVydCBsYXlvdXQgdG8gYW4gYXJyYXkgc28gd2UgY2FuIGFkZCBleHRyYSBkZXRhaWxzLlxuICAgIGxheW91dCAmJiAobGF5b3V0ID0gW2xheW91dF0pO1xuXG4gICAgLy8gRGV0ZWN0IHByb2R1Y3QgbmFtZXMgdGhhdCBjb250YWluIHRoZWlyIG1hbnVmYWN0dXJlcidzIG5hbWUuXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiAhcHJvZHVjdCkge1xuICAgICAgcHJvZHVjdCA9IGdldFByb2R1Y3QoW21hbnVmYWN0dXJlcl0pO1xuICAgIH1cbiAgICAvLyBDbGVhbiB1cCBHb29nbGUgVFYuXG4gICAgaWYgKChkYXRhID0gL1xcYkdvb2dsZSBUVlxcYi8uZXhlYyhwcm9kdWN0KSkpIHtcbiAgICAgIHByb2R1Y3QgPSBkYXRhWzBdO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc2ltdWxhdG9ycy5cbiAgICBpZiAoL1xcYlNpbXVsYXRvclxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBwcm9kdWN0ID0gKHByb2R1Y3QgPyBwcm9kdWN0ICsgJyAnIDogJycpICsgJ1NpbXVsYXRvcic7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBNaW5pIDgrIHJ1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUgb24gaU9TLlxuICAgIGlmIChuYW1lID09ICdPcGVyYSBNaW5pJyAmJiAvXFxiT1BpT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBNb2JpbGUgMTEuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAvXFxibGlrZSBpUGhvbmUgT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkYXRhID0gcGFyc2UodWEucmVwbGFjZSgvbGlrZSBpUGhvbmUgT1MvLCAnJykpO1xuICAgICAgbWFudWZhY3R1cmVyID0gZGF0YS5tYW51ZmFjdHVyZXI7XG4gICAgICBwcm9kdWN0ID0gZGF0YS5wcm9kdWN0O1xuICAgIH1cbiAgICAvLyBEZXRlY3QgaU9TLlxuICAgIGVsc2UgaWYgKC9eaVAvLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIG5hbWUgfHwgKG5hbWUgPSAnU2FmYXJpJyk7XG4gICAgICBvcyA9ICdpT1MnICsgKChkYXRhID0gLyBPUyAoW1xcZF9dKykvaS5leGVjKHVhKSlcbiAgICAgICAgPyAnICcgKyBkYXRhWzFdLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICA6ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEt1YnVudHUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnS29ucXVlcm9yJyAmJiAhL2J1bnR1L2kudGVzdChvcykpIHtcbiAgICAgIG9zID0gJ0t1YnVudHUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQW5kcm9pZCBicm93c2Vycy5cbiAgICBlbHNlIGlmICgobWFudWZhY3R1cmVyICYmIG1hbnVmYWN0dXJlciAhPSAnR29vZ2xlJyAmJlxuICAgICAgICAoKC9DaHJvbWUvLnRlc3QobmFtZSkgJiYgIS9cXGJNb2JpbGUgU2FmYXJpXFxiL2kudGVzdCh1YSkpIHx8IC9cXGJWaXRhXFxiLy50ZXN0KHByb2R1Y3QpKSkgfHxcbiAgICAgICAgKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSAmJiAvXkNocm9tZS8udGVzdChuYW1lKSAmJiAvXFxiVmVyc2lvblxcLy9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSA9ICdBbmRyb2lkIEJyb3dzZXInO1xuICAgICAgb3MgPSAvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6ICdBbmRyb2lkJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFNpbGsgZGVza3RvcC9hY2NlbGVyYXRlZCBtb2Rlcy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTaWxrJykge1xuICAgICAgaWYgKCEvXFxiTW9iaS9pLnRlc3QodWEpKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQnO1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIH1cbiAgICAgIGlmICgvQWNjZWxlcmF0ZWQgKj0gKnRydWUvaS50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdhY2NlbGVyYXRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgUGFsZU1vb24gaWRlbnRpZnlpbmcgYXMgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdQYWxlTW9vbicgJiYgKGRhdGEgPSAvXFxiRmlyZWZveFxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyBGaXJlZm94ICcgKyBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggT1MgYW5kIHByb2R1Y3RzIHJ1bm5pbmcgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdGaXJlZm94JyAmJiAoZGF0YSA9IC9cXGIoTW9iaWxlfFRhYmxldHxUVilcXGIvaS5leGVjKHVhKSkpIHtcbiAgICAgIG9zIHx8IChvcyA9ICdGaXJlZm94IE9TJyk7XG4gICAgICBwcm9kdWN0IHx8IChwcm9kdWN0ID0gZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBmYWxzZSBwb3NpdGl2ZXMgZm9yIEZpcmVmb3gvU2FmYXJpLlxuICAgIGVsc2UgaWYgKCFuYW1lIHx8IChkYXRhID0gIS9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAvXFxiKD86RmlyZWZveHxTYWZhcmkpXFxiLy5leGVjKG5hbWUpKSkge1xuICAgICAgLy8gRXNjYXBlIHRoZSBgL2AgZm9yIEZpcmVmb3ggMS5cbiAgICAgIGlmIChuYW1lICYmICFwcm9kdWN0ICYmIC9bXFwvLF18XlteKF0rP1xcKS8udGVzdCh1YS5zbGljZSh1YS5pbmRleE9mKGRhdGEgKyAnLycpICsgOCkpKSB7XG4gICAgICAgIC8vIENsZWFyIG5hbWUgb2YgZmFsc2UgcG9zaXRpdmVzLlxuICAgICAgICBuYW1lID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFJlYXNzaWduIGEgZ2VuZXJpYyBuYW1lLlxuICAgICAgaWYgKChkYXRhID0gcHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgb3MpICYmXG4gICAgICAgICAgKHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IC9cXGIoPzpBbmRyb2lkfFN5bWJpYW4gT1N8VGFibGV0IE9TfHdlYk9TKVxcYi8udGVzdChvcykpKSB7XG4gICAgICAgIG5hbWUgPSAvW2Etel0rKD86IEhhdCk/L2kuZXhlYygvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6IGRhdGEpICsgJyBCcm93c2VyJztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIENocm9tZSB2ZXJzaW9uIHRvIGRlc2NyaXB0aW9uIGZvciBFbGVjdHJvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdFbGVjdHJvbicgJiYgKGRhdGEgPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBub24tT3BlcmEgKFByZXN0by1iYXNlZCkgdmVyc2lvbnMgKG9yZGVyIGlzIGltcG9ydGFudCkuXG4gICAgaWYgKCF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbihbXG4gICAgICAgICcoPzpDbG91ZDl8Q3JpT1N8Q3JNb3xFZGdlfEZ4aU9TfElFTW9iaWxlfElyb258T3BlcmEgP01pbml8T1BpT1N8T1BSfFJhdmVufFNhbXN1bmdCcm93c2VyfFNpbGsoPyEvW1xcXFxkLl0rJCkpJyxcbiAgICAgICAgJ1ZlcnNpb24nLFxuICAgICAgICBxdWFsaWZ5KG5hbWUpLFxuICAgICAgICAnKD86RmlyZWZveHxNaW5lZmllbGR8TmV0RnJvbnQpJ1xuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBzdHViYm9ybiBsYXlvdXQgZW5naW5lcy5cbiAgICBpZiAoKGRhdGEgPVxuICAgICAgICAgIGxheW91dCA9PSAnaUNhYicgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+IDMgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAvXFxiT3BlcmFcXGIvLnRlc3QobmFtZSkgJiYgKC9cXGJPUFJcXGIvLnRlc3QodWEpID8gJ0JsaW5rJyA6ICdQcmVzdG8nKSB8fFxuICAgICAgICAgIC9cXGIoPzpNaWRvcml8Tm9va3xTYWZhcmkpXFxiL2kudGVzdCh1YSkgJiYgIS9eKD86VHJpZGVudHxFZGdlSFRNTCkkLy50ZXN0KGxheW91dCkgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAhbGF5b3V0ICYmIC9cXGJNU0lFXFxiL2kudGVzdCh1YSkgJiYgKG9zID09ICdNYWMgT1MnID8gJ1Rhc21hbicgOiAnVHJpZGVudCcpIHx8XG4gICAgICAgICAgbGF5b3V0ID09ICdXZWJLaXQnICYmIC9cXGJQbGF5U3RhdGlvblxcYig/ISBWaXRhXFxiKS9pLnRlc3QobmFtZSkgJiYgJ05ldEZyb250J1xuICAgICAgICApKSB7XG4gICAgICBsYXlvdXQgPSBbZGF0YV07XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDcgZGVza3RvcCBtb2RlLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgKGRhdGEgPSAoLzsgKig/OlhCTFdQfFp1bmVXUCkoXFxkKykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSAnICsgKC9cXCskLy50ZXN0KGRhdGEpID8gZGF0YSA6IGRhdGEgKyAnLngnKTtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA4LnggZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKC9cXGJXUERlc2t0b3BcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgbmFtZSA9ICdJRSBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSA4LngnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB2ZXJzaW9uIHx8ICh2ZXJzaW9uID0gKC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpIHx8IDApWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIDExIGlkZW50aWZ5aW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKG5hbWUgIT0gJ0lFJyAmJiBsYXlvdXQgPT0gJ1RyaWRlbnQnICYmIChkYXRhID0gL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkpKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyAnICsgbmFtZSArICh2ZXJzaW9uID8gJyAnICsgdmVyc2lvbiA6ICcnKSk7XG4gICAgICB9XG4gICAgICBuYW1lID0gJ0lFJztcbiAgICAgIHZlcnNpb24gPSBkYXRhWzFdO1xuICAgIH1cbiAgICAvLyBMZXZlcmFnZSBlbnZpcm9ubWVudCBmZWF0dXJlcy5cbiAgICBpZiAodXNlRmVhdHVyZXMpIHtcbiAgICAgIC8vIERldGVjdCBzZXJ2ZXItc2lkZSBlbnZpcm9ubWVudHMuXG4gICAgICAvLyBSaGlubyBoYXMgYSBnbG9iYWwgZnVuY3Rpb24gd2hpbGUgb3RoZXJzIGhhdmUgYSBnbG9iYWwgb2JqZWN0LlxuICAgICAgaWYgKGlzSG9zdFR5cGUoY29udGV4dCwgJ2dsb2JhbCcpKSB7XG4gICAgICAgIGlmIChqYXZhKSB7XG4gICAgICAgICAgZGF0YSA9IGphdmEubGFuZy5TeXN0ZW07XG4gICAgICAgICAgYXJjaCA9IGRhdGEuZ2V0UHJvcGVydHkoJ29zLmFyY2gnKTtcbiAgICAgICAgICBvcyA9IG9zIHx8IGRhdGEuZ2V0UHJvcGVydHkoJ29zLm5hbWUnKSArICcgJyArIGRhdGEuZ2V0UHJvcGVydHkoJ29zLnZlcnNpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmhpbm8pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmVyc2lvbiA9IGNvbnRleHQucmVxdWlyZSgncmluZ28vZW5naW5lJykudmVyc2lvbi5qb2luKCcuJyk7XG4gICAgICAgICAgICBuYW1lID0gJ1JpbmdvSlMnO1xuICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgaWYgKChkYXRhID0gY29udGV4dC5zeXN0ZW0pICYmIGRhdGEuZ2xvYmFsLnN5c3RlbSA9PSBjb250ZXh0LnN5c3RlbSkge1xuICAgICAgICAgICAgICBuYW1lID0gJ05hcndoYWwnO1xuICAgICAgICAgICAgICBvcyB8fCAob3MgPSBkYXRhWzBdLm9zIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnUmhpbm8nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgY29udGV4dC5wcm9jZXNzID09ICdvYmplY3QnICYmICFjb250ZXh0LnByb2Nlc3MuYnJvd3NlciAmJlxuICAgICAgICAgIChkYXRhID0gY29udGV4dC5wcm9jZXNzKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5lbGVjdHJvbiA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ0VsZWN0cm9uJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMuZWxlY3Ryb247XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLm53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyB2ZXJzaW9uLCAnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOVy5qcyc7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLm53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnTm9kZS5qcyc7XG4gICAgICAgICAgICBhcmNoID0gZGF0YS5hcmNoO1xuICAgICAgICAgICAgb3MgPSBkYXRhLnBsYXRmb3JtO1xuICAgICAgICAgICAgdmVyc2lvbiA9IC9bXFxkLl0rLy5leGVjKGRhdGEudmVyc2lvbik7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbiA/IHZlcnNpb25bMF0gOiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEFkb2JlIEFJUi5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnJ1bnRpbWUpKSA9PSBhaXJSdW50aW1lQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdBZG9iZSBBSVInO1xuICAgICAgICBvcyA9IGRhdGEuZmxhc2guc3lzdGVtLkNhcGFiaWxpdGllcy5vcztcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBQaGFudG9tSlMuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5waGFudG9tKSkgPT0gcGhhbnRvbUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnUGhhbnRvbUpTJztcbiAgICAgICAgdmVyc2lvbiA9IChkYXRhID0gZGF0YS52ZXJzaW9uIHx8IG51bGwpICYmIChkYXRhLm1ham9yICsgJy4nICsgZGF0YS5taW5vciArICcuJyArIGRhdGEucGF0Y2gpO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIGNvbXBhdGliaWxpdHkgbW9kZXMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAoZGF0YSA9IC9cXGJUcmlkZW50XFwvKFxcZCspL2kuZXhlYyh1YSkpKSB7XG4gICAgICAgIC8vIFdlJ3JlIGluIGNvbXBhdGliaWxpdHkgbW9kZSB3aGVuIHRoZSBUcmlkZW50IHZlcnNpb24gKyA0IGRvZXNuJ3RcbiAgICAgICAgLy8gZXF1YWwgdGhlIGRvY3VtZW50IG1vZGUuXG4gICAgICAgIHZlcnNpb24gPSBbdmVyc2lvbiwgZG9jLmRvY3VtZW50TW9kZV07XG4gICAgICAgIGlmICgoZGF0YSA9ICtkYXRhWzFdICsgNCkgIT0gdmVyc2lvblsxXSkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0lFICcgKyB2ZXJzaW9uWzFdICsgJyBtb2RlJyk7XG4gICAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnJyk7XG4gICAgICAgICAgdmVyc2lvblsxXSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgdmVyc2lvbiA9IG5hbWUgPT0gJ0lFJyA/IFN0cmluZyh2ZXJzaW9uWzFdLnRvRml4ZWQoMSkpIDogdmVyc2lvblswXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSAxMSBtYXNraW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgL14oPzpDaHJvbWV8RmlyZWZveClcXGIvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnbWFza2luZyBhcyAnICsgbmFtZSArICcgJyArIHZlcnNpb24pO1xuICAgICAgICBuYW1lID0gJ0lFJztcbiAgICAgICAgdmVyc2lvbiA9ICcxMS4wJztcbiAgICAgICAgbGF5b3V0ID0gWydUcmlkZW50J107XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcyAmJiBmb3JtYXQob3MpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgcHJlcmVsZWFzZSBwaGFzZXMuXG4gICAgaWYgKHZlcnNpb24gJiYgKGRhdGEgPVxuICAgICAgICAgIC8oPzpbYWJdfGRwfHByZXxbYWJdXFxkK3ByZSkoPzpcXGQrXFwrPyk/JC9pLmV4ZWModmVyc2lvbikgfHxcbiAgICAgICAgICAvKD86YWxwaGF8YmV0YSkoPzogP1xcZCk/L2kuZXhlYyh1YSArICc7JyArICh1c2VGZWF0dXJlcyAmJiBuYXYuYXBwTWlub3JWZXJzaW9uKSkgfHxcbiAgICAgICAgICAvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgJ2EnXG4gICAgICAgICkpIHtcbiAgICAgIHByZXJlbGVhc2UgPSAvYi9pLnRlc3QoZGF0YSkgPyAnYmV0YScgOiAnYWxwaGEnO1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZShSZWdFeHAoZGF0YSArICdcXFxcKz8kJyksICcnKSArXG4gICAgICAgIChwcmVyZWxlYXNlID09ICdiZXRhJyA/IGJldGEgOiBhbHBoYSkgKyAoL1xcZCtcXCs/Ly5leGVjKGRhdGEpIHx8ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggTW9iaWxlLlxuICAgIGlmIChuYW1lID09ICdGZW5uZWMnIHx8IG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGIoPzpBbmRyb2lkfEZpcmVmb3ggT1MpXFxiLy50ZXN0KG9zKSkge1xuICAgICAgbmFtZSA9ICdGaXJlZm94IE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIE9ic2N1cmUgTWF4dGhvbidzIHVucmVsaWFibGUgdmVyc2lvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdNYXh0aG9uJyAmJiB2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKC9cXC5bXFxkLl0rLywgJy54Jyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBYYm94IDM2MCBhbmQgWGJveCBPbmUuXG4gICAgZWxzZSBpZiAoL1xcYlhib3hcXGIvaS50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnKSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcgJiYgL1xcYklFTW9iaWxlXFxiLy50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdtb2JpbGUgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgbW9iaWxlIHBvc3RmaXguXG4gICAgZWxzZSBpZiAoKC9eKD86Q2hyb21lfElFfE9wZXJhKSQvLnRlc3QobmFtZSkgfHwgbmFtZSAmJiAhcHJvZHVjdCAmJiAhL0Jyb3dzZXJ8TW9iaS8udGVzdChuYW1lKSkgJiZcbiAgICAgICAgKG9zID09ICdXaW5kb3dzIENFJyB8fCAvTW9iaS9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBwbGF0Zm9ybSBwcmV2aWV3LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0lFJyAmJiB1c2VGZWF0dXJlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGNvbnRleHQuZXh0ZXJuYWwgPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdwbGF0Zm9ybSBwcmV2aWV3Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdlbWJlZGRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgQmxhY2tCZXJyeSBPUyB2ZXJzaW9uLlxuICAgIC8vIGh0dHA6Ly9kb2NzLmJsYWNrYmVycnkuY29tL2VuL2RldmVsb3BlcnMvZGVsaXZlcmFibGVzLzE4MTY5L0hUVFBfaGVhZGVyc19zZW50X2J5X0JCX0Jyb3dzZXJfMTIzNDkxMV8xMS5qc3BcbiAgICBlbHNlIGlmICgoL1xcYkJsYWNrQmVycnlcXGIvLnRlc3QocHJvZHVjdCkgfHwgL1xcYkJCMTBcXGIvLnRlc3QodWEpKSAmJiAoZGF0YSA9XG4gICAgICAgICAgKFJlZ0V4cChwcm9kdWN0LnJlcGxhY2UoLyArL2csICcgKicpICsgJy8oWy5cXFxcZF0rKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICkpIHtcbiAgICAgIGRhdGEgPSBbZGF0YSwgL0JCMTAvLnRlc3QodWEpXTtcbiAgICAgIG9zID0gKGRhdGFbMV0gPyAocHJvZHVjdCA9IG51bGwsIG1hbnVmYWN0dXJlciA9ICdCbGFja0JlcnJ5JykgOiAnRGV2aWNlIFNvZnR3YXJlJykgKyAnICcgKyBkYXRhWzBdO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBpZGVudGlmeWluZy9tYXNraW5nIGl0c2VsZiBhcyBhbm90aGVyIGJyb3dzZXIuXG4gICAgLy8gaHR0cDovL3d3dy5vcGVyYS5jb20vc3VwcG9ydC9rYi92aWV3Lzg0My9cbiAgICBlbHNlIGlmICh0aGlzICE9IGZvck93biAmJiBwcm9kdWN0ICE9ICdXaWknICYmIChcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgb3BlcmEpIHx8XG4gICAgICAgICAgKC9PcGVyYS8udGVzdChuYW1lKSAmJiAvXFxiKD86TVNJRXxGaXJlZm94KVxcYi9pLnRlc3QodWEpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiT1MgWCAoPzpcXGQrXFwuKXsyLH0vLnRlc3Qob3MpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdJRScgJiYgKFxuICAgICAgICAgICAgKG9zICYmICEvXldpbi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDUuNSkgfHxcbiAgICAgICAgICAgIC9cXGJXaW5kb3dzIFhQXFxiLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gOCB8fFxuICAgICAgICAgICAgdmVyc2lvbiA9PSA4ICYmICEvXFxiVHJpZGVudFxcYi8udGVzdCh1YSlcbiAgICAgICAgICApKVxuICAgICAgICApICYmICFyZU9wZXJhLnRlc3QoKGRhdGEgPSBwYXJzZS5jYWxsKGZvck93biwgdWEucmVwbGFjZShyZU9wZXJhLCAnJykgKyAnOycpKSkgJiYgZGF0YS5uYW1lKSB7XG4gICAgICAvLyBXaGVuIFwiaWRlbnRpZnlpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIGJvdGggT3BlcmEgYW5kIHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGRhdGEgPSAnaW5nIGFzICcgKyBkYXRhLm5hbWUgKyAoKGRhdGEgPSBkYXRhLnZlcnNpb24pID8gJyAnICsgZGF0YSA6ICcnKTtcbiAgICAgIGlmIChyZU9wZXJhLnRlc3QobmFtZSkpIHtcbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSAmJiBvcyA9PSAnTWFjIE9TJykge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gJ2lkZW50aWZ5JyArIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBXaGVuIFwibWFza2luZ1wiLCB0aGUgVUEgY29udGFpbnMgb25seSB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBlbHNlIHtcbiAgICAgICAgZGF0YSA9ICdtYXNrJyArIGRhdGE7XG4gICAgICAgIGlmIChvcGVyYUNsYXNzKSB7XG4gICAgICAgICAgbmFtZSA9IGZvcm1hdChvcGVyYUNsYXNzLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMSAkMicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lID0gJ09wZXJhJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdXNlRmVhdHVyZXMpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGF5b3V0ID0gWydQcmVzdG8nXTtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXZWJLaXQgTmlnaHRseSBhbmQgYXBwcm94aW1hdGUgQ2hyb21lL1NhZmFyaSB2ZXJzaW9ucy5cbiAgICBpZiAoKGRhdGEgPSAoL1xcYkFwcGxlV2ViS2l0XFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgLy8gQ29ycmVjdCBidWlsZCBudW1iZXIgZm9yIG51bWVyaWMgY29tcGFyaXNvbi5cbiAgICAgIC8vIChlLmcuIFwiNTMyLjVcIiBiZWNvbWVzIFwiNTMyLjA1XCIpXG4gICAgICBkYXRhID0gW3BhcnNlRmxvYXQoZGF0YS5yZXBsYWNlKC9cXC4oXFxkKSQvLCAnLjAkMScpKSwgZGF0YV07XG4gICAgICAvLyBOaWdodGx5IGJ1aWxkcyBhcmUgcG9zdGZpeGVkIHdpdGggYSBcIitcIi5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmIGRhdGFbMV0uc2xpY2UoLTEpID09ICcrJykge1xuICAgICAgICBuYW1lID0gJ1dlYktpdCBOaWdodGx5JztcbiAgICAgICAgcHJlcmVsZWFzZSA9ICdhbHBoYSc7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhWzFdLnNsaWNlKDAsIC0xKTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFyIGluY29ycmVjdCBicm93c2VyIHZlcnNpb25zLlxuICAgICAgZWxzZSBpZiAodmVyc2lvbiA9PSBkYXRhWzFdIHx8XG4gICAgICAgICAgdmVyc2lvbiA9PSAoZGF0YVsyXSA9ICgvXFxiU2FmYXJpXFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgZnVsbCBDaHJvbWUgdmVyc2lvbiB3aGVuIGF2YWlsYWJsZS5cbiAgICAgIGRhdGFbMV0gPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKS9pLmV4ZWModWEpIHx8IDApWzFdO1xuICAgICAgLy8gRGV0ZWN0IEJsaW5rIGxheW91dCBlbmdpbmUuXG4gICAgICBpZiAoZGF0YVswXSA9PSA1MzcuMzYgJiYgZGF0YVsyXSA9PSA1MzcuMzYgJiYgcGFyc2VGbG9hdChkYXRhWzFdKSA+PSAyOCAmJiBsYXlvdXQgPT0gJ1dlYktpdCcpIHtcbiAgICAgICAgbGF5b3V0ID0gWydCbGluayddO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEphdmFTY3JpcHRDb3JlLlxuICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzY4NDc0L2hvdy1jYW4taS1kZXRlY3Qtd2hpY2gtamF2YXNjcmlwdC1lbmdpbmUtdjgtb3ItanNjLWlzLXVzZWQtYXQtcnVudGltZS1pbi1hbmRyb2lcbiAgICAgIGlmICghdXNlRmVhdHVyZXMgfHwgKCFsaWtlQ2hyb21lICYmICFkYXRhWzFdKSkge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIFNhZmFyaScpO1xuICAgICAgICBkYXRhID0gKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNDAwID8gMSA6IGRhdGEgPCA1MDAgPyAyIDogZGF0YSA8IDUyNiA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQgPyAnNCsnIDogZGF0YSA8IDUzNSA/IDUgOiBkYXRhIDwgNTM3ID8gNiA6IGRhdGEgPCA1MzggPyA3IDogZGF0YSA8IDYwMSA/IDggOiAnOCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBDaHJvbWUnKTtcbiAgICAgICAgZGF0YSA9IGRhdGFbMV0gfHwgKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNTMwID8gMSA6IGRhdGEgPCA1MzIgPyAyIDogZGF0YSA8IDUzMi4wNSA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQuMDMgPyA1IDogZGF0YSA8IDUzNC4wNyA/IDYgOiBkYXRhIDwgNTM0LjEwID8gNyA6IGRhdGEgPCA1MzQuMTMgPyA4IDogZGF0YSA8IDUzNC4xNiA/IDkgOiBkYXRhIDwgNTM0LjI0ID8gMTAgOiBkYXRhIDwgNTM0LjMwID8gMTEgOiBkYXRhIDwgNTM1LjAxID8gMTIgOiBkYXRhIDwgNTM1LjAyID8gJzEzKycgOiBkYXRhIDwgNTM1LjA3ID8gMTUgOiBkYXRhIDwgNTM1LjExID8gMTYgOiBkYXRhIDwgNTM1LjE5ID8gMTcgOiBkYXRhIDwgNTM2LjA1ID8gMTggOiBkYXRhIDwgNTM2LjEwID8gMTkgOiBkYXRhIDwgNTM3LjAxID8gMjAgOiBkYXRhIDwgNTM3LjExID8gJzIxKycgOiBkYXRhIDwgNTM3LjEzID8gMjMgOiBkYXRhIDwgNTM3LjE4ID8gMjQgOiBkYXRhIDwgNTM3LjI0ID8gMjUgOiBkYXRhIDwgNTM3LjM2ID8gMjYgOiBsYXlvdXQgIT0gJ0JsaW5rJyA/ICcyNycgOiAnMjgnKTtcbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgcG9zdGZpeCBvZiBcIi54XCIgb3IgXCIrXCIgZm9yIGFwcHJveGltYXRlIHZlcnNpb25zLlxuICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gKz0gJyAnICsgKGRhdGEgKz0gdHlwZW9mIGRhdGEgPT0gJ251bWJlcicgPyAnLngnIDogL1suK10vLnRlc3QoZGF0YSkgPyAnJyA6ICcrJykpO1xuICAgICAgLy8gT2JzY3VyZSB2ZXJzaW9uIGZvciBzb21lIFNhZmFyaSAxLTIgcmVsZWFzZXMuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAoIXZlcnNpb24gfHwgcGFyc2VJbnQodmVyc2lvbikgPiA0NSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IGRhdGE7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBkZXNrdG9wIG1vZGVzLlxuICAgIGlmIChuYW1lID09ICdPcGVyYScgJiYgIChkYXRhID0gL1xcYnpib3Z8enZhdiQvLmV4ZWMob3MpKSkge1xuICAgICAgbmFtZSArPSAnICc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIGlmIChkYXRhID09ICd6dmF2Jykge1xuICAgICAgICBuYW1lICs9ICdNaW5pJztcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuYW1lICs9ICdNb2JpbGUnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSArICckJyksICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IENocm9tZSBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAvXFxiQ2hyb21lXFxiLy5leGVjKGxheW91dCAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIG5hbWUgPSAnQ2hyb21lIE1vYmlsZSc7XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcblxuICAgICAgaWYgKC9cXGJPUyBYXFxiLy50ZXN0KG9zKSkge1xuICAgICAgICBtYW51ZmFjdHVyZXIgPSAnQXBwbGUnO1xuICAgICAgICBvcyA9ICdpT1MgNC4zKyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFN0cmlwIGluY29ycmVjdCBPUyB2ZXJzaW9ucy5cbiAgICBpZiAodmVyc2lvbiAmJiB2ZXJzaW9uLmluZGV4T2YoKGRhdGEgPSAvW1xcZC5dKyQvLmV4ZWMob3MpKSkgPT0gMCAmJlxuICAgICAgICB1YS5pbmRleE9mKCcvJyArIGRhdGEgKyAnLScpID4gLTEpIHtcbiAgICAgIG9zID0gdHJpbShvcy5yZXBsYWNlKGRhdGEsICcnKSk7XG4gICAgfVxuICAgIC8vIEFkZCBsYXlvdXQgZW5naW5lLlxuICAgIGlmIChsYXlvdXQgJiYgIS9cXGIoPzpBdmFudHxOb29rKVxcYi8udGVzdChuYW1lKSAmJiAoXG4gICAgICAgIC9Ccm93c2VyfEx1bmFzY2FwZXxNYXh0aG9uLy50ZXN0KG5hbWUpIHx8XG4gICAgICAgIG5hbWUgIT0gJ1NhZmFyaScgJiYgL15pT1MvLnRlc3Qob3MpICYmIC9cXGJTYWZhcmlcXGIvLnRlc3QobGF5b3V0WzFdKSB8fFxuICAgICAgICAvXig/OkFkb2JlfEFyb3JhfEJyZWFjaHxNaWRvcml8T3BlcmF8UGhhbnRvbXxSZWtvbnF8Um9ja3xTYW1zdW5nIEludGVybmV0fFNsZWlwbmlyfFdlYikvLnRlc3QobmFtZSkgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgLy8gRG9uJ3QgYWRkIGxheW91dCBkZXRhaWxzIHRvIGRlc2NyaXB0aW9uIGlmIHRoZXkgYXJlIGZhbHNleS5cbiAgICAgIChkYXRhID0gbGF5b3V0W2xheW91dC5sZW5ndGggLSAxXSkgJiYgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gQ29tYmluZSBjb250ZXh0dWFsIGluZm9ybWF0aW9uLlxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIGRlc2NyaXB0aW9uID0gWycoJyArIGRlc2NyaXB0aW9uLmpvaW4oJzsgJykgKyAnKSddO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgbWFudWZhY3R1cmVyIHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgcHJvZHVjdCAmJiBwcm9kdWN0LmluZGV4T2YobWFudWZhY3R1cmVyKSA8IDApIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ29uICcgKyBtYW51ZmFjdHVyZXIpO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgcHJvZHVjdCB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAocHJvZHVjdCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgoL15vbiAvLnRlc3QoZGVzY3JpcHRpb25bZGVzY3JpcHRpb24ubGVuZ3RoIC0gMV0pID8gJycgOiAnb24gJykgKyBwcm9kdWN0KTtcbiAgICB9XG4gICAgLy8gUGFyc2UgdGhlIE9TIGludG8gYW4gb2JqZWN0LlxuICAgIGlmIChvcykge1xuICAgICAgZGF0YSA9IC8gKFtcXGQuK10rKSQvLmV4ZWMob3MpO1xuICAgICAgaXNTcGVjaWFsQ2FzZWRPUyA9IGRhdGEgJiYgb3MuY2hhckF0KG9zLmxlbmd0aCAtIGRhdGFbMF0ubGVuZ3RoIC0gMSkgPT0gJy8nO1xuICAgICAgb3MgPSB7XG4gICAgICAgICdhcmNoaXRlY3R1cmUnOiAzMixcbiAgICAgICAgJ2ZhbWlseSc6IChkYXRhICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/IG9zLnJlcGxhY2UoZGF0YVswXSwgJycpIDogb3MsXG4gICAgICAgICd2ZXJzaW9uJzogZGF0YSA/IGRhdGFbMV0gOiBudWxsLFxuICAgICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgdmVyc2lvbiA9IHRoaXMudmVyc2lvbjtcbiAgICAgICAgICByZXR1cm4gdGhpcy5mYW1pbHkgKyAoKHZlcnNpb24gJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gJyAnICsgdmVyc2lvbiA6ICcnKSArICh0aGlzLmFyY2hpdGVjdHVyZSA9PSA2NCA/ICcgNjQtYml0JyA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gQWRkIGJyb3dzZXIvT1MgYXJjaGl0ZWN0dXJlLlxuICAgIGlmICgoZGF0YSA9IC9cXGIoPzpBTUR8SUF8V2lufFdPV3x4ODZffHgpNjRcXGIvaS5leGVjKGFyY2gpKSAmJiAhL1xcYmk2ODZcXGIvaS50ZXN0KGFyY2gpKSB7XG4gICAgICBpZiAob3MpIHtcbiAgICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgICAgIG9zLmZhbWlseSA9IG9zLmZhbWlseS5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSksICcnKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgICBuYW1lICYmICgvXFxiV09XNjRcXGIvaS50ZXN0KHVhKSB8fFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiAvXFx3KD86ODZ8MzIpJC8udGVzdChuYXYuY3B1Q2xhc3MgfHwgbmF2LnBsYXRmb3JtKSAmJiAhL1xcYldpbjY0OyB4NjRcXGIvaS50ZXN0KHVhKSkpXG4gICAgICApIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnMzItYml0Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENocm9tZSAzOSBhbmQgYWJvdmUgb24gT1MgWCBpcyBhbHdheXMgNjQtYml0LlxuICAgIGVsc2UgaWYgKFxuICAgICAgICBvcyAmJiAvXk9TIFgvLnRlc3Qob3MuZmFtaWx5KSAmJlxuICAgICAgICBuYW1lID09ICdDaHJvbWUnICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPj0gMzlcbiAgICApIHtcbiAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgIH1cblxuICAgIHVhIHx8ICh1YSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgdmFyIHBsYXRmb3JtID0ge307XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gZGVzY3JpcHRpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3NlcidzIGxheW91dCBlbmdpbmUuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gbGF5b3V0IGVuZ2luZXMgaW5jbHVkZTpcbiAgICAgKiBcIkJsaW5rXCIsIFwiRWRnZUhUTUxcIiwgXCJHZWNrb1wiLCBcIlRyaWRlbnRcIiBhbmQgXCJXZWJLaXRcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5sYXlvdXQgPSBsYXlvdXQgJiYgbGF5b3V0WzBdO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QncyBtYW51ZmFjdHVyZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBtYW51ZmFjdHVyZXJzIGluY2x1ZGU6XG4gICAgICogXCJBcHBsZVwiLCBcIkFyY2hvc1wiLCBcIkFtYXpvblwiLCBcIkFzdXNcIiwgXCJCYXJuZXMgJiBOb2JsZVwiLCBcIkJsYWNrQmVycnlcIixcbiAgICAgKiBcIkdvb2dsZVwiLCBcIkhQXCIsIFwiSFRDXCIsIFwiTEdcIiwgXCJNaWNyb3NvZnRcIiwgXCJNb3Rvcm9sYVwiLCBcIk5pbnRlbmRvXCIsXG4gICAgICogXCJOb2tpYVwiLCBcIlNhbXN1bmdcIiBhbmQgXCJTb255XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubWFudWZhY3R1cmVyID0gbWFudWZhY3R1cmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIvZW52aXJvbm1lbnQuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gYnJvd3NlciBuYW1lcyBpbmNsdWRlOlxuICAgICAqIFwiQ2hyb21lXCIsIFwiRWxlY3Ryb25cIiwgXCJGaXJlZm94XCIsIFwiRmlyZWZveCBmb3IgaU9TXCIsIFwiSUVcIixcbiAgICAgKiBcIk1pY3Jvc29mdCBFZGdlXCIsIFwiUGhhbnRvbUpTXCIsIFwiU2FmYXJpXCIsIFwiU2VhTW9ua2V5XCIsIFwiU2lsa1wiLFxuICAgICAqIFwiT3BlcmEgTWluaVwiIGFuZCBcIk9wZXJhXCJcbiAgICAgKlxuICAgICAqIE1vYmlsZSB2ZXJzaW9ucyBvZiBzb21lIGJyb3dzZXJzIGhhdmUgXCJNb2JpbGVcIiBhcHBlbmRlZCB0byB0aGVpciBuYW1lOlxuICAgICAqIGVnLiBcIkNocm9tZSBNb2JpbGVcIiwgXCJGaXJlZm94IE1vYmlsZVwiLCBcIklFIE1vYmlsZVwiIGFuZCBcIk9wZXJhIE1vYmlsZVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm5hbWUgPSBuYW1lO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFscGhhL2JldGEgcmVsZWFzZSBpbmRpY2F0b3IuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByZXJlbGVhc2UgPSBwcmVyZWxlYXNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QgaG9zdGluZyB0aGUgYnJvd3Nlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBwcm9kdWN0cyBpbmNsdWRlOlxuICAgICAqXG4gICAgICogXCJCbGFja0JlcnJ5XCIsIFwiR2FsYXh5IFM0XCIsIFwiTHVtaWFcIiwgXCJpUGFkXCIsIFwiaVBvZFwiLCBcImlQaG9uZVwiLCBcIktpbmRsZVwiLFxuICAgICAqIFwiS2luZGxlIEZpcmVcIiwgXCJOZXh1c1wiLCBcIk5vb2tcIiwgXCJQbGF5Qm9va1wiLCBcIlRvdWNoUGFkXCIgYW5kIFwiVHJhbnNmb3JtZXJcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcm9kdWN0ID0gcHJvZHVjdDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyJ3MgdXNlciBhZ2VudCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnVhID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS52ZXJzaW9uID0gbmFtZSAmJiB2ZXJzaW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5vcyA9IG9zIHx8IHtcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZSB0aGUgT1MgaXMgYnVpbHQgZm9yLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgbnVtYmVyfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2FyY2hpdGVjdHVyZSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIGZhbWlseSBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQ29tbW9uIHZhbHVlcyBpbmNsdWRlOlxuICAgICAgICogXCJXaW5kb3dzXCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCBSMiAvIDdcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IC8gVmlzdGFcIixcbiAgICAgICAqIFwiV2luZG93cyBYUFwiLCBcIk9TIFhcIiwgXCJVYnVudHVcIiwgXCJEZWJpYW5cIiwgXCJGZWRvcmFcIiwgXCJSZWQgSGF0XCIsIFwiU3VTRVwiLFxuICAgICAgICogXCJBbmRyb2lkXCIsIFwiaU9TXCIgYW5kIFwiV2luZG93cyBQaG9uZVwiXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAnZmFtaWx5JzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAndmVyc2lvbic6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogUmV0dXJucyB0aGUgT1Mgc3RyaW5nLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIE9TIHN0cmluZy5cbiAgICAgICAqL1xuICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7IHJldHVybiAnbnVsbCc7IH1cbiAgICB9O1xuXG4gICAgcGxhdGZvcm0ucGFyc2UgPSBwYXJzZTtcbiAgICBwbGF0Zm9ybS50b1N0cmluZyA9IHRvU3RyaW5nUGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0udmVyc2lvbikge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCh2ZXJzaW9uKTtcbiAgICB9XG4gICAgaWYgKHBsYXRmb3JtLm5hbWUpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuICAgIGlmIChvcyAmJiBuYW1lICYmICEob3MgPT0gU3RyaW5nKG9zKS5zcGxpdCgnICcpWzBdICYmIChvcyA9PSBuYW1lLnNwbGl0KCcgJylbMF0gfHwgcHJvZHVjdCkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKHByb2R1Y3QgPyAnKCcgKyBvcyArICcpJyA6ICdvbiAnICsgb3MpO1xuICAgIH1cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLmpvaW4oJyAnKTtcbiAgICB9XG4gICAgcmV0dXJuIHBsYXRmb3JtO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IHBsYXRmb3JtLlxuICB2YXIgcGxhdGZvcm0gPSBwYXJzZSgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMsIGxpa2Ugci5qcywgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEV4cG9zZSBwbGF0Zm9ybSBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIHBsYXRmb3JtIGlzXG4gICAgLy8gbG9hZGVkIGJ5IGEgc2NyaXB0IHRhZyBpbiB0aGUgcHJlc2VuY2Ugb2YgYW4gQU1EIGxvYWRlci5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvIHBsYXRmb3JtIGNhbiBiZSBhbGlhc2VkIHRocm91Z2ggcGF0aCBtYXBwaW5nLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBhbiBgZXhwb3J0c2Agb2JqZWN0LlxuICBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZvck93bihwbGF0Zm9ybSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgZnJlZUV4cG9ydHNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJ2YXIgdjEgPSByZXF1aXJlKCcuL3YxJyk7XG52YXIgdjQgPSByZXF1aXJlKCcuL3Y0Jyk7XG5cbnZhciB1dWlkID0gdjQ7XG51dWlkLnYxID0gdjE7XG51dWlkLnY0ID0gdjQ7XG5cbm1vZHVsZS5leHBvcnRzID0gdXVpZDtcbiIsIi8qKlxuICogQ29udmVydCBhcnJheSBvZiAxNiBieXRlIHZhbHVlcyB0byBVVUlEIHN0cmluZyBmb3JtYXQgb2YgdGhlIGZvcm06XG4gKiBYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFhcbiAqL1xudmFyIGJ5dGVUb0hleCA9IFtdO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICBieXRlVG9IZXhbaV0gPSAoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpO1xufVxuXG5mdW5jdGlvbiBieXRlc1RvVXVpZChidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IG9mZnNldCB8fCAwO1xuICB2YXIgYnRoID0gYnl0ZVRvSGV4O1xuICByZXR1cm4gYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJ5dGVzVG9VdWlkO1xuIiwiLy8gVW5pcXVlIElEIGNyZWF0aW9uIHJlcXVpcmVzIGEgaGlnaCBxdWFsaXR5IHJhbmRvbSAjIGdlbmVyYXRvci4gIEluIHRoZVxuLy8gYnJvd3NlciB0aGlzIGlzIGEgbGl0dGxlIGNvbXBsaWNhdGVkIGR1ZSB0byB1bmtub3duIHF1YWxpdHkgb2YgTWF0aC5yYW5kb20oKVxuLy8gYW5kIGluY29uc2lzdGVudCBzdXBwb3J0IGZvciB0aGUgYGNyeXB0b2AgQVBJLiAgV2UgZG8gdGhlIGJlc3Qgd2UgY2FuIHZpYVxuLy8gZmVhdHVyZS1kZXRlY3Rpb25cblxuLy8gZ2V0UmFuZG9tVmFsdWVzIG5lZWRzIHRvIGJlIGludm9rZWQgaW4gYSBjb250ZXh0IHdoZXJlIFwidGhpc1wiIGlzIGEgQ3J5cHRvIGltcGxlbWVudGF0aW9uLlxudmFyIGdldFJhbmRvbVZhbHVlcyA9ICh0eXBlb2YoY3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQoY3J5cHRvKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAodHlwZW9mKG1zQ3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChtc0NyeXB0bykpO1xuaWYgKGdldFJhbmRvbVZhbHVlcykge1xuICAvLyBXSEFUV0cgY3J5cHRvIFJORyAtIGh0dHA6Ly93aWtpLndoYXR3Zy5vcmcvd2lraS9DcnlwdG9cbiAgdmFyIHJuZHM4ID0gbmV3IFVpbnQ4QXJyYXkoMTYpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB3aGF0d2dSTkcoKSB7XG4gICAgZ2V0UmFuZG9tVmFsdWVzKHJuZHM4KTtcbiAgICByZXR1cm4gcm5kczg7XG4gIH07XG59IGVsc2Uge1xuICAvLyBNYXRoLnJhbmRvbSgpLWJhc2VkIChSTkcpXG4gIC8vXG4gIC8vIElmIGFsbCBlbHNlIGZhaWxzLCB1c2UgTWF0aC5yYW5kb20oKS4gIEl0J3MgZmFzdCwgYnV0IGlzIG9mIHVuc3BlY2lmaWVkXG4gIC8vIHF1YWxpdHkuXG4gIHZhciBybmRzID0gbmV3IEFycmF5KDE2KTtcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1hdGhSTkcoKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIHI7IGkgPCAxNjsgaSsrKSB7XG4gICAgICBpZiAoKGkgJiAweDAzKSA9PT0gMCkgciA9IE1hdGgucmFuZG9tKCkgKiAweDEwMDAwMDAwMDtcbiAgICAgIHJuZHNbaV0gPSByID4+PiAoKGkgJiAweDAzKSA8PCAzKSAmIDB4ZmY7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJuZHM7XG4gIH07XG59XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG4vLyAqKmB2MSgpYCAtIEdlbmVyYXRlIHRpbWUtYmFzZWQgVVVJRCoqXG4vL1xuLy8gSW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL0xpb3NLL1VVSUQuanNcbi8vIGFuZCBodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvdXVpZC5odG1sXG5cbnZhciBfbm9kZUlkO1xudmFyIF9jbG9ja3NlcTtcblxuLy8gUHJldmlvdXMgdXVpZCBjcmVhdGlvbiB0aW1lXG52YXIgX2xhc3RNU2VjcyA9IDA7XG52YXIgX2xhc3ROU2VjcyA9IDA7XG5cbi8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYnJvb2ZhL25vZGUtdXVpZCBmb3IgQVBJIGRldGFpbHNcbmZ1bmN0aW9uIHYxKG9wdGlvbnMsIGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gYnVmICYmIG9mZnNldCB8fCAwO1xuICB2YXIgYiA9IGJ1ZiB8fCBbXTtcblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgdmFyIG5vZGUgPSBvcHRpb25zLm5vZGUgfHwgX25vZGVJZDtcbiAgdmFyIGNsb2Nrc2VxID0gb3B0aW9ucy5jbG9ja3NlcSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jbG9ja3NlcSA6IF9jbG9ja3NlcTtcblxuICAvLyBub2RlIGFuZCBjbG9ja3NlcSBuZWVkIHRvIGJlIGluaXRpYWxpemVkIHRvIHJhbmRvbSB2YWx1ZXMgaWYgdGhleSdyZSBub3RcbiAgLy8gc3BlY2lmaWVkLiAgV2UgZG8gdGhpcyBsYXppbHkgdG8gbWluaW1pemUgaXNzdWVzIHJlbGF0ZWQgdG8gaW5zdWZmaWNpZW50XG4gIC8vIHN5c3RlbSBlbnRyb3B5LiAgU2VlICMxODlcbiAgaWYgKG5vZGUgPT0gbnVsbCB8fCBjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgdmFyIHNlZWRCeXRlcyA9IHJuZygpO1xuICAgIGlmIChub2RlID09IG51bGwpIHtcbiAgICAgIC8vIFBlciA0LjUsIGNyZWF0ZSBhbmQgNDgtYml0IG5vZGUgaWQsICg0NyByYW5kb20gYml0cyArIG11bHRpY2FzdCBiaXQgPSAxKVxuICAgICAgbm9kZSA9IF9ub2RlSWQgPSBbXG4gICAgICAgIHNlZWRCeXRlc1swXSB8IDB4MDEsXG4gICAgICAgIHNlZWRCeXRlc1sxXSwgc2VlZEJ5dGVzWzJdLCBzZWVkQnl0ZXNbM10sIHNlZWRCeXRlc1s0XSwgc2VlZEJ5dGVzWzVdXG4gICAgICBdO1xuICAgIH1cbiAgICBpZiAoY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuMi4yLCByYW5kb21pemUgKDE0IGJpdCkgY2xvY2tzZXFcbiAgICAgIGNsb2Nrc2VxID0gX2Nsb2Nrc2VxID0gKHNlZWRCeXRlc1s2XSA8PCA4IHwgc2VlZEJ5dGVzWzddKSAmIDB4M2ZmZjtcbiAgICB9XG4gIH1cblxuICAvLyBVVUlEIHRpbWVzdGFtcHMgYXJlIDEwMCBuYW5vLXNlY29uZCB1bml0cyBzaW5jZSB0aGUgR3JlZ29yaWFuIGVwb2NoLFxuICAvLyAoMTU4Mi0xMC0xNSAwMDowMCkuICBKU051bWJlcnMgYXJlbid0IHByZWNpc2UgZW5vdWdoIGZvciB0aGlzLCBzb1xuICAvLyB0aW1lIGlzIGhhbmRsZWQgaW50ZXJuYWxseSBhcyAnbXNlY3MnIChpbnRlZ2VyIG1pbGxpc2Vjb25kcykgYW5kICduc2VjcydcbiAgLy8gKDEwMC1uYW5vc2Vjb25kcyBvZmZzZXQgZnJvbSBtc2Vjcykgc2luY2UgdW5peCBlcG9jaCwgMTk3MC0wMS0wMSAwMDowMC5cbiAgdmFyIG1zZWNzID0gb3B0aW9ucy5tc2VjcyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5tc2VjcyA6IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuXG4gIC8vIFBlciA0LjIuMS4yLCB1c2UgY291bnQgb2YgdXVpZCdzIGdlbmVyYXRlZCBkdXJpbmcgdGhlIGN1cnJlbnQgY2xvY2tcbiAgLy8gY3ljbGUgdG8gc2ltdWxhdGUgaGlnaGVyIHJlc29sdXRpb24gY2xvY2tcbiAgdmFyIG5zZWNzID0gb3B0aW9ucy5uc2VjcyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5uc2VjcyA6IF9sYXN0TlNlY3MgKyAxO1xuXG4gIC8vIFRpbWUgc2luY2UgbGFzdCB1dWlkIGNyZWF0aW9uIChpbiBtc2VjcylcbiAgdmFyIGR0ID0gKG1zZWNzIC0gX2xhc3RNU2VjcykgKyAobnNlY3MgLSBfbGFzdE5TZWNzKS8xMDAwMDtcblxuICAvLyBQZXIgNC4yLjEuMiwgQnVtcCBjbG9ja3NlcSBvbiBjbG9jayByZWdyZXNzaW9uXG4gIGlmIChkdCA8IDAgJiYgb3B0aW9ucy5jbG9ja3NlcSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgY2xvY2tzZXEgPSBjbG9ja3NlcSArIDEgJiAweDNmZmY7XG4gIH1cblxuICAvLyBSZXNldCBuc2VjcyBpZiBjbG9jayByZWdyZXNzZXMgKG5ldyBjbG9ja3NlcSkgb3Igd2UndmUgbW92ZWQgb250byBhIG5ld1xuICAvLyB0aW1lIGludGVydmFsXG4gIGlmICgoZHQgPCAwIHx8IG1zZWNzID4gX2xhc3RNU2VjcykgJiYgb3B0aW9ucy5uc2VjcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbnNlY3MgPSAwO1xuICB9XG5cbiAgLy8gUGVyIDQuMi4xLjIgVGhyb3cgZXJyb3IgaWYgdG9vIG1hbnkgdXVpZHMgYXJlIHJlcXVlc3RlZFxuICBpZiAobnNlY3MgPj0gMTAwMDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3V1aWQudjEoKTogQ2FuXFwndCBjcmVhdGUgbW9yZSB0aGFuIDEwTSB1dWlkcy9zZWMnKTtcbiAgfVxuXG4gIF9sYXN0TVNlY3MgPSBtc2VjcztcbiAgX2xhc3ROU2VjcyA9IG5zZWNzO1xuICBfY2xvY2tzZXEgPSBjbG9ja3NlcTtcblxuICAvLyBQZXIgNC4xLjQgLSBDb252ZXJ0IGZyb20gdW5peCBlcG9jaCB0byBHcmVnb3JpYW4gZXBvY2hcbiAgbXNlY3MgKz0gMTIyMTkyOTI4MDAwMDA7XG5cbiAgLy8gYHRpbWVfbG93YFxuICB2YXIgdGwgPSAoKG1zZWNzICYgMHhmZmZmZmZmKSAqIDEwMDAwICsgbnNlY3MpICUgMHgxMDAwMDAwMDA7XG4gIGJbaSsrXSA9IHRsID4+PiAyNCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiAxNiAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdGwgJiAweGZmO1xuXG4gIC8vIGB0aW1lX21pZGBcbiAgdmFyIHRtaCA9IChtc2VjcyAvIDB4MTAwMDAwMDAwICogMTAwMDApICYgMHhmZmZmZmZmO1xuICBiW2krK10gPSB0bWggPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bWggJiAweGZmO1xuXG4gIC8vIGB0aW1lX2hpZ2hfYW5kX3ZlcnNpb25gXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMjQgJiAweGYgfCAweDEwOyAvLyBpbmNsdWRlIHZlcnNpb25cbiAgYltpKytdID0gdG1oID4+PiAxNiAmIDB4ZmY7XG5cbiAgLy8gYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgIChQZXIgNC4yLjIgLSBpbmNsdWRlIHZhcmlhbnQpXG4gIGJbaSsrXSA9IGNsb2Nrc2VxID4+PiA4IHwgMHg4MDtcblxuICAvLyBgY2xvY2tfc2VxX2xvd2BcbiAgYltpKytdID0gY2xvY2tzZXEgJiAweGZmO1xuXG4gIC8vIGBub2RlYFxuICBmb3IgKHZhciBuID0gMDsgbiA8IDY7ICsrbikge1xuICAgIGJbaSArIG5dID0gbm9kZVtuXTtcbiAgfVxuXG4gIHJldHVybiBidWYgPyBidWYgOiBieXRlc1RvVXVpZChiKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2MTtcbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbmZ1bmN0aW9uIHY0KG9wdGlvbnMsIGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gYnVmICYmIG9mZnNldCB8fCAwO1xuXG4gIGlmICh0eXBlb2Yob3B0aW9ucykgPT0gJ3N0cmluZycpIHtcbiAgICBidWYgPSBvcHRpb25zID09PSAnYmluYXJ5JyA/IG5ldyBBcnJheSgxNikgOiBudWxsO1xuICAgIG9wdGlvbnMgPSBudWxsO1xuICB9XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBybmRzID0gb3B0aW9ucy5yYW5kb20gfHwgKG9wdGlvbnMucm5nIHx8IHJuZykoKTtcblxuICAvLyBQZXIgNC40LCBzZXQgYml0cyBmb3IgdmVyc2lvbiBhbmQgYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgXG4gIHJuZHNbNl0gPSAocm5kc1s2XSAmIDB4MGYpIHwgMHg0MDtcbiAgcm5kc1s4XSA9IChybmRzWzhdICYgMHgzZikgfCAweDgwO1xuXG4gIC8vIENvcHkgYnl0ZXMgdG8gYnVmZmVyLCBpZiBwcm92aWRlZFxuICBpZiAoYnVmKSB7XG4gICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IDE2OyArK2lpKSB7XG4gICAgICBidWZbaSArIGlpXSA9IHJuZHNbaWldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWYgfHwgYnl0ZXNUb1V1aWQocm5kcyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjQ7XG4iLCIvKlxyXG5XaWxkRW1pdHRlci5qcyBpcyBhIHNsaW0gbGl0dGxlIGV2ZW50IGVtaXR0ZXIgYnkgQGhlbnJpa2pvcmV0ZWcgbGFyZ2VseSBiYXNlZFxyXG5vbiBAdmlzaW9ubWVkaWEncyBFbWl0dGVyIGZyb20gVUkgS2l0LlxyXG5cclxuV2h5PyBJIHdhbnRlZCBpdCBzdGFuZGFsb25lLlxyXG5cclxuSSBhbHNvIHdhbnRlZCBzdXBwb3J0IGZvciB3aWxkY2FyZCBlbWl0dGVycyBsaWtlIHRoaXM6XHJcblxyXG5lbWl0dGVyLm9uKCcqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgb3RoZXIsIGV2ZW50LCBwYXlsb2Fkcykge1xyXG5cclxufSk7XHJcblxyXG5lbWl0dGVyLm9uKCdzb21lbmFtZXNwYWNlKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcblBsZWFzZSBub3RlIHRoYXQgY2FsbGJhY2tzIHRyaWdnZXJlZCBieSB3aWxkY2FyZCByZWdpc3RlcmVkIGV2ZW50cyBhbHNvIGdldFxyXG50aGUgZXZlbnQgbmFtZSBhcyB0aGUgZmlyc3QgYXJndW1lbnQuXHJcbiovXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IFdpbGRFbWl0dGVyO1xyXG5cclxuZnVuY3Rpb24gV2lsZEVtaXR0ZXIoKSB7IH1cclxuXHJcbldpbGRFbWl0dGVyLm1peGluID0gZnVuY3Rpb24gKGNvbnN0cnVjdG9yKSB7XHJcbiAgICB2YXIgcHJvdG90eXBlID0gY29uc3RydWN0b3IucHJvdG90eXBlIHx8IGNvbnN0cnVjdG9yO1xyXG5cclxuICAgIHByb3RvdHlwZS5pc1dpbGRFbWl0dGVyPSB0cnVlO1xyXG5cclxuICAgIC8vIExpc3RlbiBvbiB0aGUgZ2l2ZW4gYGV2ZW50YCB3aXRoIGBmbmAuIFN0b3JlIGEgZ3JvdXAgbmFtZSBpZiBwcmVzZW50LlxyXG4gICAgcHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXHJcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcclxuICAgICAgICBmdW5jLl9ncm91cE5hbWUgPSBncm91cDtcclxuICAgICAgICAodGhpcy5jYWxsYmFja3NbZXZlbnRdID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdIHx8IFtdKS5wdXNoKGZ1bmMpO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBBZGRzIGFuIGBldmVudGAgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBzaW5nbGVcclxuICAgIC8vIHRpbWUgdGhlbiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQuXHJcbiAgICBwcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xyXG4gICAgICAgIHZhciBzZWxmID0gdGhpcyxcclxuICAgICAgICAgICAgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXHJcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcclxuICAgICAgICBmdW5jdGlvbiBvbigpIHtcclxuICAgICAgICAgICAgc2VsZi5vZmYoZXZlbnQsIG9uKTtcclxuICAgICAgICAgICAgZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLm9uKGV2ZW50LCBncm91cCwgb24pO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBVbmJpbmRzIGFuIGVudGlyZSBncm91cFxyXG4gICAgcHJvdG90eXBlLnJlbGVhc2VHcm91cCA9IGZ1bmN0aW9uIChncm91cE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLCBpLCBsZW4sIGhhbmRsZXJzO1xyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBoYW5kbGVycyA9IHRoaXMuY2FsbGJhY2tzW2l0ZW1dO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBoYW5kbGVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICAgICAgICAgICAgaWYgKGhhbmRsZXJzW2ldLl9ncm91cE5hbWUgPT09IGdyb3VwTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coJ3JlbW92aW5nJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0IGFuZCBzaG9ydGVuIHRoZSBhcnJheSB3ZSdyZSBsb29waW5nIHRocm91Z2hcclxuICAgICAgICAgICAgICAgICAgICBoYW5kbGVycy5zcGxpY2UoaSwgMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaS0tO1xyXG4gICAgICAgICAgICAgICAgICAgIGxlbi0tO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBSZW1vdmUgdGhlIGdpdmVuIGNhbGxiYWNrIGZvciBgZXZlbnRgIG9yIGFsbFxyXG4gICAgLy8gcmVnaXN0ZXJlZCBjYWxsYmFja3MuXHJcbiAgICBwcm90b3R5cGUub2ZmID0gZnVuY3Rpb24gKGV2ZW50LCBmbikge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcclxuICAgICAgICAgICAgaTtcclxuXHJcbiAgICAgICAgaWYgKCFjYWxsYmFja3MpIHJldHVybiB0aGlzO1xyXG5cclxuICAgICAgICAvLyByZW1vdmUgYWxsIGhhbmRsZXJzXHJcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcclxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyByZW1vdmUgc3BlY2lmaWMgaGFuZGxlclxyXG4gICAgICAgIGkgPSBjYWxsYmFja3MuaW5kZXhPZihmbik7XHJcbiAgICAgICAgY2FsbGJhY2tzLnNwbGljZShpLCAxKTtcclxuICAgICAgICBpZiAoY2FsbGJhY2tzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8vIEVtaXQgYGV2ZW50YCB3aXRoIHRoZSBnaXZlbiBhcmdzLlxyXG4gICAgLy8gYWxzbyBjYWxscyBhbnkgYCpgIGhhbmRsZXJzXHJcbiAgICBwcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIChldmVudCkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXHJcbiAgICAgICAgICAgIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcclxuICAgICAgICAgICAgc3BlY2lhbENhbGxiYWNrcyA9IHRoaXMuZ2V0V2lsZGNhcmRDYWxsYmFja3MoZXZlbnQpLFxyXG4gICAgICAgICAgICBpLFxyXG4gICAgICAgICAgICBsZW4sXHJcbiAgICAgICAgICAgIGl0ZW0sXHJcbiAgICAgICAgICAgIGxpc3RlbmVycztcclxuXHJcbiAgICAgICAgaWYgKGNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBjYWxsYmFja3Muc2xpY2UoKTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoc3BlY2lhbENhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBsZW4gPSBzcGVjaWFsQ2FsbGJhY2tzLmxlbmd0aDtcclxuICAgICAgICAgICAgbGlzdGVuZXJzID0gc3BlY2lhbENhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgW2V2ZW50XS5jb25jYXQoYXJncykpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gSGVscGVyIGZvciBmb3IgZmluZGluZyBzcGVjaWFsIHdpbGRjYXJkIGV2ZW50IGhhbmRsZXJzIHRoYXQgbWF0Y2ggdGhlIGV2ZW50XHJcbiAgICBwcm90b3R5cGUuZ2V0V2lsZGNhcmRDYWxsYmFja3MgPSBmdW5jdGlvbiAoZXZlbnROYW1lKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaXRlbSxcclxuICAgICAgICAgICAgc3BsaXQsXHJcbiAgICAgICAgICAgIHJlc3VsdCA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgc3BsaXQgPSBpdGVtLnNwbGl0KCcqJyk7XHJcbiAgICAgICAgICAgIGlmIChpdGVtID09PSAnKicgfHwgKHNwbGl0Lmxlbmd0aCA9PT0gMiAmJiBldmVudE5hbWUuc2xpY2UoMCwgc3BsaXRbMF0ubGVuZ3RoKSA9PT0gc3BsaXRbMF0pKSB7XHJcbiAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KHRoaXMuY2FsbGJhY2tzW2l0ZW1dKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfTtcclxuXHJcbn07XHJcblxyXG5XaWxkRW1pdHRlci5taXhpbihXaWxkRW1pdHRlcik7XHJcbiIsIi8qIVxuICogRXZlbnRFbWl0dGVyIHY1LjIuNCAtIGdpdC5pby9lZVxuICogVW5saWNlbnNlIC0gaHR0cDovL3VubGljZW5zZS5vcmcvXG4gKiBPbGl2ZXIgQ2FsZHdlbGwgLSBodHRwOi8vb2xpLm1lLnVrL1xuICogQHByZXNlcnZlXG4gKi9cblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuICAgICd1c2Ugc3RyaWN0JztcblxuICAgIC8qKlxuICAgICAqIENsYXNzIGZvciBtYW5hZ2luZyBldmVudHMuXG4gICAgICogQ2FuIGJlIGV4dGVuZGVkIHRvIHByb3ZpZGUgZXZlbnQgZnVuY3Rpb25hbGl0eSBpbiBvdGhlciBjbGFzc2VzLlxuICAgICAqXG4gICAgICogQGNsYXNzIEV2ZW50RW1pdHRlciBNYW5hZ2VzIGV2ZW50IHJlZ2lzdGVyaW5nIGFuZCBlbWl0dGluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7fVxuXG4gICAgLy8gU2hvcnRjdXRzIHRvIGltcHJvdmUgc3BlZWQgYW5kIHNpemVcbiAgICB2YXIgcHJvdG8gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlO1xuICAgIHZhciBvcmlnaW5hbEdsb2JhbFZhbHVlID0gZXhwb3J0cy5FdmVudEVtaXR0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyB0aGUgaW5kZXggb2YgdGhlIGxpc3RlbmVyIGZvciB0aGUgZXZlbnQgaW4gaXRzIHN0b3JhZ2UgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IGxpc3RlbmVycyBBcnJheSBvZiBsaXN0ZW5lcnMgdG8gc2VhcmNoIHRocm91Z2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGxvb2sgZm9yLlxuICAgICAqIEByZXR1cm4ge051bWJlcn0gSW5kZXggb2YgdGhlIHNwZWNpZmllZCBsaXN0ZW5lciwgLTEgaWYgbm90IGZvdW5kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVycywgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzW2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFsaWFzIGEgbWV0aG9kIHdoaWxlIGtlZXBpbmcgdGhlIGNvbnRleHQgY29ycmVjdCwgdG8gYWxsb3cgZm9yIG92ZXJ3cml0aW5nIG9mIHRhcmdldCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGFsaWFzZWQgbWV0aG9kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWxpYXMobmFtZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gYWxpYXNDbG9zdXJlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbbmFtZV0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBsaXN0ZW5lciBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaWxsIGluaXRpYWxpc2UgdGhlIGV2ZW50IG9iamVjdCBhbmQgbGlzdGVuZXIgYXJyYXlzIGlmIHJlcXVpcmVkLlxuICAgICAqIFdpbGwgcmV0dXJuIGFuIG9iamVjdCBpZiB5b3UgdXNlIGEgcmVnZXggc2VhcmNoLiBUaGUgb2JqZWN0IGNvbnRhaW5zIGtleXMgZm9yIGVhY2ggbWF0Y2hlZCBldmVudC4gU28gL2JhW3J6XS8gbWlnaHQgcmV0dXJuIGFuIG9iamVjdCBjb250YWluaW5nIGJhciBhbmQgYmF6LiBCdXQgb25seSBpZiB5b3UgaGF2ZSBlaXRoZXIgZGVmaW5lZCB0aGVtIHdpdGggZGVmaW5lRXZlbnQgb3IgYWRkZWQgc29tZSBsaXN0ZW5lcnMgdG8gdGhlbS5cbiAgICAgKiBFYWNoIHByb3BlcnR5IGluIHRoZSBvYmplY3QgcmVzcG9uc2UgaXMgYW4gYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfE9iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgdGhlIGV2ZW50LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldExpc3RlbmVycyhldnQpIHtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmV0dXJuIGEgY29uY2F0ZW5hdGVkIGFycmF5IG9mIGFsbCBtYXRjaGluZyBldmVudHMgaWZcbiAgICAgICAgLy8gdGhlIHNlbGVjdG9yIGlzIGEgcmVndWxhciBleHByZXNzaW9uLlxuICAgICAgICBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2Vba2V5XSA9IGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0gZXZlbnRzW2V2dF0gfHwgKGV2ZW50c1tldnRdID0gW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGxpc3Qgb2YgbGlzdGVuZXIgb2JqZWN0cyBhbmQgZmxhdHRlbnMgaXQgaW50byBhIGxpc3Qgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3RbXX0gbGlzdGVuZXJzIFJhdyBsaXN0ZW5lciBvYmplY3RzLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW119IEp1c3QgdGhlIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKi9cbiAgICBwcm90by5mbGF0dGVuTGlzdGVuZXJzID0gZnVuY3Rpb24gZmxhdHRlbkxpc3RlbmVycyhsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGZsYXRMaXN0ZW5lcnMgPSBbXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgZmxhdExpc3RlbmVycy5wdXNoKGxpc3RlbmVyc1tpXS5saXN0ZW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmxhdExpc3RlbmVycztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgcmVxdWVzdGVkIGxpc3RlbmVycyB2aWEgZ2V0TGlzdGVuZXJzIGJ1dCB3aWxsIGFsd2F5cyByZXR1cm4gdGhlIHJlc3VsdHMgaW5zaWRlIGFuIG9iamVjdC4gVGhpcyBpcyBtYWlubHkgZm9yIGludGVybmFsIHVzZSBidXQgb3RoZXJzIG1heSBmaW5kIGl0IHVzZWZ1bC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciBhbiBldmVudCBpbiBhbiBvYmplY3QuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzQXNPYmplY3QgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnNBc09iamVjdChldnQpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBpZiAobGlzdGVuZXJzIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICByZXNwb25zZVtldnRdID0gbGlzdGVuZXJzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlIHx8IGxpc3RlbmVycztcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gaXNWYWxpZExpc3RlbmVyIChsaXN0ZW5lcikge1xuICAgICAgICBpZiAodHlwZW9mIGxpc3RlbmVyID09PSAnZnVuY3Rpb24nIHx8IGxpc3RlbmVyIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9IGVsc2UgaWYgKGxpc3RlbmVyICYmIHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIubGlzdGVuZXIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBsaXN0ZW5lciBmdW5jdGlvbiB0byB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFRoZSBsaXN0ZW5lciB3aWxsIG5vdCBiZSBhZGRlZCBpZiBpdCBpcyBhIGR1cGxpY2F0ZS5cbiAgICAgKiBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGl0IGlzIGNhbGxlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSB0aGVuIHRoZSBsaXN0ZW5lciB3aWxsIGJlIGFkZGVkIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICghaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJJc1dyYXBwZWQgPSB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnB1c2gobGlzdGVuZXJJc1dyYXBwZWQgPyBsaXN0ZW5lciA6IHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgICAgICAgICBvbmNlOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZExpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub24gPSBhbGlhcygnYWRkTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIFNlbWktYWxpYXMgb2YgYWRkTGlzdGVuZXIuIEl0IHdpbGwgYWRkIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlXG4gICAgICogYXV0b21hdGljYWxseSByZW1vdmVkIGFmdGVyIGl0cyBmaXJzdCBleGVjdXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZE9uY2VMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZE9uY2VMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZExpc3RlbmVyKGV2dCwge1xuICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgb25jZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkT25jZUxpc3RlbmVyLlxuICAgICAqL1xuICAgIHByb3RvLm9uY2UgPSBhbGlhcygnYWRkT25jZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmVzIGFuIGV2ZW50IG5hbWUuIFRoaXMgaXMgcmVxdWlyZWQgaWYgeW91IHdhbnQgdG8gdXNlIGEgcmVnZXggdG8gYWRkIGEgbGlzdGVuZXIgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIElmIHlvdSBkb24ndCBkbyB0aGlzIHRoZW4gaG93IGRvIHlvdSBleHBlY3QgaXQgdG8ga25vdyB3aGF0IGV2ZW50IHRvIGFkZCB0bz8gU2hvdWxkIGl0IGp1c3QgYWRkIHRvIGV2ZXJ5IHBvc3NpYmxlIG1hdGNoIGZvciBhIHJlZ2V4PyBOby4gVGhhdCBpcyBzY2FyeSBhbmQgYmFkLlxuICAgICAqIFlvdSBuZWVkIHRvIHRlbGwgaXQgd2hhdCBldmVudCBuYW1lcyBzaG91bGQgYmUgbWF0Y2hlZCBieSBhIHJlZ2V4LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBjcmVhdGUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnQgPSBmdW5jdGlvbiBkZWZpbmVFdmVudChldnQpIHtcbiAgICAgICAgdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFVzZXMgZGVmaW5lRXZlbnQgdG8gZGVmaW5lIG11bHRpcGxlIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nW119IGV2dHMgQW4gYXJyYXkgb2YgZXZlbnQgbmFtZXMgdG8gZGVmaW5lLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50cyA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50cyhldnRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXZ0cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgdGhpcy5kZWZpbmVFdmVudChldnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIGZyb20gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaGVuIHBhc3NlZCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSwgaXQgd2lsbCByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byByZW1vdmUgZnJvbSB0aGUgZXZlbnQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBpbmRleDtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcik7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUxpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub2ZmID0gYWxpYXMoJ3JlbW92ZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBhZGQgdGhlIGFycmF5IG9mIGxpc3RlbmVycyB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICogWWVhaCwgdGhpcyBmdW5jdGlvbiBkb2VzIHF1aXRlIGEgYml0LiBUaGF0J3MgcHJvYmFibHkgYSBiYWQgdGhpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyhmYWxzZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byByZW1vdmUgdGhlIGxpc3RlbmVycyBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byByZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXJzID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnModHJ1ZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBFZGl0cyBsaXN0ZW5lcnMgaW4gYnVsay4gVGhlIGFkZExpc3RlbmVycyBhbmQgcmVtb3ZlTGlzdGVuZXJzIG1ldGhvZHMgYm90aCB1c2UgdGhpcyB0byBkbyB0aGVpciBqb2IuIFlvdSBzaG91bGQgcmVhbGx5IHVzZSB0aG9zZSBpbnN0ZWFkLCB0aGlzIGlzIGEgbGl0dGxlIGxvd2VyIGxldmVsLlxuICAgICAqIFRoZSBmaXJzdCBhcmd1bWVudCB3aWxsIGRldGVybWluZSBpZiB0aGUgbGlzdGVuZXJzIGFyZSByZW1vdmVkICh0cnVlKSBvciBhZGRlZCAoZmFsc2UpLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHlvdSBjYW4gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkL3JlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gbWFuaXB1bGF0ZSB0aGUgbGlzdGVuZXJzIG9mIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVtb3ZlIFRydWUgaWYgeW91IHdhbnQgdG8gcmVtb3ZlIGxpc3RlbmVycywgZmFsc2UgaWYgeW91IHdhbnQgdG8gYWRkLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkL3JlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5tYW5pcHVsYXRlTGlzdGVuZXJzID0gZnVuY3Rpb24gbWFuaXB1bGF0ZUxpc3RlbmVycyhyZW1vdmUsIGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgdmFsdWU7XG4gICAgICAgIHZhciBzaW5nbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVyIDogdGhpcy5hZGRMaXN0ZW5lcjtcbiAgICAgICAgdmFyIG11bHRpcGxlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lcnMgOiB0aGlzLmFkZExpc3RlbmVycztcblxuICAgICAgICAvLyBJZiBldnQgaXMgYW4gb2JqZWN0IHRoZW4gcGFzcyBlYWNoIG9mIGl0cyBwcm9wZXJ0aWVzIHRvIHRoaXMgbWV0aG9kXG4gICAgICAgIGlmICh0eXBlb2YgZXZ0ID09PSAnb2JqZWN0JyAmJiAhKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgICAgICAgIGZvciAoaSBpbiBldnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZ0Lmhhc093blByb3BlcnR5KGkpICYmICh2YWx1ZSA9IGV2dFtpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGFzcyB0aGUgc2luZ2xlIGxpc3RlbmVyIHN0cmFpZ2h0IHRocm91Z2ggdG8gdGhlIHNpbmd1bGFyIG1ldGhvZFxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgcGFzcyBiYWNrIHRvIHRoZSBtdWx0aXBsZSBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBTbyBldnQgbXVzdCBiZSBhIHN0cmluZ1xuICAgICAgICAgICAgLy8gQW5kIGxpc3RlbmVycyBtdXN0IGJlIGFuIGFycmF5IG9mIGxpc3RlbmVyc1xuICAgICAgICAgICAgLy8gTG9vcCBvdmVyIGl0IGFuZCBwYXNzIGVhY2ggb25lIHRvIHRoZSBtdWx0aXBsZSBtZXRob2RcbiAgICAgICAgICAgIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGV2dCwgbGlzdGVuZXJzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgZnJvbSBhIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBJZiB5b3UgZG8gbm90IHNwZWNpZnkgYW4gZXZlbnQgdGhlbiBhbGwgbGlzdGVuZXJzIHdpbGwgYmUgcmVtb3ZlZC5cbiAgICAgKiBUaGF0IG1lYW5zIGV2ZXJ5IGV2ZW50IHdpbGwgYmUgZW1wdGllZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ2V4IHRvIHJlbW92ZSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IFtldnRdIE9wdGlvbmFsIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvci4gV2lsbCByZW1vdmUgZnJvbSBldmVyeSBldmVudCBpZiBub3QgcGFzc2VkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24gcmVtb3ZlRXZlbnQoZXZ0KSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mIGV2dDtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJlbW92ZSBkaWZmZXJlbnQgdGhpbmdzIGRlcGVuZGluZyBvbiB0aGUgc3RhdGUgb2YgZXZ0XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbZXZ0XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgZXZlbnRzIG1hdGNoaW5nIHRoZSByZWdleC5cbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBpbiBhbGwgZXZlbnRzXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUV2ZW50LlxuICAgICAqXG4gICAgICogQWRkZWQgdG8gbWlycm9yIHRoZSBub2RlIEFQSS5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBhbGlhcygncmVtb3ZlRXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGFuIGV2ZW50IG9mIHlvdXIgY2hvaWNlLlxuICAgICAqIFdoZW4gZW1pdHRlZCwgZXZlcnkgbGlzdGVuZXIgYXR0YWNoZWQgdG8gdGhhdCBldmVudCB3aWxsIGJlIGV4ZWN1dGVkLlxuICAgICAqIElmIHlvdSBwYXNzIHRoZSBvcHRpb25hbCBhcmd1bWVudCBhcnJheSB0aGVuIHRob3NlIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCB0byBldmVyeSBsaXN0ZW5lciB1cG9uIGV4ZWN1dGlvbi5cbiAgICAgKiBCZWNhdXNlIGl0IHVzZXMgYGFwcGx5YCwgeW91ciBhcnJheSBvZiBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgYXMgaWYgeW91IHdyb3RlIHRoZW0gb3V0IHNlcGFyYXRlbHkuXG4gICAgICogU28gdGhleSB3aWxsIG5vdCBhcnJpdmUgd2l0aGluIHRoZSBhcnJheSBvbiB0aGUgb3RoZXIgc2lkZSwgdGhleSB3aWxsIGJlIHNlcGFyYXRlLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthcmdzXSBPcHRpb25hbCBhcnJheSBvZiBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdEV2ZW50ID0gZnVuY3Rpb24gZW1pdEV2ZW50KGV2dCwgYXJncykge1xuICAgICAgICB2YXIgbGlzdGVuZXJzTWFwID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJzO1xuICAgICAgICB2YXIgbGlzdGVuZXI7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzTWFwKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzTWFwLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnNNYXBba2V5XS5zbGljZSgwKTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHNoYWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkIGVpdGhlciB3aXRoIGEgYmFzaWMgY2FsbCBvciBhbiBhcHBseSBpZiB0aGVyZSBpcyBhbiBhcmdzIGFycmF5XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChsaXN0ZW5lci5vbmNlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBsaXN0ZW5lci5saXN0ZW5lci5hcHBseSh0aGlzLCBhcmdzIHx8IFtdKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgPT09IHRoaXMuX2dldE9uY2VSZXR1cm5WYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGVtaXRFdmVudFxuICAgICAqL1xuICAgIHByb3RvLnRyaWdnZXIgPSBhbGlhcygnZW1pdEV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBTdWJ0bHkgZGlmZmVyZW50IGZyb20gZW1pdEV2ZW50IGluIHRoYXQgaXQgd2lsbCBwYXNzIGl0cyBhcmd1bWVudHMgb24gdG8gdGhlIGxpc3RlbmVycywgYXMgb3Bwb3NlZCB0byB0YWtpbmcgYSBzaW5nbGUgYXJyYXkgb2YgYXJndW1lbnRzIHRvIHBhc3Mgb24uXG4gICAgICogQXMgd2l0aCBlbWl0RXZlbnQsIHlvdSBjYW4gcGFzcyBhIHJlZ2V4IGluIHBsYWNlIG9mIHRoZSBldmVudCBuYW1lIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gT3B0aW9uYWwgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdCA9IGZ1bmN0aW9uIGVtaXQoZXZ0KSB7XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW1pdEV2ZW50KGV2dCwgYXJncyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmIGFcbiAgICAgKiBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhlIG9uZSBzZXQgaGVyZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZFxuICAgICAqIGFmdGVyIGV4ZWN1dGlvbi4gVGhpcyB2YWx1ZSBkZWZhdWx0cyB0byB0cnVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbmV3IHZhbHVlIHRvIGNoZWNrIGZvciB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uc2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gc2V0T25jZVJldHVyblZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX29uY2VSZXR1cm5WYWx1ZSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWZcbiAgICAgKiB0aGUgbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoaXMgb25lIHRoZW4gaXQgc2hvdWxkIGJlIHJlbW92ZWRcbiAgICAgKiBhdXRvbWF0aWNhbGx5LiBJdCB3aWxsIHJldHVybiB0cnVlIGJ5IGRlZmF1bHQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHsqfEJvb2xlYW59IFRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGZvciBvciB0aGUgZGVmYXVsdCwgdHJ1ZS5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gX2dldE9uY2VSZXR1cm5WYWx1ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkoJ19vbmNlUmV0dXJuVmFsdWUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29uY2VSZXR1cm5WYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGV2ZW50cyBvYmplY3QgYW5kIGNyZWF0ZXMgb25lIGlmIHJlcXVpcmVkLlxuICAgICAqXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgZXZlbnRzIHN0b3JhZ2Ugb2JqZWN0LlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRFdmVudHMgPSBmdW5jdGlvbiBfZ2V0RXZlbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXZlbnRzIHx8ICh0aGlzLl9ldmVudHMgPSB7fSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJldmVydHMgdGhlIGdsb2JhbCB7QGxpbmsgRXZlbnRFbWl0dGVyfSB0byBpdHMgcHJldmlvdXMgdmFsdWUgYW5kIHJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhpcyB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IE5vbiBjb25mbGljdGluZyBFdmVudEVtaXR0ZXIgY2xhc3MuXG4gICAgICovXG4gICAgRXZlbnRFbWl0dGVyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiBub0NvbmZsaWN0KCkge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IG9yaWdpbmFsR2xvYmFsVmFsdWU7XG4gICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgfTtcblxuICAgIC8vIEV4cG9zZSB0aGUgY2xhc3MgZWl0aGVyIHZpYSBBTUQsIENvbW1vbkpTIG9yIHRoZSBnbG9iYWwgb2JqZWN0XG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKXtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG59KHRoaXMgfHwge30pKTtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdS9PcGVuVmlkdSc7XG5cbmlmICh3aW5kb3cpIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICB3aW5kb3dbJ09wZW5WaWR1J10gPSBPcGVuVmlkdTtcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmRlYnVnKCghIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCcgOiAnUmVtb3RlJyksICdjYW5kaWRhdGUgZm9yJyxcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkLCBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcblxuICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ29uSWNlQ2FuZGlkYXRlJywge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJ1xuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0UmVtb3RlU3RyZWFtcyhvcHRpb25zOiBTdHJlYW1PcHRpb25zU2VydmVyW10pOiB2b2lkIHtcblxuICAgICAgICAvLyBUaGlzIGlzIHJlYWR5IGZvciBzdXBwb3J0aW5nIG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb24gb2JqZWN0LiBSaWdodCBub3cgdGhlIGxvb3Agd2lsbCBhbHdheXMgcnVuIGp1c3Qgb25jZVxuICAgICAgICAvLyB0aGlzLnN0cmVhbSBzaG91bGQgYWxzbyBiZSByZXBsYWNlZCBieSBhIGNvbGxlY3Rpb24gb2Ygc3RyZWFtcyB0byBzdXBwb3J0IG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb25cbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IG9wdHMuaWQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogdGhpcyxcbiAgICAgICAgICAgICAgICBmcmFtZVJhdGU6IG9wdHMuZnJhbWVSYXRlLFxuICAgICAgICAgICAgICAgIHJlY3ZBdWRpbzogb3B0cy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICByZWN2VmlkZW86IG9wdHMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyZWFtKHRoaXMuc2Vzc2lvbiwgc3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgIHRoaXMuYWRkU3RyZWFtKHN0cmVhbSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnQ29ubmVjdGlvbicgd2l0aCAnY29ubmVjdGlvbklkJyBbXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArICddIGlzIG5vdyBjb25maWd1cmVkIGZvciByZWNlaXZpbmcgU3RyZWFtcyB3aXRoIG9wdGlvbnM6ICcsIHRoaXMuc3RyZWFtLmluYm91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkU3RyZWFtKHN0cmVhbTogU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5jb25uZWN0aW9uID0gdGhpcztcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZVN0cmVhbShzdHJlYW1JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IExvY2FsUmVjb3JkZXJTdGF0ZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmRlY2xhcmUgdmFyIE1lZGlhUmVjb3JkZXI6IGFueTtcblxuXG4vKipcbiAqIEVhc3kgcmVjb3JkaW5nIG9mIFtbU3RyZWFtXV0gb2JqZWN0cyBzdHJhaWdodGF3YXkgZnJvbSB0aGUgYnJvd3Nlci5cbiAqXG4gKiA+IFdBUk5JTkc6IFBlcmZvcm1pbmcgYnJvd3NlciBsb2NhbCByZWNvcmRpbmcgb2YgKipyZW1vdGUgc3RyZWFtcyoqIG1heSBjYXVzZSBzb21lIHRyb3VibGVzLiBBIGxvbmcgd2FpdGluZyB0aW1lIG1heSBiZSByZXF1aXJlZCBhZnRlciBjYWxsaW5nIF9Mb2NhbFJlY29yZGVyLnN0b3AoKV8gaW4gdGhpcyBjYXNlXG4gKi9cbmV4cG9ydCBjbGFzcyBMb2NhbFJlY29yZGVyIHtcblxuICAgIHN0YXRlOiBMb2NhbFJlY29yZGVyU3RhdGU7XG5cbiAgICBwcml2YXRlIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuICAgIHByaXZhdGUgbWVkaWFSZWNvcmRlcjogYW55O1xuICAgIHByaXZhdGUgY2h1bmtzOiBhbnlbXSA9IFtdO1xuICAgIHByaXZhdGUgYmxvYjogQmxvYjtcbiAgICBwcml2YXRlIGNvdW50ID0gMDtcbiAgICBwcml2YXRlIGlkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXdTcmM6IHN0cmluZztcbiAgICBwcml2YXRlIGh0bWxQYXJlbnRFbGVtZW50SWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlldzogSFRNTFZpZGVvRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gKCEhdGhpcy5zdHJlYW0uY29ubmVjdGlvbikgPyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA6ICdkZWZhdWx0LWNvbm5lY3Rpb24nO1xuICAgICAgICB0aGlzLmlkID0gdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXycgKyB0aGlzLmNvbm5lY3Rpb25JZCArICdfbG9jYWxyZWNvcmQnO1xuICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU3RhcnRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQURZYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdGFydGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZWNvcmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdHJ5IHtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlY29yZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQURZXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuY2xlYW4oKVxcJyBvciBpbml0IGEgbmV3IExvY2FsUmVjb3JkZXIgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIlN0YXJ0aW5nIGxvY2FsIHJlY29yZGluZyBvZiBzdHJlYW0gJ1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyBcIicgb2YgY29ubmVjdGlvbiAnXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArIFwiJ1wiKTtcblxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgb3B0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDknKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz12cDknIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JyB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDgnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz12cDgnIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1VzaW5nIG1pbWVUeXBlICcgKyBvcHRpb25zLm1pbWVUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIodGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdpc1R5cGVTdXBwb3J0ZWQgaXMgbm90IHN1cHBvcnRlZCwgdXNpbmcgZGVmYXVsdCBjb2RlY3MgZm9yIGJyb3dzZXInKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIodGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXJ0KDEwKTtcblxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmRhdGFhdmFpbGFibGUgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY2h1bmtzLnB1c2goZS5kYXRhKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmVycm9yID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIGVycm9yOiAnLCBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0YXJ0ID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0YXJ0ZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnBhdXNlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHBhdXNlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25yZXN1bWUgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcmVzdW1lZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub253YXJuaW5nID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciB3YXJuaW5nOiAnICsgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIHJlc29sdmUoKTtcblxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEVuZHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYCBvciBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgRklOSVNIRURgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0b3BwZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHN0b3AoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIG9yIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0b3AoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUGF1c2VzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2AuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFBBVVNFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyB3YXMgc3VjY2Vzc2Z1bGx5IHBhdXNlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcGF1c2UoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC5wYXVzZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgb3IgXFwnTG9jYWxSZWNvcmRlci5yZXN1bWUoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5wYXVzZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXN1bWVzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFBBVVNFRGAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyB3YXMgc3VjY2Vzc2Z1bGx5IHJlc3VtZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlc3VtZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlc3VtZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnBhdXNlKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucmVzdW1lKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHJldmlld3MgdGhlIHJlY29yZGluZywgYXBwZW5kaW5nIGEgbmV3IEhUTUxWaWRlb0VsZW1lbnQgdG8gZWxlbWVudCB3aXRoIGlkIGBwYXJlbnRJZGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBwcmV2aWV3KHBhcmVudEVsZW1lbnQpOiBIVE1MVmlkZW9FbGVtZW50IHtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnByZXZpZXcoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuaWQgPSB0aGlzLmlkO1xuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5hdXRvcGxheSA9IHRydWU7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBwYXJlbnRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhpcy5odG1sUGFyZW50RWxlbWVudElkID0gcGFyZW50RWxlbWVudDtcblxuICAgICAgICAgICAgY29uc3QgcGFyZW50RWxlbWVudERvbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBhcmVudEVsZW1lbnQpO1xuICAgICAgICAgICAgaWYgKHBhcmVudEVsZW1lbnREb20pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnREb20uYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5odG1sUGFyZW50RWxlbWVudElkID0gcGFyZW50RWxlbWVudC5pZDtcbiAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5zcmMgPSB0aGlzLnZpZGVvUHJldmlld1NyYztcblxuICAgICAgICByZXR1cm4gdGhpcy52aWRlb1ByZXZpZXc7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBHcmFjZWZ1bGx5IHN0b3BzIGFuZCBjbGVhbnMgdGhlIGN1cnJlbnQgcmVjb3JkaW5nIChXQVJOSU5HOiBpdCBpcyBjb21wbGV0ZWx5IGRpc21pc3NlZCkuIFNldHMgW1tzdGF0ZV1dIHRvIGBSRUFEWWAgc28gdGhlIHJlY29yZGluZyBjYW4gc3RhcnQgYWdhaW5cbiAgICAgKi9cbiAgICBjbGVhbigpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZiA9ICgpID0+IHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmJsb2I7XG4gICAgICAgICAgICB0aGlzLmNodW5rcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IDA7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tZWRpYVJlY29yZGVyO1xuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkcgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgdGhpcy5zdG9wKCkudGhlbigoKSA9PiBmKCkpLmNhdGNoKCgpID0+IGYoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIERvd25sb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gdGhyb3VnaCB0aGUgYnJvd3Nlci4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIGRvd25sb2FkKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLmRvd25sb2FkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgYTogSFRNTEFuY2hvckVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICAgICAgICBhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xuXG4gICAgICAgICAgICBjb25zdCB1cmwgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgYS5ocmVmID0gdXJsO1xuICAgICAgICAgICAgYS5kb3dubG9hZCA9IHRoaXMuaWQgKyAnLndlYm0nO1xuICAgICAgICAgICAgYS5jbGljaygpO1xuICAgICAgICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcblxuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHJhdyBCbG9iIGZpbGUuIE1ldGhvZHMgcHJldmlldywgZG93bmxvYWQsIHVwbG9hZEFzQmluYXJ5IGFuZCB1cGxvYWRBc011bHRpcGFydGZpbGUgdXNlIHRoaXMgc2FtZSBmaWxlIHRvIHBlcmZvcm0gdGhlaXIgc3BlY2lmaWMgYWN0aW9ucy4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIGdldEJsb2IoKTogQmxvYiB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignQ2FsbCBcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgYmVmb3JlIGdldHRpbmcgQmxvYiBmaWxlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmxvYjtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBsb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gYXMgYSBiaW5hcnkgZmlsZSBwZXJmb3JtaW5nIGFuIEhUVFAvUE9TVCBvcGVyYXRpb24gdG8gVVJMIGBlbmRwb2ludGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGAuIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBjYW4gYmUgcGFzc2VkIGFzIHNlY29uZCBwYXJhbWV0ZXIuIEZvciBleGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHZhciBoZWFkZXJzID0ge1xuICAgICAqICBcIkNvb2tpZVwiOiBcIiRWZXJzaW9uPTE7IFNraW49bmV3O1wiLFxuICAgICAqICBcIkF1dGhvcml6YXRpb25cIjpcIkJhc2ljIFFXeGhaR3BianB1SUhObGN0WlE9PVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB3aXRoIHRoZSBgaHR0cC5yZXNwb25zZVRleHRgIGZyb20gc2VydmVyIGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggdGhlIGZhaWxlZCBgaHR0cC5zdGF0dXNgIGlmIG5vdFxuICAgICAqL1xuICAgIHVwbG9hZEFzQmluYXJ5KGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNCaW5hcnkoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoaHR0cC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBodHRwLnNlbmQodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIG11bHRpcGFydCBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90OlxuICAgICAqL1xuICAgIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzZW5kYWJsZSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgICAgIHNlbmRhYmxlLmFwcGVuZCgnZmlsZScsIHRoaXMuYmxvYiwgdGhpcy5pZCArICcud2VibScpO1xuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoaHR0cC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGh0dHAuc2VuZChzZW5kYWJsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIG9uU3RvcERlZmF1bHQoKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0b3BwZWQgIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcblxuICAgICAgICB0aGlzLmJsb2IgPSBuZXcgQmxvYih0aGlzLmNodW5rcywgeyB0eXBlOiAndmlkZW8vd2VibScgfSk7XG4gICAgICAgIHRoaXMuY2h1bmtzID0gW107XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXdTcmMgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTCh0aGlzLmJsb2IpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQ7XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IExvY2FsUmVjb3JkZXIgfSBmcm9tICcuL0xvY2FsUmVjb3JkZXInO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBEZXZpY2UgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0RldmljZSc7XG5pbXBvcnQgeyBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IHsgUHVibGlzaGVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvUHVibGlzaGVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmdBdXRvIGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8nO1xuaW1wb3J0ICogYXMgc2NyZWVuU2hhcmluZyBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZyc7XG5cbmltcG9ydCBScGNCdWlsZGVyID0gcmVxdWlyZSgnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbi8qKlxuICogRW50cnlwb2ludCBvZiBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKiBVc2UgaXQgdG8gaW5pdGlhbGl6ZSBvYmplY3RzIG9mIHR5cGUgW1tTZXNzaW9uXV0sIFtbUHVibGlzaGVyXV0gYW5kIFtbTG9jYWxSZWNvcmRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgcHJpdmF0ZSBqc29uUnBjQ2xpZW50OiBhbnk7XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlc3Npb246IFNlc3Npb247XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICB3c1VyaTogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VjcmV0ID0gJyc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByZWNvcmRlciA9IGZhbHNlO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaWNlU2VydmVyczogUlRDSWNlU2VydmVyW107XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByb2xlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBhZHZhbmNlZENvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uID0ge307XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgY29uc29sZS5pbmZvKFwiJ09wZW5WaWR1JyBpbml0aWFsaXplZFwiKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgbmV3IHNlc3Npb25cbiAgICovXG4gIGluaXRTZXNzaW9uKCk6IFNlc3Npb24ge1xuICAgIHRoaXMuc2Vzc2lvbiA9IG5ldyBTZXNzaW9uKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnNlc3Npb247XG4gIH1cblxuXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcblxuICAvKipcbiAgICogUmV0dXJucyBhIG5ldyBwdWJsaXNoZXJcbiAgICpcbiAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzRGlhbG9nT3BlbmVkYCBldmVudCwgb25seSBpZiB0aGUgcG9wLXVwIHNob3duIGJ5IHRoZSBicm93c2VyIHRvIHJlcXVlc3QgcGVybWlzc2lvbnMgZm9yIHRoZSBjYW1lcmEgaXMgb3BlbmVkLiBZb3UgY2FuIHVzZSB0aGlzIGV2ZW50IHRvIGFsZXJ0IHRoZSB1c2VyIGFib3V0IGdyYW50aW5nIHBlcm1pc3Npb25zXG4gICAqIGZvciB5b3VyIHdlYnNpdGUuIEFuIGBhY2Nlc3NEaWFsb2dDbG9zZWRgIGV2ZW50IHdpbGwgYWxzbyBiZSBkaXNwYXRjaGVkIGFmdGVyIHVzZXIgY2xpY2tzIG9uIFwiQWxsb3dcIiBvciBcIkJsb2NrXCIgaW4gdGhlIHBvcC11cC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGBhY2Nlc3NEZW5pZWRgIGV2ZW50IG9uY2UgaXQgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSBhIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2AgZXZlbnQgb25jZSB0aGUgbG9jYWwgc3RyZWFtcyBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgIEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSkuIElmICpudWxsKiBvciAqdW5kZWZpbmVkKiBubyBkZWZhdWx0IHZpZGVvIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBQdWJsaXNoZXIuXG4gICAqIFlvdSBjYW4gYWx3YXlzIGNhbGwgbWV0aG9kIFtbUHVibGlzaGVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24pXG4gICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBpbml0UHVibGlzaGVyYCBzdWNjZWVkcywgYW5kIGlzIGRlZmluZWQgaWYgaXQgZmFpbHMuXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICBgY29tcGxldGlvbkhhbmRsZXJgIGZ1bmN0aW9uIGlzIGNhbGxlZCBiZWZvcmUgdGhlIFB1Ymxpc2hlciBkaXNwYXRjaGVzIGFuIGBhY2Nlc3NBbGxvd2VkYCBvciBhbiBgYWNjZXNzRGVuaWVkYCBldmVudFxuICAgKi9cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcGFyYW0yPywgcGFyYW0zPyk6IFB1Ymxpc2hlciB7XG5cbiAgICBsZXQgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcztcblxuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiAhPT0gJ2Z1bmN0aW9uJykpIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzKScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0gKDxQdWJsaXNoZXJQcm9wZXJ0aWVzPnBhcmFtMik7XG5cbiAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGF1ZGlvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgOiB1bmRlZmluZWQsXG4gICAgICAgIGZyYW1lUmF0ZTogdGhpcy5pc01lZGlhU3RyZWFtVHJhY2socHJvcGVydGllcy52aWRlb1NvdXJjZSkgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5mcmFtZVJhdGUgOiB1bmRlZmluZWQpLFxuICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSAhPT0gJ3VuZGVmaW5lZCcpID8gKCh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlID09PSAnc3RyaW5nJykgPyBWaWRlb0luc2VydE1vZGVbcHJvcGVydGllcy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6ICh0eXBlb2YgcHJvcGVydGllcy5taXJyb3IgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMubWlycm9yIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaEF1ZGlvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaEF1ZGlvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMucmVzb2x1dGlvbiAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5yZXNvbHV0aW9uIDogJzY0MHg0ODAnKSxcbiAgICAgICAgdmlkZW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy52aWRlb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy52aWRlb1NvdXJjZSA6IHVuZGVmaW5lZFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogdHJ1ZSxcbiAgICAgICAgcHVibGlzaEF1ZGlvOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246ICc2NDB4NDgwJ1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBwdWJsaXNoZXI6IFB1Ymxpc2hlciA9IG5ldyBQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgdGhpcyk7XG5cbiAgICBsZXQgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTI7XG4gICAgfSBlbHNlIGlmICghIXBhcmFtMykge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTM7XG4gICAgfVxuXG4gICAgcHVibGlzaGVyLmluaXRpYWxpemUoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzQWxsb3dlZCcsIFtdKTtcbiAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnLCBbXSk7XG4gICAgICB9KTtcblxuICAgIHJldHVybiBwdWJsaXNoZXI7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBQcm9taXNpZmllZCB2ZXJzaW9uIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqXG4gICAqID4gV0FSTklORzogZXZlbnRzIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGFuZCBgYWNjZXNzRGlhbG9nQ2xvc2VkYCB3aWxsIG5vdCBiZSBkaXNwYXRjaGVkIGlmIHVzaW5nIHRoaXMgbWV0aG9kIGluc3RlYWQgb2YgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICovXG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFByb21pc2U8UHVibGlzaGVyPjtcbiAgaW5pdFB1Ymxpc2hlckFzeW5jKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+O1xuXG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQcm9taXNlPFB1Ymxpc2hlcj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxQdWJsaXNoZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgbGV0IHB1Ymxpc2hlcjogUHVibGlzaGVyO1xuXG4gICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUocHVibGlzaGVyKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICBwdWJsaXNoZXIgPSB0aGlzLmluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgbG9jYWwgcmVjb3JkZXIgZm9yIHJlY29yZGluZyBzdHJlYW1zIHN0cmFpZ2h0IGF3YXkgZnJvbSB0aGUgYnJvd3NlclxuICAgKiBAcGFyYW0gc3RyZWFtICBTdHJlYW0gdG8gcmVjb3JkXG4gICAqL1xuICBpbml0TG9jYWxSZWNvcmRlcihzdHJlYW06IFN0cmVhbSk6IExvY2FsUmVjb3JkZXIge1xuICAgIHJldHVybiBuZXcgTG9jYWxSZWNvcmRlcihzdHJlYW0pO1xuICB9XG5cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1XG4gICAqIEByZXR1cm5zIDEgaWYgdGhlIGJyb3dzZXIgc3VwcG9ydHMgT3BlblZpZHUsIDAgb3RoZXJ3aXNlXG4gICAqL1xuICBjaGVja1N5c3RlbVJlcXVpcmVtZW50cygpOiBudW1iZXIge1xuICAgIGNvbnN0IGJyb3dzZXIgPSBwbGF0Zm9ybS5uYW1lO1xuICAgIGNvbnN0IHZlcnNpb24gPSBwbGF0Zm9ybS52ZXJzaW9uO1xuXG4gICAgaWYgKChicm93c2VyICE9PSAnQ2hyb21lJykgJiYgKGJyb3dzZXIgIT09ICdDaHJvbWUgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnRmlyZWZveCcpICYmIChicm93c2VyICE9PSAnRmlyZWZveCBNb2JpbGUnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggZm9yIGlPUycpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ09wZXJhJykgJiYgKGJyb3dzZXIgIT09ICdPcGVyYSBNb2JpbGUnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdTYWZhcmknKSkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIENvbGxlY3RzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtZWRpYSBpbnB1dCBkZXZpY2VzIGF2YWlsYWJsZSBvbiB0aGUgc3lzdGVtLiBZb3UgY2FuIHBhc3MgcHJvcGVydHkgYGRldmljZUlkYCBvZiBhIFtbRGV2aWNlXV0gb2JqZWN0IGFzIHZhbHVlIG9mIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgKi9cbiAgZ2V0RGV2aWNlcygpOiBQcm9taXNlPERldmljZVtdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPERldmljZVtdPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKS50aGVuKChkZXZpY2VJbmZvcykgPT4ge1xuICAgICAgICBjb25zdCBkZXZpY2VzOiBEZXZpY2VbXSA9IFtdO1xuICAgICAgICBkZXZpY2VJbmZvcy5mb3JFYWNoKGRldmljZUluZm8gPT4ge1xuICAgICAgICAgIGlmIChkZXZpY2VJbmZvLmtpbmQgPT09ICdhdWRpb2lucHV0JyB8fCBkZXZpY2VJbmZvLmtpbmQgPT09ICd2aWRlb2lucHV0Jykge1xuICAgICAgICAgICAgZGV2aWNlcy5wdXNoKHtcbiAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICBkZXZpY2VJZDogZGV2aWNlSW5mby5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgbGFiZWw6IGRldmljZUluZm8ubGFiZWxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc29sdmUoZGV2aWNlcyk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZ2V0dGluZyBkZXZpY2VzJywgZXJyb3IpO1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBHZXQgYSBNZWRpYVN0cmVhbSBvYmplY3QgdGhhdCB5b3UgY2FuIGN1c3RvbWl6ZSBiZWZvcmUgY2FsbGluZyBbW2luaXRQdWJsaXNoZXJdXSAocGFzcyBfTWVkaWFTdHJlYW1UcmFja18gcHJvcGVydHkgb2YgdGhlIF9NZWRpYVN0cmVhbV8gdmFsdWUgcmVzb2x2ZWQgYnkgdGhlIFByb21pc2UgYXMgYGF1ZGlvU291cmNlYCBvciBgdmlkZW9Tb3VyY2VgIHByb3BlcnRpZXMgaW4gW1tpbml0UHVibGlzaGVyXV0pXG4gICAqXG4gICAqIFBhcmFtZXRlciBgb3B0aW9uc2AgaXMgdGhlIHNhbWUgYXMgaW4gW1tpbml0UHVibGlzaGVyXV0gc2Vjb25kIHBhcmFtZXRlciAob2YgdHlwZSBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSksIGJ1dCBvbmx5IHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyB3aWxsIGJlIGFwcGxpZWQ6IGBhdWRpb1NvdXJjZWAsIGB2aWRlb1NvdXJjZWAsIGBmcmFtZVJhdGVgLCBgcmVzb2x1dGlvbmBcbiAgICpcbiAgICogVG8gY3VzdG9taXplIHRoZSBQdWJsaXNoZXIncyB2aWRlbywgdGhlIEFQSSBmb3IgSFRNTENhbnZhc0VsZW1lbnQgaXMgdmVyeSB1c2VmdWwuIEZvciBleGFtcGxlLCB0byBnZXQgYSBibGFjay1hbmQtd2hpdGUgdmlkZW8gYXQgMTAgZnBzIGFuZCBIRCByZXNvbHV0aW9uIHdpdGggbm8gc291bmQ6XG4gICAqIGBgYFxuICAgKiB2YXIgT1YgPSBuZXcgT3BlblZpZHUoKTtcbiAgICogdmFyIEZSQU1FX1JBVEUgPSAxMDtcbiAgICpcbiAgICogT1YuZ2V0VXNlck1lZGlhKHtcbiAgICogICAgYXVkaW9Tb3VyY2U6IGZhbHNlO1xuICAgKiAgICB2aWRlb1NvdXJjZTogdW5kZWZpbmVkLFxuICAgKiAgICByZXNvbHV0aW9uOiAnMTI4MHg3MjAnLFxuICAgKiAgICBmcmFtZVJhdGU6IEZSQU1FX1JBVEVcbiAgICogfSlcbiAgICogLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgKlxuICAgKiAgICB2YXIgdmlkZW9UcmFjayA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAqICAgIHZpZGVvLnNyY09iamVjdCA9IG5ldyBNZWRpYVN0cmVhbShbdmlkZW9UcmFja10pO1xuICAgKlxuICAgKiAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAqICAgIHZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICogICAgY3R4LmZpbHRlciA9ICdncmF5c2NhbGUoMTAwJSknO1xuICAgKlxuICAgKiAgICB2aWRlby5hZGRFdmVudExpc3RlbmVyKCdwbGF5JywgKCkgPT4ge1xuICAgKiAgICAgIHZhciBsb29wID0gKCkgPT4ge1xuICAgKiAgICAgICAgaWYgKCF2aWRlby5wYXVzZWQgJiYgIXZpZGVvLmVuZGVkKSB7XG4gICAqICAgICAgICAgIGN0eC5kcmF3SW1hZ2UodmlkZW8sIDAsIDAsIDMwMCwgMTcwKTtcbiAgICogICAgICAgICAgc2V0VGltZW91dChsb29wLCAxMDAwLyBGUkFNRV9SQVRFKTsgLy8gRHJhd2luZyBhdCAxMCBmcHNcbiAgICogICAgICAgIH1cbiAgICogICAgICB9O1xuICAgKiAgICAgIGxvb3AoKTtcbiAgICogICAgfSk7XG4gICAqICAgIHZpZGVvLnBsYXkoKTtcbiAgICpcbiAgICogICAgdmFyIGdyYXlWaWRlb1RyYWNrID0gY2FudmFzLmNhcHR1cmVTdHJlYW0oRlJBTUVfUkFURSkuZ2V0VmlkZW9UcmFja3MoKVswXTtcbiAgICogICAgdmFyIHB1Ymxpc2hlciA9IHRoaXMuT1YuaW5pdFB1Ymxpc2hlcihcbiAgICogICAgICBteUh0bWxUYXJnZXQsXG4gICAqICAgICAge1xuICAgKiAgICAgICAgYXVkaW9Tb3VyY2U6IGZhbHNlLFxuICAgKiAgICAgICAgdmlkZW9Tb3VyY2U6IGdyYXlWaWRlb1RyYWNrXG4gICAqICAgICAgfSk7XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGdldFVzZXJNZWRpYShvcHRpb25zOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxNZWRpYVN0cmVhbT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5nZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMob3B0aW9ucylcbiAgICAgICAgLnRoZW4oY29uc3RyYWludHMgPT4ge1xuICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKVxuICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICBsZXQgZXJyb3JOYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKCEob3B0aW9ucy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbicpKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoZXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG5cbiAgLyogdHNsaW50OmRpc2FibGU6bm8tZW1wdHkgKi9cbiAgLyoqXG4gICAqIERpc2FibGUgYWxsIGxvZ2dpbmcgZXhjZXB0IGVycm9yIGxldmVsXG4gICAqL1xuICBlbmFibGVQcm9kTW9kZSgpOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmRlYnVnID0gKCkgPT4geyB9O1xuICAgIGNvbnNvbGUuaW5mbyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLndhcm4gPSAoKSA9PiB7IH07XG4gIH1cbiAgLyogdHNsaW50OmVuYWJsZTpuby1lbXB0eSAqL1xuXG5cbiAgLyoqXG4gICAqIFNldCBPcGVuVmlkdSBhZHZhbmNlZCBjb25maWd1cmF0aW9uIG9wdGlvbnMuIEN1cnJlbnRseSBgY29uZmlndXJhdGlvbmAgaXMgYW4gb2JqZWN0IHdpdGggdGhlIGZvbGxvd2luZyBvcHRpb25hbCBwcm9wZXJ0aWVzIChzZWUgW1tPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbl1dIGZvciBtb3JlIGRldGFpbHMpOlxuICAgKiAtIGBpY2VTZXJ2ZXJzYDogc2V0IGN1c3RvbSBTVFVOL1RVUk4gc2VydmVycyB0byBiZSB1c2VkIGJ5IE9wZW5WaWR1IEJyb3dzZXJcbiAgICogLSBgc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb25gOiB1cmwgdG8gYSBjdXN0b20gc2NyZWVuIHNoYXJlIGV4dGVuc2lvbiBmb3IgQ2hyb21lIHRvIGJlIHVzZWQgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBvbmUsIGJhc2VkIG9uIG91cnMgW2h0dHBzOi8vZ2l0aHViLmNvbS9PcGVuVmlkdS9vcGVudmlkdS1zY3JlZW4tc2hhcmluZy1jaHJvbWUtZXh0ZW5zaW9uXShodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbilcbiAgICogLSBgcHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zYDogY3VzdG9tIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBbW1B1Ymxpc2hlclNwZWFraW5nRXZlbnRdXSBmZWF0dXJlXG4gICAqL1xuICBzZXRBZHZhbmNlZENvbmZpZ3VyYXRpb24oY29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24pOiB2b2lkIHtcbiAgICB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb247XG4gIH1cblxuXG4gIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyhwdWJsaXNoZXJQcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPE1lZGlhU3RyZWFtQ29uc3RyYWludHM+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGxldCBhdWRpbywgdmlkZW87XG5cbiAgICAgIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBudWxsIHx8IHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgPT09IGZhbHNlKSB7XG4gICAgICAgIGF1ZGlvID0gZmFsc2U7XG4gICAgICB9IGVsc2UgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBhdWRpbyA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhdWRpbyA9IHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBudWxsIHx8IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09IGZhbHNlKSB7XG4gICAgICAgIHZpZGVvID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2aWRlbyA9IHtcbiAgICAgICAgICBoZWlnaHQ6IHtcbiAgICAgICAgICAgIGlkZWFsOiA0ODBcbiAgICAgICAgICB9LFxuICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICBpZGVhbDogNjQwXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtZWRpYUNvbnN0cmFpbnRzOiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbyxcbiAgICAgICAgdmlkZW9cbiAgICAgIH07XG5cbiAgICAgIGlmICh0eXBlb2YgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA9IHsgZGV2aWNlSWQ6IHsgZXhhY3Q6IG1lZGlhQ29uc3RyYWludHMuYXVkaW8gfSB9O1xuICAgICAgfVxuXG4gICAgICBpZiAobWVkaWFDb25zdHJhaW50cy52aWRlbykge1xuXG4gICAgICAgIGlmICghIXB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbikge1xuICAgICAgICAgIGNvbnN0IHdpZHRoQW5kSGVpZ2h0ID0gcHVibGlzaGVyUHJvcGVydGllcy5yZXNvbHV0aW9uLnRvTG93ZXJDYXNlKCkuc3BsaXQoJ3gnKTtcbiAgICAgICAgICBjb25zdCB3aWR0aCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFswXSk7XG4gICAgICAgICAgY29uc3QgaGVpZ2h0ID0gTnVtYmVyKHdpZHRoQW5kSGVpZ2h0WzFdKTtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLndpZHRoLmlkZWFsID0gd2lkdGg7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS5oZWlnaHQuaWRlYWwgPSBoZWlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZSkge1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuZnJhbWVSYXRlID0geyBpZGVhbDogcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghIXB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgJiYgdHlwZW9mIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzdHJpbmcnKSB7XG5cbiAgICAgICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbicpIHtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUgIT09ICdDaHJvbWUnICYmIHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVELCAnWW91IGNhbiBvbmx5IHNjcmVlbiBzaGFyZSBpbiBkZXNrdG9wIENocm9tZSBhbmQgRmlyZWZveC4gRGV0ZWN0ZWQgYnJvd3NlcjogJyArIHBsYXRmb3JtLm5hbWUpO1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gJiYgIShwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSkge1xuXG4gICAgICAgICAgICAgICAgLy8gQ3VzdG9tIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lXG5cbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldFNjcmVlbkNvbnN0cmFpbnRzKChlcnJvciwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yIHx8ICEhc2NyZWVuQ29uc3RyYWludHMubWFuZGF0b3J5ICYmIHNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZSA9PT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnIHx8IGVycm9yID09PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25JZCA9IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIS5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbklkLCAoc3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICg8c3RyaW5nPnRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWZhdWx0IHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lXG5cbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nQXV0by5nZXRTY3JlZW5JZCgoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25VcmwgPSAhIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uID8gdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gOlxuICAgICAgICAgICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2hyb21lLmdvb2dsZS5jb20vd2Vic3RvcmUvZGV0YWlsL29wZW52aWR1LXNjcmVlbnNoYXJpbmcvbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCBleHRlbnNpb25VcmwpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdpbnN0YWxsZWQtZGlzYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9ICdzY3JlZW4nO1xuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zdHJpbmctbGl0ZXJhbFxuICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlb1snZGV2aWNlSWQnXSA9IHsgZXhhY3Q6IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgfTtcbiAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc3RhcnRXcyhvbkNvbm5lY3RTdWNjZXM6IChlcnJvcjogRXJyb3IpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSB7XG4gICAgICBoZWFydGJlYXQ6IDUwMDAsXG4gICAgICBzZW5kQ2xvc2VNZXNzYWdlOiBmYWxzZSxcbiAgICAgIHdzOiB7XG4gICAgICAgIHVyaTogdGhpcy53c1VyaSxcbiAgICAgICAgdXNlU29ja0pTOiBmYWxzZSxcbiAgICAgICAgb25jb25uZWN0ZWQ6IG9uQ29ubmVjdFN1Y2NlcyxcbiAgICAgICAgb25kaXNjb25uZWN0OiB0aGlzLmRpc2Nvbm5lY3RDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBvbnJlY29ubmVjdGluZzogdGhpcy5yZWNvbm5lY3RpbmdDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBvbnJlY29ubmVjdGVkOiB0aGlzLnJlY29ubmVjdGVkQ2FsbGJhY2suYmluZCh0aGlzKVxuICAgICAgfSxcbiAgICAgIHJwYzoge1xuICAgICAgICByZXF1ZXN0VGltZW91dDogMTAwMDAsXG4gICAgICAgIHBhcnRpY2lwYW50Sm9pbmVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEpvaW5lZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50UHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50VW5wdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50VW5wdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudExlZnQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50TGVmdC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50RXZpY3RlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRFdmljdGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RhcnRlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RhcnRlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0b3BwZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0b3BwZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzZW5kTWVzc2FnZTogdGhpcy5zZXNzaW9uLm9uTmV3TWVzc2FnZS5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5cbi8qKlxuICogUGFja3MgbG9jYWwgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGNhbiBwdWJsaXNoIGl0IHRvIGEgc2Vzc2lvbi4gSW5pdGlhbGl6ZWQgd2l0aCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAqL1xuZXhwb3J0IGNsYXNzIFB1Ymxpc2hlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgUHVibGlzaGVyIGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3RcbiAgICAgKi9cbiAgICBhY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHlvdSBoYXZlIGNhbGxlZCBbW1B1Ymxpc2hlci5zdWJzY3JpYmVUb1JlbW90ZV1dIHdpdGggdmFsdWUgYHRydWVgIG9yIGBmYWxzZWAgKCpmYWxzZSogYnkgZGVmYXVsdClcbiAgICAgKi9cbiAgICBpc1N1YnNjcmliZWRUb1JlbW90ZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIHRvIHdoaWNoIHRoZSBQdWJsaXNoZXIgYmVsb25nc1xuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247IC8vIEluaXRpYWxpemVkIGJ5IFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpXG5cbiAgICBwcml2YXRlIGFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcztcbiAgICBwcml2YXRlIHBlcm1pc3Npb25EaWFsb2dUaW1lb3V0OiBOb2RlSlMuVGltZXI7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgcHJpdmF0ZSBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uZWUub24oJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQtYnktZGlzY29ubmVjdCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgYXVkaW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIGF1ZGlvIHN0cmVhbScpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gcHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVucHVibGlzaCBpdFxuICAgICAqL1xuICAgIHB1Ymxpc2hWaWRlbyh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIENhbGwgdGhpcyBtZXRob2QgYmVmb3JlIFtbU2Vzc2lvbi5wdWJsaXNoXV0gdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBQdWJsaXNoZXIge1xuICAgICAgICBzdXBlci5vbmNlKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbUNyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHRoaXMuc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUub25jZSgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgZXJyb3JDYWxsYmFjayA9IChvcGVuVmlkdUVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJlamVjdChvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmlzTWVkaWFTdHJlYW1UcmFjayh0aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjaygoPE1lZGlhU3RyZWFtVHJhY2s+dGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQXBwbHkgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW8gYW5kIFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvXG4gICAgICAgICAgICAgICAgaWYgKCEhbWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdLmVuYWJsZWQgPSAhIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCEhbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSAhIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBzdWJzY3JpYmVkIHRvIG91ciByZW1vdGUgd2UgZG9uJ3Qgc3RpbGwgc2V0IHRoZSBNZWRpYVN0cmVhbSBvYmplY3QgaW4gdGhlIHZpZGVvIGVsZW1lbnRzIHRvXG4gICAgICAgICAgICAgICAgICAgIC8vIGF2b2lkIGVhcmx5ICdzdHJlYW1QbGF5aW5nJyBldmVudFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS51cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcblxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuZmlyc3RWaWRlb0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVWaWRlb0VsZW1lbnQodGhpcy5maXJzdFZpZGVvRWxlbWVudC50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnRoaXMucHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyh0aGlzLnByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgLnRoZW4oY29uc3RyYWludHMgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG91dGJvdW5kU3RyZWFtT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IGNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyUHJvcGVydGllczogdGhpcy5wcm9wZXJ0aWVzXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHNBdXg6IE1lZGlhU3RyZWFtQ29uc3RyYWludHMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGltZUZvckRpYWxvZ0V2ZW50ID0gMTI1MDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kVmlkZW8oKSB8fCB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZpbmVkQXVkaW9Db25zdHJhaW50ID0gKChjb25zdHJhaW50cy5hdWRpbyA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiBjb25zdHJhaW50cy5hdWRpbyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gZmFsc2UgOiBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBjb25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIodGltZUZvckRpYWxvZ0V2ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHNBdXgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgJiYgdGhpcy5zdHJlYW0uaXNTZW5kQXVkaW8oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiBnZXR0aW5nIGRlc2t0b3AgYXMgdXNlciBtZWRpYSBhdWRpbyBjb25zdHJhaW50IG11c3QgYmUgZmFsc2UuIE5vdyB3ZSBjYW4gYXNrIGZvciBpdCBpZiByZXF1aXJlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXguYXVkaW8gPSBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihhdWRpb09ubHlTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soYXVkaW9Pbmx5U3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWUsIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnb3ZlcmNvbnN0cmFpbmVkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlBVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWUsIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogY29uc3RyYWludHMudmlkZW9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEIDogT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ1wiICsgKDxDb25zdHJhaW5ET01TdHJpbmdQYXJhbWV0ZXJzPig8TWVkaWFUcmFja0NvbnN0cmFpbnRzPmNvbnN0cmFpbnRzLmF1ZGlvKS5kZXZpY2VJZCEhKS5leGFjdCArIFwiJyBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IHRoZSB2YWx1ZSBwYXNzZWQgZm9yIGNvbnN0cmFpbnQgJ1wiICsgZXJyb3IuY29uc3RyYWludCArIFwiJ1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiVmlkZW8gaW5wdXQgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ1wiICsgKDxDb25zdHJhaW5ET01TdHJpbmdQYXJhbWV0ZXJzPig8TWVkaWFUcmFja0NvbnN0cmFpbnRzPmNvbnN0cmFpbnRzLnZpZGVvKS5kZXZpY2VJZCEhKS5leGFjdCArIFwiJyBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IHRoZSB2YWx1ZSBwYXNzZWQgZm9yIGNvbnN0cmFpbnQgJ1wiICsgZXJyb3IuY29uc3RyYWludCArIFwiJ1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk5PX0lOUFVUX1NPVVJDRV9TRVQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJQcm9wZXJ0aWVzICdhdWRpb1NvdXJjZScgYW5kICd2aWRlb1NvdXJjZScgY2Fubm90IGJlIHNldCB0byBmYWxzZSBvciBudWxsIGF0IHRoZSBzYW1lIHRpbWUgd2hlbiBjYWxsaW5nICdPcGVuVmlkdS5pbml0UHVibGlzaGVyJ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVTZXNzaW9uKHNlc3Npb246IFNlc3Npb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbiA9IHNlc3Npb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWVzdGFibGlzaFN0cmVhbVBsYXlpbmdFdmVudCgpIHtcbiAgICAgICAgaWYgKHRoaXMuZWUuZ2V0TGlzdGVuZXJzKCdzdHJlYW1QbGF5aW5nJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5hZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIHNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih3YWl0VGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEaWFsb2dPcGVuZWQnLCBbXSk7XG4gICAgICAgIH0sIHdhaXRUaW1lKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZTogbnVtYmVyLCB3YWl0VGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0KTtcbiAgICAgICAgaWYgKChEYXRlLm5vdygpIC0gc3RhcnRUaW1lKSA+IHdhaXRUaW1lKSB7XG4gICAgICAgICAgICAvLyBQZXJtaXNzaW9uIGRpYWxvZyB3YXMgc2hvd24gYW5kIG5vdyBpcyBjbG9zZWRcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEaWFsb2dDbG9zZWQnLCBbXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4vUHVibGlzaGVyJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU3Vic2NyaWJlciB9IGZyb20gJy4vU3Vic2NyaWJlcic7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTaWduYWxPcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TaWduYWxPcHRpb25zJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0Nvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IE9iak1hcCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL09iak1hcCc7XG5pbXBvcnQgeyBTZXNzaW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL1Nlc3Npb25PcHRpb25zJztcbmltcG9ydCB7IENvbm5lY3Rpb25FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0Nvbm5lY3Rpb25FdmVudCc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5pbXBvcnQgeyBSZWNvcmRpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1JlY29yZGluZ0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudCc7XG5pbXBvcnQgeyBTaWduYWxFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50JztcbmltcG9ydCB7IFN0cmVhbUV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLy8gVGhpcyBtYXAgaXMgb25seSB1c2VkIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gJ2pvaW5Sb29tJyByZXNwb25zZSBhbmQgJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnIG5vdGlmaWNhdGlvblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVTdHJlYW1zQ3JlYXRlZDogT2JqTWFwPGJvb2xlYW4+ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE9iak1hcDxDb25uZWN0aW9uPiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcml6ZWQgZm9ybWF0XG4gICAgICogYXMgSlNPTiBvciBYTUwgaXMgYSBnb29kIGlkZWEpLCB0aGUgb25seSByZXN0cmljdGlvbiBpcyBhIG1heGltdW0gbGVuZ3RoIG9mIDEwMDAwIGNoYXJzLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRhZGF0YSBpcyBub3QgY29uc2lkZXJlZCBzZWN1cmUsIGFzIGl0IGlzIGdlbmVyYXRlZCBpbiB0aGUgY2xpZW50IHNpZGUuIFRvIHBhc3Mgc2VjdXJpemVkIGRhdGEsIGFkZCBpdCBhcyBhIHBhcmFtZXRlciBpbiB0aGVcbiAgICAgKiB0b2tlbiBnZW5lcmF0aW9uIG9wZXJhdGlvbiAodGhyb3VnaCB0aGUgQVBJIFJFU1QsIG9wZW52aWR1LWphdmEtY2xpZW50IG9yIG9wZW52aWR1LW5vZGUtY2xpZW50KS5cbiAgICAgKlxuICAgICAqIE9ubHkgYWZ0ZXIgdGhlIHJldHVybmVkIFByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gb2JqZWN0IHdpbGwgYmUgYXZhaWxhYmxlIGFuZCBwcm9wZXJseSBkZWZpbmVkLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBmaXJzdCBkaXNwYXRjaCBvbmUgb3IgbW9yZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cyB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2Q6XG4gICAgICogLSBGaXJzdCBvbmUgZm9yIHlvdXIgb3duIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0LCBzbyB5b3UgY2FuIHJldHJpZXZlIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gcHJvcGVydHkuXG4gICAgICogLSBUaGVuIG9uZSBmb3IgZWFjaCByZW1vdGUgQ29ubmVjdGlvbiBwcmV2aW91c2x5IGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiwgaWYgYW55LiBBbnkgb3RoZXIgcmVtb3RlIHVzZXIgY29ubmVjdGluZyB0byB0aGUgU2Vzc2lvbiBhZnRlciB5b3UgaGF2ZVxuICAgICAqIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCB3aGVuIHRoZXkgZG8gc28uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgZm9yIGVhY2ggcmVtb3RlIGFjdGl2ZSBbW1B1Ymxpc2hlcl1dIHRoYXQgd2FzIGFscmVhZHkgc3RyZWFtaW5nXG4gICAgICogd2hlbiBjb25uZWN0aW5nLCBqdXN0IGFmdGVyIGRpc3BhdGNoaW5nIGFsbCByZW1vdGUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0byB3aGljaCB5b3UgbXVzdCBzdWJzY3JpYmUgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqXG4gICAgICovXG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YT86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1Rva2VuKHRva2VuKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIEVhcmx5IGNvbmZpZ3VyYXRpb24gdG8gZGVhY3RpdmF0ZSBhdXRvbWF0aWMgc3Vic2NyaXB0aW9uIHRvIHN0cmVhbXNcbiAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRva2VuLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISFtZXRhZGF0YSA/IHRoaXMuc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGEpIDogJydcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdEF1eCh0b2tlbikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBwbGF0Zm9ybS5uYW1lICsgJyAnICsgcGxhdGZvcm0udmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGVhdmVzIHRoZSBzZXNzaW9uLCBkZXN0cm95aW5nIGFsbCBzdHJlYW1zIGFuZCBkZWxldGluZyB0aGUgdXNlciBhcyBhIHBhcnRpY2lwYW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBlYWNoIFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgdG8gYXZvaWQgdGhpcyBiZWhhdmlvdXIgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24gKHRvIGRvIHNvIGl0IGlzIGEgbWFuZGF0b3J5IHJlcXVpcmVtZW50IHRvIGNhbGwgYFNlc3Npb24udW5wdWJsaXNoKClgXG4gICAgICogb3IvYW5kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaW4gdGhlIHByZXZpb3VzIHNlc3Npb24pLiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZGlzY29ubmVjdGVkIHBhcnRpY2lwYW50IHdhcyBwdWJsaXNoaW5nLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvdXIgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgaW4gYW55IGNhc2UuIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sZWF2ZShmYWxzZSwgJ2Rpc2Nvbm5lY3QnKTtcbiAgICB9XG5cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgYHN0cmVhbWAsIGFkZGluZyBhIG5ldyBIVE1MIHZpZGVvIGVsZW1lbnQgdG8gRE9NIHdpdGggYHN1YnNjcmliZXJQcm9wZXJ0aWVzYCBzZXR0aW5ncy4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWQgaW4gdGhlIGNhbGxiYWNrIG9mIGBzdHJlYW1DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliaW5nIHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZCA9IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAndW5zdWJzY3JpYmVGcm9tVmlkZW8nLFxuICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHVuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcykgYW5kXG4gICAgICogZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsJywgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0uY29ubmVjdGlvbiAhPT0gdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5wdWJsaXNoaW5nIGxvY2FsIG1lZGlhICgnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyknKTtcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyBvbmUgc2lnbmFsLiBgc2lnbmFsYCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiBgYGBqc29uXG4gICAgICoge2RhdGE6c3RyaW5nLCB0bzpDb25uZWN0aW9uW10sIHR5cGU6c3RyaW5nfVxuICAgICAqIGBgYFxuICAgICAqIEFsbCB1c2VycyBzdWJzY3JpYmVkIHRvIHRoYXQgc2lnbmFsIChgc2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCAuLi4pYCBvciBgc2Vzc2lvbi5vbignc2lnbmFsJywgLi4uKWAgZm9yIGFsbCBzaWduYWxzKSBhbmQgd2hvc2UgQ29ubmVjdGlvbiBvYmplY3RzIGFyZSBpbiBgdG9gIGFycmF5IHdpbGwgcmVjZWl2ZSBpdC4gVGhlaXIgbG9jYWxcbiAgICAgKiBTZXNzaW9uIG9iamVjdHMgd2lsbCBkaXNwYXRjaCBhIGBzaWduYWxgIG9yIGBzaWduYWw6dHlwZWAgZXZlbnQuIFNlZSBbW1NpZ25hbEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgbWVzc2FnZSBzdWNjZXNzZnVsbHkgcmVhY2hlZCBvcGVudmlkdS1zZXJ2ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdC4gX1RoaXMgZG9lc24ndFxuICAgICAqIG1lYW4gdGhhdCBvcGVudmlkdS1zZXJ2ZXIgY291bGQgcmVzZW5kIHRoZSBtZXNzYWdlIHRvIGFsbCB0aGUgbGlzdGVkIHJlY2VpdmVycy5fXG4gICAgICovXG4gICAgLyogdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cbiAgICBzaWduYWwoc2lnbmFsOiBTaWduYWxPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsTWVzc2FnZSA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWRzLnB1c2goY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogSlNPTi5zdHJpbmdpZnkoc2lnbmFsTWVzc2FnZSlcbiAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qIHRzbGludDplbmFibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayAnc3BlYWtpbmcnIGV2ZW50IGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGRpc2FibGFlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhIXN0ci5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24ocmVzcG9uc2UuaWQsICcnKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Nvbm5lY3Rpb24gJyArIHJlc3BvbnNlLmlkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tyZXNwb25zZS5pZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5uYW1lLCAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIG1zZy5uYW1lICsgXCIgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50TGVmdCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBzdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGFmdGVyQ29ubmVjdGlvbkZvdW5kID0gKGNvbm5lY3Rpb24pID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSkge1xuICAgICAgICAgICAgICAgIC8vIEF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gc3RyZWFtLnN1YnNjcmliZSgpIGluIFwib25QYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGFuZCBpbiBcImpvaW5Sb29tXCIgcnBjIGNhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBjb25kaXRpb24gaXMgZmFsc2UgaWYgb3BlbnZpZHUtc2VydmVyIHNlbmRzIFwicGFydGljaXBhbnRQdWJsaXNoZWRcIiBldmVudCB0byBhIHN1YnNjcmliZXIgcGFydGljaXBhbnQgdGhhdCBoYXNcbiAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IHN1YnNjcmliZWQgdG8gY2VydGFpbiBzdHJlYW0gaW4gdGhlIGNhbGxiYWNrIG9mIFwiam9pblJvb21cIiBtZXRob2RcblxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBHZXQgdGhlIGV4aXN0aW5nIENvbm5lY3Rpb24gY3JlYXRlZCBvbiAnb25QYXJ0aWNpcGFudEpvaW5lZCcgZm9yXG4gICAgICAgIC8vIGV4aXN0aW5nIHBhcnRpY2lwYW50cyBvciBjcmVhdGUgYSBuZXcgb25lIGZvciBuZXcgcGFydGljaXBhbnRzXG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24ocmVzcG9uc2UuaWQsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgcmVzcG9uc2UuaWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50UHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29uID0+IHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgZXhpc3RpbmcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBjb247XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UubWV0YWRhdGEgPSBjb24uZGF0YTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLm9wdGlvbnMgPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlLnN0cmVhbXMpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgbmV3IENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5uYW1lLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIG1zZy5uYW1lICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgY29ubmVjdGlvbi5zdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuXG4gICAgICAgICAgICAgICAgLy8gRGVsZXRpbmcgdGhlIHJlbW90ZSBzdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZDogc3RyaW5nID0gY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ucmVtb3ZlU3RyZWFtKHN0cmVhbUlkKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50RXZpY3RlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgLyp0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLm5hbWUgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgJ2ZvcmNlRGlzY29ubmVjdCcpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5kaXNwb3NlKCk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgJ2ZvcmNlRGlzY29ubmVjdCcpXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTsqL1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk5ld01lc3NhZ2UobXNnKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgc2lnbmFsOiAnICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG5cbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKG1zZy5mcm9tLCBcIkNvbm5lY3Rpb24gJ1wiICsgbXNnLmZyb20gKyBcIicgdW5rbm93IHdoZW4gJ29uTmV3TWVzc2FnZScuIEV4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogXCJcbiAgICAgICAgICAgICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpICsgJy4gRXhpc3RpbmcgbG9jYWwgY29ubmVjdGlvbjogJyArIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWwnLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsOicgKyBtc2cudHlwZSwgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVjdkljZUNhbmRpZGF0ZShtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY2FuZGlkYXRlID0ge1xuICAgICAgICAgICAgY2FuZGlkYXRlOiBtc2cuY2FuZGlkYXRlLFxuICAgICAgICAgICAgc2RwTWlkOiBtc2cuc2RwTWlkLFxuICAgICAgICAgICAgc2RwTUxpbmVJbmRleDogbXNnLnNkcE1MaW5lSW5kZXgsXG4gICAgICAgICAgICB0b0pTT046ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKG1zZy5lbmRwb2ludE5hbWUsICdDb25uZWN0aW9uIG5vdCBmb3VuZCBmb3IgZW5kcG9pbnQgJyArIG1zZy5lbmRwb2ludE5hbWUgKyAnLiBJY2UgY2FuZGlkYXRlIHdpbGwgYmUgaWdub3JlZDogJyArIGNhbmRpZGF0ZSlcbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgIHN0cmVhbS5nZXRXZWJSdGNQZWVyKCkuYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBhZGRpbmcgY2FuZGlkYXRlIGZvciAnICsgc3RyZWFtLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblNlc3Npb25DbG9zZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnU2Vzc2lvbiBjbG9zZWQ6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcbiAgICAgICAgY29uc3QgcyA9IG1zZy5yb29tO1xuICAgICAgICBpZiAocyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbi1jbG9zZWQnLCBbe1xuICAgICAgICAgICAgICAgIHNlc3Npb246IHNcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWQnLCBtc2cpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTG9zdENvbm5lY3Rpb24oKTogdm9pZCB7XG5cbiAgICAgICAgLyppZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0qL1xuXG4gICAgICAgIGNvbnNvbGUud2FybignTG9zdCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgdGhpcy5sZWF2ZSh0cnVlLCAnbmV0d29ya0Rpc2Nvbm5lY3QnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk1lZGlhRXJyb3IocGFyYW1zKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWEgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgY29uc3QgZXJyID0gcGFyYW1zLmVycm9yO1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnZXJyb3ItbWVkaWEnLCBbe1xuICAgICAgICAgICAgICAgIGVycm9yOiBlcnJcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignUmVjZWl2ZWQgdW5kZWZpbmVkIG1lZGlhIGVycm9yLiBQYXJhbXM6JywgcGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0YXJ0ZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0YXJ0ZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdGFydGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3JkaW5nU3RvcHBlZChyZXNwb25zZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVjb3JkaW5nU3RvcHBlZCcsIFtuZXcgUmVjb3JkaW5nRXZlbnQodGhpcywgJ3JlY29yZGluZ1N0b3BwZWQnLCByZXNwb25zZS5pZCwgcmVzcG9uc2UubmFtZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxlYXZlKGZvcmNlZDogYm9vbGVhbiwgcmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBmb3JjZWQgPSAhIWZvcmNlZDtcbiAgICAgICAgY29uc29sZS5pbmZvKCdMZWF2aW5nIFNlc3Npb24gKGZvcmNlZD0nICsgZm9yY2VkICsgJyknKTtcblxuICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkICYmICFmb3JjZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdsZWF2ZVJvb20nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVlLmVtaXRFdmVudCgnbG9jYWwtc3RyZWFtLWRlc3Ryb3llZC1ieS1kaXNjb25uZWN0JywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBNYWtlIFNlc3Npb24gb2JqZWN0IGRpc3BhdGNoICdzZXNzaW9uRGlzY29ubmVjdGVkJyBldmVudCAoaWYgaXQgaXMgbm90IGFscmVhZHkgZGlzcG9zZWQpXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudCA9IG5ldyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQodGhpcywgcmVhc29uKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcsIFtzZXNzaW9uRGlzY29ubmVjdEV2ZW50XSk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3Ugd2VyZSBub3QgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0QXV4KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zdGFydFdzKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBqb2luUGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46ICghIXRva2VuKSA/IHRva2VuIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdqb2luUm9vbScsIGpvaW5QYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGF0YSA9IHJlc3BvbnNlLm1ldGFkYXRhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSByZW1vdGUgQ29ubmVjdGlvbnMgd2l0aCB2YWx1ZSByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25zOiBuZXcgQXJyYXk8Q29ubmVjdGlvbj4oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJ0aWNpcGFudHM6IENvbm5lY3Rpb25PcHRpb25zW10gPSByZXNwb25zZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50cy5mb3JFYWNoKHBhcnRpY2lwYW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMucHVzaChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLnB1c2goY29ubmVjdGlvbi5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCB0aGlzLmNvbm5lY3Rpb24sICcnKV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggZXhpc3RpbmcgY29ubmVjdGlvbiBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ3N0cmVhbUNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGFjdGl2ZSBzdHJlYW0gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5mb3JFYWNoKHN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBzdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW1vdGVDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIGNvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodG9rZW4pO1xuICAgICAgICB0aGlzLnNlc3Npb25JZCA9IDxzdHJpbmc+dXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Nlc3Npb25JZCcpO1xuICAgICAgICBjb25zdCBzZWNyZXQgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnc2VjcmV0Jyk7XG4gICAgICAgIGNvbnN0IHJlY29yZGVyID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3JlY29yZGVyJyk7XG4gICAgICAgIGNvbnN0IHR1cm5Vc2VybmFtZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0dXJuVXNlcm5hbWUnKTtcbiAgICAgICAgY29uc3QgdHVybkNyZWRlbnRpYWwgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVybkNyZWRlbnRpYWwnKTtcbiAgICAgICAgY29uc3Qgcm9sZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyb2xlJyk7XG5cbiAgICAgICAgaWYgKCEhc2VjcmV0KSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyZWNvcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdHVyblVzZXJuYW1lICYmICEhdHVybkNyZWRlbnRpYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0dW5VcmwgPSAnc3R1bjonICsgdXJsLmhvc3RuYW1lICsgJzozNDc4JztcbiAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMiA9IHR1cm5VcmwxICsgJz90cmFuc3BvcnQ9dGNwJztcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtcbiAgICAgICAgICAgICAgICB7IHVybHM6IFtzdHVuVXJsXSB9LFxuICAgICAgICAgICAgICAgIHsgdXJsczogW3R1cm5VcmwxLCB0dXJuVXJsMl0sIHVzZXJuYW1lOiB0dXJuVXNlcm5hbWUsIGNyZWRlbnRpYWw6IHR1cm5DcmVkZW50aWFsIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnVFVSTiB0ZW1wIGNyZWRlbnRpYWxzIFsnICsgdHVyblVzZXJuYW1lICsgJzonICsgdHVybkNyZWRlbnRpYWwgKyAnXScpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcm9sZSkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yb2xlID0gcm9sZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub3BlbnZpZHUud3NVcmkgPSAnd3NzOi8vJyArIHVybC5ob3N0ICsgJy9vcGVudmlkdSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBXZWJSdGNQZWVyLCBXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlclNlbmRyZWN2IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNQZWVyL1dlYlJ0Y1BlZXInO1xuaW1wb3J0IHsgV2ViUnRjU3RhdHMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1N0YXRzL1dlYlJ0Y1N0YXRzJztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5pbXBvcnQgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKTtcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIG1lZGlhIHN0cmVhbXMgYXZhaWxhYmxlIGluIE9wZW5WaWR1IFNlcnZlciBmb3IgY2VydGFpbiBzZXNzaW9uLlxuICogRWFjaCBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBoYXMgYW4gYXR0cmlidXRlIG9mIHR5cGUgU3RyZWFtLCBhcyB0aGV5IGdpdmUgYWNjZXNzXG4gKiB0byBvbmUgb2YgdGhlbSAoc2VuZGluZyBhbmQgcmVjZWl2aW5nIGl0LCByZXNwZWN0aXZlbHkpXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW0ge1xuXG4gICAgLyoqXG4gICAgICogVGhlIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgaXMgcHVibGlzaGluZyB0aGUgc3RyZWFtXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZyYW1lIHJhdGUgb2YgdGhlIHZpZGVvIGluIGZyYW1lcyBwZXIgc2Vjb25kLiBUaGlzIHByb3BlcnR5IGlzIG9ubHkgZGVmaW5lZCBpZiB0aGUgW1tQdWJsaXNoZXJdXSBvZlxuICAgICAqIHRoZSBzdHJlYW0gd2FzIGluaXRpYWxpemVkIHBhc3NpbmcgYSBfZnJhbWVSYXRlXyBwcm9wZXJ0eSBvbiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICAgKi9cbiAgICBmcmFtZVJhdGU/OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIGEgdmlkZW8gdHJhY2sgb3Igbm90XG4gICAgICovXG4gICAgaGFzVmlkZW86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIGFuIGF1ZGlvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc0F1ZGlvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIHN0cmVhbUlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBgXCJDQU1FUkFcImAgb3IgYFwiU0NSRUVOXCJgLiAqdW5kZWZpbmVkKiBpZiBzdHJlYW0gaXMgYXVkaW8tb25seVxuICAgICAqL1xuICAgIHR5cGVPZlZpZGVvPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtTWFuYWdlciBvYmplY3QgKFtbUHVibGlzaGVyXV0gb3IgW1tTdWJzY3JpYmVyXV0pIGluIGNoYXJnZSBvZiBkaXNwbGF5aW5nIHRoaXMgc3RyZWFtIGluIHRoZSBET01cbiAgICAgKi9cbiAgICBzdHJlYW1NYW5hZ2VyOiBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNQZWVyOiBXZWJSdGNQZWVyO1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5ib3VuZFN0cmVhbU9wdHM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3BlZWNoRXZlbnQ6IGFueTtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlc3Npb246IFNlc3Npb24sIG9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zIHwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIHwge30pIHtcblxuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCdpZCcpKSB7XG4gICAgICAgICAgICAvLyBJbmJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBTdWJzY3JpYmVyXG4gICAgICAgICAgICB0aGlzLmluYm91bmRTdHJlYW1PcHRzID0gPEluYm91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICdTQ1JFRU4nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAnQ0FNRVJBJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMudHlwZU9mVmlkZW87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pc1NlbmRBdWRpbygpO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaXNTZW5kVmlkZW8oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gbWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWwoKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGluYm91bmQgb3B0aW9ucyB1bmRlZmluZWQgYW5kIG91dGJvdW5kIG9wdGlvbnMgZGVmaW5lZFxuICAgICAgICByZXR1cm4gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzICYmICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5nZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlcG9ydCA9PiByZXNvbHZlKHJlcG9ydCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpOiBSVENJY2VDYW5kaWRhdGVbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclNlbmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgdXNlck1lZGlhQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pc1NlbmRWaWRlbygpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3B1Ymxpc2hWaWRlbycsIHtcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW0sXG4gICAgICAgICAgICAgICAgICAgIGRvTG9vcGJhY2s6IHRoaXMuZGlzcGxheU15UmVtb3RlKCkgfHwgZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvQWN0aXZlOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiB0aGlzLmlzU2VuZFZpZGVvKCksXG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiAoKHRoaXMuaXNTZW5kVmlkZW8oKSkgPyAodGhpcy5pc1NlbmRTY3JlZW4oKSA/ICdTQ1JFRU4nIDogJ0NBTUVSQScpIDogJycpLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xXG4gICAgICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnRXJyb3Igb24gcHVibGlzaFZpZGVvOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0xvY2FsU3RyZWFtUHVibGlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlUGVlclN1Y2Nlc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKCkudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclJlY2VpdmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgb2ZmZXJDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5yZWN2QXVkaW8sXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMucmVjdlZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWQuIENvbnN0cmFpbnRzIG9mIGdlbmVyYXRlIFNEUCBvZmZlclwiLFxuICAgICAgICAgICAgICAgIG9mZmVyQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gc3Vic2NyaWJlIHRvICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3JlY2VpdmVWaWRlb0Zyb20nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gcmVjdlZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNmdWxseUVzdGFibGlzaGVkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclJlY3Zvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKVxuICAgICAgICAgICAgICAgIC50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbW90ZVBlZXJTdWNjZXNmdWxseUVzdGFibGlzaGVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gdGhpcy53ZWJSdGNQZWVyLnBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnUGVlciByZW1vdGUgc3RyZWFtJywgdGhpcy5tZWRpYVN0cmVhbSk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSAmJiAhIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAmJiB0aGlzLnNlc3Npb24uc3BlYWtpbmdFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMgPSBuZXcgV2ViUnRjU3RhdHModGhpcyk7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wV2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMud2ViUnRjU3RhdHMgJiYgdGhpcy53ZWJSdGNTdGF0cy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5zdG9wV2ViUnRjU3RhdHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SWNlU2VydmVyc0NvbmYoKTogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgcmV0dXJuVmFsdWU7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMgPT09ICdmcmVlaWNlJyA/XG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGB2aWRlb2AgZWxlbWVudCBwYXJhbWV0ZXIgZGlzcGxheSB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IGFyZVxuICAgICAqIFttYW5hZ2luZyB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd25dKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpXG4gICAgICpcbiAgICAgKiBDYWxsaW5nIHRoaXMgbWV0aG9kIHdpdGggYSB2aWRlbyBhbHJlYWR5IGFkZGVkIHRvIG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgY2F1c2UgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYmVcbiAgICAgKiBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBwcmV2aW91cyBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgdG8gYmUgYXNzb2NpYXRlZCB0byB0aGlzIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIDEgaWYgdGhlIHZpZGVvIHdhc24ndCBhc3NvY2lhdGVkIHRvIGFueSBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqIDAgaWYgdGhlIHZpZGVvIHdhcyBhbHJlYWR5IGFkZGVkIHRvIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXIuIC0xIGlmIHRoZSB2aWRlbyB3YXMgcHJldmlvdXNseSBhc3NvY2lhdGVkIHRvIGFueSBvdGhlclxuICAgICAqIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgb25lIGFuZCBwcm9wZXJseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKi9cbiAgICBhZGRWaWRlb0VsZW1lbnQodmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgLy8gSWYgdGhlIHZpZGVvIGVsZW1lbnQgaXMgYWxyZWFkeSBwYXJ0IG9mIHRoaXMgU3RyZWFtTWFuYWdlciBkbyBub3RoaW5nXG4gICAgICAgIGZvciAoY29uc3QgdiBvZiB0aGlzLnZpZGVvcykge1xuICAgICAgICAgICAgaWYgKHYudmlkZW8gPT09IHZpZGVvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmV0dXJuTnVtYmVyID0gMTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3Muc2xpY2UoKS5yZXZlcnNlKCkuZm9yRWFjaCgoc3RyZWFtTWFuYWdlclZpZGVvLCBpbmRleCwgdmlkZW9zKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgb25jYW5wbGF5IGV2ZW50IGxpc3RlbmVyIChvbmx5IE9wZW5WaWR1IGJyb3dzZXIgb25lLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICAgICAgaWYgKCEhc3RyZWFtTWFuYWdlclZpZGVvLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbW92ZSB2aWRlb3MgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyICh0aG9zZSBnZW5lcmF0ZWQgYnkgcGFzc2luZyBhIHZhbGlkIHRhcmdldEVsZW1lbnQgaW4gT3BlblZpZHUuaW5pdFB1Ymxpc2hlciBhbmQgU2Vzc2lvbi5zdWJzY3JpYmVcbiAgICAgICAgICAgICAgICAvLyBvciB0aG9zZSBjcmVhdGVkIGJ5IFN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KS4gVGhlc2UgYXJlIGFsc28gdGhlIHZpZGVvcyB0aGF0IHRyaWdnZXJlZCBhIHZpZGVvRWxlbWVudENyZWF0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucGFyZW50Tm9kZSEucmVtb3ZlQ2hpbGQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50RGVzdHJveWVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZSh2aWRlb3MubGVuZ3RoIC0gMSAtIGluZGV4LCAxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHNyY09iamVjdCBpbiBhbGwgdmlkZW9zIG1hbmFnZWQgYnkgdGhlIHVzZXJcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwcG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gY2FwdHVyZSBzb21lIGRlc2t0b3Agc2NyZWVuIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBoYXMgYmVlbiBjYWxsZWQgd2l0aCBwcm9wZXJ0aWVzIGB2aWRlb1NvdXJjZWAgYW5kIGBhdWRpb1NvdXJjZWAgb2ZcbiAgICAgKiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBwYXJhbWV0ZXIgYm90aCBzZXQgdG8gKmZhbHNlKiBvciAqbnVsbCpcbiAgICAgKi9cbiAgICBOT19JTlBVVF9TT1VSQ0VfU0VUID0gJ05PX0lOUFVUX1NPVVJDRV9TRVQnLFxuXG4gICAgLyoqXG4gICAgICogU29tZSBtZWRpYSBwcm9wZXJ0eSBvZiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBzdWNoIGFzIGBmcmFtZVJhdGVgIG9yIGByZXNvbHV0aW9uYCBpcyBub3Qgc3VwcG9ydGVkXG4gICAgICogYnkgdGhlIGlucHV0IGRldmljZXMgKHdoZW5ldmVyIGl0IGlzIHBvc3NpYmxlIHRoZXkgYXJlIGF1dG9tYXRpY2FsbHkgYWRqdXN0ZWQgdG8gdGhlIG1vc3Qgc2ltaWxhciB2YWx1ZSkuXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEID0gJ09QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuLyoqXG4gKiBTaW1wbGUgb2JqZWN0IHRvIGlkZW50aWZ5IHJ1bnRpbWUgZXJyb3JzIG9uIHRoZSBjbGllbnQgc2lkZVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHVFcnJvciB7XG5cbiAgICBuYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBIb3cgdGhlIHZpZGVvIHdpbGwgYmUgaW5zZXJ0ZWQgaW4gdGhlIERPTSBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuIFNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dIGFuZCBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXVxuICovXG5leHBvcnQgZW51bSBWaWRlb0luc2VydE1vZGUge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHRhcmdldCBlbGVtZW50IChhcyBuZXh0IHNpYmxpbmcpXG4gICAgICovXG4gICAgQUZURVIgPSAnQUZURVInLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGxhc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgQVBQRU5EID0gJ0FQUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYmVmb3JlIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgcHJldmlvdXMgc2libGluZylcbiAgICAgKi9cbiAgICBCRUZPUkUgPSAnQkVGT1JFJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBmaXJzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBQUkVQRU5EID0gJ1BSRVBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIHJlcGxhY2VzIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUkVQTEFDRSA9ICdSRVBMQUNFJ1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYGNvbm5lY3Rpb25DcmVhdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgY29ubmVjdGlvbkRlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgd2FzIGNyZWF0ZWQgb3IgZGVzdHJveWVkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZvciAnY29ubmVjdGlvbkRlc3Ryb3llZCcgZXZlbnQ6XG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3VyIHRoYXQgbWF5IGJlIHByZXZlbnRlZCBieSBjYWxsaW5nIFtbRXZlbnQucHJldmVudERlZmF1bHRdXVxuICAgICAqL1xuICAgIGNhbmNlbGFibGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0IHRoYXQgZGlzcGF0Y2hlZCB0aGUgZXZlbnRcbiAgICAgKi9cbiAgICB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHR5cGUgb2YgZXZlbnQuIFRoaXMgaXMgdGhlIHNhbWUgc3RyaW5nIHlvdSBwYXNzIGFzIGZpcnN0IHBhcmFtZXRlciB3aGVuIGNhbGxpbmcgbWV0aG9kIGBvbigpYCBvZiBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBbW0V2ZW50RGlzcGF0Y2hlcl1dIGludGVyZmFjZVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIHByaXZhdGUgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvdXI6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvdXIgPSAoKSA9PiB7IH07XG4gICAgICAgIHRoaXMuaGFzQmVlblByZXZlbnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHJlY29yZGluZ1N0YXJ0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGByZWNvcmRpbmdTdG9wcGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIElEIGdlbmVyYXRlZCBpbiBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlY29yZGluZyBuYW1lIHlvdSBzdXBwbGllZCB0byBvcGVudmlkdS1zZXJ2ZXIuIEZvciBleGFtcGxlLCB0byBuYW1lIHlvdXIgcmVjb3JkaW5nIGZpbGUgTVlfUkVDT1JESU5HOlxuICAgICAqIC0gV2l0aCAqKkFQSSBSRVNUKio6IFBPU1QgdG8gYC9hcGkvcmVjb3JkaW5ncy9zdGFydGAgcGFzc2luZyBKU09OIGJvZHkgYHtcInNlc3Npb25cIjpcInNlc3Npb25JZFwiLFwibmFtZVwiOlwiTVlfUkVDT1JESU5HXCJ9YFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LWphdmEtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIE1ZX1JFQ09SRElORylgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKE1ZX1JFQ09SRElORykuYnVpbGQoKSlgXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtbm9kZS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgTVlfUkVDT1JESU5HKWAgb3IgYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgbmV3IFJlY29yZGluZ1Byb3BlcnRpZXMuQnVpbGRlcigpLm5hbWUoTVlfUkVDT1JESU5HKS5idWlsZCgpKWBcbiAgICAgKlxuICAgICAqIElmIG5vIG5hbWUgaXMgc3VwcGxpZWQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSB1bmRlZmluZWQgYW5kIHRoZSByZWNvcmRlZCBmaWxlIHdpbGwgYmUgbmFtZWQgYWZ0ZXIgcHJvcGVydHkgW1tpZF1dXG4gICAgICovXG4gICAgbmFtZT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIGlmIChuYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogeW91IGhhdmUgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogeW91ciBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHRydWUsIHRhcmdldCwgJ3Nlc3Npb25EaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkNhbGxpbmcgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvdXIoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEZvciAnc3RyZWFtRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwidW5wdWJsaXNoXCI6IG1ldGhvZCBgU2Vzc2lvbi51bnB1Ymxpc2goKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogbWV0aG9kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcIm5ldHdvcmtEaXNjb25uZWN0XCI6IHRoZSB1c2VyJ3MgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ3N0cmVhbUNyZWF0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFB1Ymxpc2hlciwgdHlwZTogc3RyaW5nLCBzdHJlYW06IFN0cmVhbSwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgUHVibGlzaGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9jYWwgU3RyZWFtXG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW91ciB1cG9uICdcIiArIHRoaXMudHlwZSArIFwiJyBldmVudCBkaXNwYXRjaGVkIGJ5ICdQdWJsaXNoZXInXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHZpZGVvRWxlbWVudENyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuIFNlZVxuICogW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uLlxuICogLSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSB3aGVuZXZlciBhbiBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWRlb0VsZW1lbnRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGVsZW1lbnQgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBlbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQsIHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiZnVuY3Rpb24gTWFwcGVyKClcbntcbiAgdmFyIHNvdXJjZXMgPSB7fTtcblxuXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKVxuICB7XG4gICAgZm9yKHZhciBrZXkgaW4gc291cmNlcylcbiAgICB7XG4gICAgICB2YXIgc291cmNlID0gc291cmNlc1trZXldO1xuXG4gICAgICBmb3IodmFyIGtleTIgaW4gc291cmNlKVxuICAgICAgICBjYWxsYmFjayhzb3VyY2Vba2V5Ml0pO1xuICAgIH07XG4gIH07XG5cbiAgdGhpcy5nZXQgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBpZHNbaWRdO1xuICB9O1xuXG4gIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcblxuICAgIGRlbGV0ZSBpZHNbaWRdO1xuXG4gICAgLy8gQ2hlY2sgaXQncyBlbXB0eVxuICAgIGZvcih2YXIgaSBpbiBpZHMpe3JldHVybiBmYWxzZX1cblxuICAgIGRlbGV0ZSBzb3VyY2VzW3NvdXJjZV07XG4gIH07XG5cbiAgdGhpcy5zZXQgPSBmdW5jdGlvbih2YWx1ZSwgaWQsIHNvdXJjZSlcbiAge1xuICAgIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHNvdXJjZXNbc291cmNlXSA9IGlkcyA9IHt9O1xuXG4gICAgaWRzW2lkXSA9IHZhbHVlO1xuICB9O1xufTtcblxuXG5NYXBwZXIucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG57XG4gIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGlkLCBzb3VyY2UpO1xuICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICByZXR1cm4gdmFsdWU7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gTWFwcGVyO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBKc29uUnBjQ2xpZW50ICA9IHJlcXVpcmUoJy4vanNvbnJwY2NsaWVudCcpO1xuXG5cbmV4cG9ydHMuSnNvblJwY0NsaWVudCAgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uLycpO1xudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5EYXRlLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiArbmV3IERhdGU7XG59O1xuXG52YXIgUElOR19JTlRFUlZBTCA9IDUwMDA7XG5cbnZhciBSRUNPTk5FQ1RJTkcgPSAnUkVDT05ORUNUSU5HJztcbnZhciBDT05ORUNURUQgPSAnQ09OTkVDVEVEJztcbnZhciBESVNDT05ORUNURUQgPSAnRElTQ09OTkVDVEVEJztcblxudmFyIExvZ2dlciA9IGNvbnNvbGU7XG5cbi8qKlxuICpcbiAqIGhlYXJ0YmVhdDogaW50ZXJ2YWwgaW4gbXMgZm9yIGVhY2ggaGVhcnRiZWF0IG1lc3NhZ2UsXG4gKiBzZW5kQ2xvc2VNZXNzYWdlIDogdHJ1ZSAvIGZhbHNlLCBiZWZvcmUgY2xvc2luZyB0aGUgY29ubmVjdGlvbiwgaXQgc2VuZHMgYSBjbG9zZVNlc3Npb24gbWVzc2FnZVxuICogPHByZT5cbiAqIHdzIDoge1xuICogXHR1cmkgOiBVUkkgdG8gY29ubnRlY3QgdG8sXG4gKiAgdXNlU29ja0pTIDogdHJ1ZSAodXNlIFNvY2tKUykgLyBmYWxzZSAodXNlIFdlYlNvY2tldCkgYnkgZGVmYXVsdCxcbiAqIFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuICogXHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcbiAqIFx0b25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG4gKiBcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbiAqIFx0b25lcnJvciA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGVyZSBpcyBhbiBlcnJvclxuICogfSxcbiAqIHJwYyA6IHtcbiAqIFx0cmVxdWVzdFRpbWVvdXQgOiB0aW1lb3V0IGZvciBhIHJlcXVlc3QsXG4gKiBcdHNlc3Npb25TdGF0dXNDaGFuZ2VkOiBjYWxsYmFjayBtZXRob2QgZm9yIGNoYW5nZXMgaW4gc2Vzc2lvbiBzdGF0dXMsXG4gKiBcdG1lZGlhUmVuZWdvdGlhdGlvbjogbWVkaWFSZW5lZ290aWF0aW9uXG4gKiB9XG4gKiA8L3ByZT5cbiAqL1xuZnVuY3Rpb24gSnNvblJwY0NsaWVudChjb25maWd1cmF0aW9uKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgd3NDb25maWcgPSBjb25maWd1cmF0aW9uLndzO1xuXG4gICAgdmFyIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSAtMTtcblxuICAgIHZhciBwaW5nTmV4dE51bSA9IDA7XG4gICAgdmFyIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgdmFyIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgIHZhciBwaW5nSW50ZXJ2YWw7XG5cbiAgICB2YXIgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgdmFyIG9ucmVjb25uZWN0aW5nID0gd3NDb25maWcub25yZWNvbm5lY3Rpbmc7XG4gICAgdmFyIG9ucmVjb25uZWN0ZWQgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGVkO1xuICAgIHZhciBvbmNvbm5lY3RlZCA9IHdzQ29uZmlnLm9uY29ubmVjdGVkO1xuICAgIHZhciBvbmVycm9yID0gd3NDb25maWcub25lcnJvcjtcblxuICAgIGNvbmZpZ3VyYXRpb24ucnBjLnB1bGwgPSBmdW5jdGlvbihwYXJhbXMsIHJlcXVlc3QpIHtcbiAgICAgICAgcmVxdWVzdC5yZXBseShudWxsLCBcInB1c2hcIik7XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNUSU5HIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBSRUNPTk5FQ1RJTkcpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIFJFQ09OTkVDVElORyBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVElORyBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXR1cyA9IFJFQ09OTkVDVElORztcbiAgICAgICAgaWYgKG9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9ucmVjb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uY29ubmVjdGVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05DT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVzZVBpbmcoKTtcblxuICAgICAgICBpZiAob25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9ORVJST1IgLS0tLS0tLS0tLS1cIik7XG5cbiAgICAgICAgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgICAgIGlmIChvbmVycm9yKSB7XG4gICAgICAgICAgICBvbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKHdzQ29uZmlnKTtcblxuICAgIExvZ2dlci5kZWJ1ZygnQ29ubmVjdGluZyB3ZWJzb2NrZXQgdG8gVVJJOiAnICsgd3NDb25maWcudXJpKTtcblxuICAgIHZhciBycGNCdWlsZGVyT3B0aW9ucyA9IHtcbiAgICAgICAgcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5yZXF1ZXN0VGltZW91dCxcbiAgICAgICAgcGluZ19yZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLmhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0XG4gICAgfTtcblxuICAgIHZhciBycGMgPSBuZXcgUnBjQnVpbGRlcihScGNCdWlsZGVyLnBhY2tlcnMuSnNvblJQQywgcnBjQnVpbGRlck9wdGlvbnMsIHdzLFxuICAgICAgICBmdW5jdGlvbihyZXF1ZXN0KSB7XG5cbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVjZWl2ZWQgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IGNvbmZpZ3VyYXRpb24ucnBjW3JlcXVlc3QubWV0aG9kXTtcblxuICAgICAgICAgICAgICAgIGlmIChmdW5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWV0aG9kIFwiICsgcmVxdWVzdC5tZXRob2QgKyBcIiBub3QgcmVnaXN0ZXJlZCBpbiBjbGllbnRcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyhyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKCdFeGNlcHRpb24gcHJvY2Vzc2luZyByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAobWV0aG9kICE9PSAncGluZycpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVxdWVzdDogbWV0aG9kOicgKyBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgcnBjLmVuY29kZShtZXRob2QsIHBhcmFtcywgZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1I6XCIgKyBlcnJvci5tZXNzYWdlICsgXCIgaW4gUmVxdWVzdDogbWV0aG9kOlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyBcIiByZXF1ZXN0OlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1IgREFUQTpcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yLmRhdGEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdFRpbWUgPSByZXF1ZXN0VGltZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT0gdW5kZWZpbmVkICYmIHJlc3VsdC52YWx1ZSAhPT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVzcG9uc2U6ICcgKyBKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIm5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBcIiArIHBpbmdOZXh0TnVtICsgJyAob2xkPScgK1xuICAgICAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiArICcpJyk7XG4gICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBwaW5nTmV4dE51bTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZW5kUGluZygpIHtcbiAgICAgICAgaWYgKGVuYWJsZWRQaW5ncykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG51bGw7XG4gICAgICAgICAgICBpZiAocGluZ05leHROdW0gPT0gMCB8fCBwaW5nTmV4dE51bSA9PSBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbDogY29uZmlndXJhdGlvbi5oZWFydGJlYXQgfHwgUElOR19JTlRFUlZBTFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwaW5nTmV4dE51bSsrO1xuXG4gICAgICAgICAgICBzZWxmLnNlbmQoJ3BpbmcnLCBwYXJhbXMsIChmdW5jdGlvbihwaW5nTnVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJFcnJvciBpbiBwaW5nIHJlcXVlc3QgI1wiICsgcGluZ051bSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubWVzc2FnZSArIFwiKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaW5nTnVtID4gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZXJ2ZXIgZGlkIG5vdCByZXNwb25kIHRvIHBpbmcgbWVzc2FnZSAjXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5nTnVtICsgXCIuIFJlY29ubmVjdGluZy4uLiBcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKHBpbmdOZXh0TnVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUcnlpbmcgdG8gc2VuZCBwaW5nLCBidXQgcGluZyBpcyBub3QgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgKiBJZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0IGhhcyBhbnkgdmFsdWUsIHRoZSBwaW5nLXBvbmcgd2lsbCB3b3JrIHdpdGggdGhlIGludGVydmFsXG4gICAgKiBvZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0XG4gICAgKi9cbiAgICBmdW5jdGlvbiB1c2VQaW5nKCkge1xuICAgICAgICBpZiAoIXBpbmdQb25nU3RhcnRlZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgcGluZyAoaWYgY29uZmlndXJlZClcIilcbiAgICAgICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwaW5nSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzZW5kUGluZywgY29uZmlndXJhdGlvbi5oZWFydGJlYXQpO1xuICAgICAgICAgICAgICAgIHNlbmRQaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NpbmcganNvblJwY0NsaWVudCBleHBsaWNpdGx5IGJ5IGNsaWVudFwiKTtcblxuICAgICAgICBpZiAocGluZ0ludGVydmFsICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xlYXJpbmcgcGluZyBpbnRlcnZhbFwiKTtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGNvbmZpZ3VyYXRpb24uc2VuZENsb3NlTWVzc2FnZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VuZGluZyBjbG9zZSBtZXNzYWdlXCIpXG4gICAgICAgICAgICB0aGlzLnNlbmQoJ2Nsb3NlU2Vzc2lvbicsIG51bGwsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyBjbG9zZSBtZXNzYWdlOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcblx0XHRcdHdzLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIHdzLmZvcmNlQ2xvc2UobWlsbGlzKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlY29ubmVjdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpzb25ScGNDbGllbnQ7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gID0gcmVxdWlyZSgnLi93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cblxuZXhwb3J0cy5XZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb247IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxMy0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIEJyb3dzZXJXZWJTb2NrZXQgPSBnbG9iYWwuV2ViU29ja2V0IHx8IGdsb2JhbC5Nb3pXZWJTb2NrZXQ7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqIEdldCBlaXRoZXIgdGhlIGBXZWJTb2NrZXRgIG9yIGBNb3pXZWJTb2NrZXRgIGdsb2JhbHNcbiAqIGluIHRoZSBicm93c2VyIG9yIHRyeSB0byByZXNvbHZlIFdlYlNvY2tldC1jb21wYXRpYmxlXG4gKiBpbnRlcmZhY2UgZXhwb3NlZCBieSBgd3NgIGZvciBOb2RlLWxpa2UgZW52aXJvbm1lbnQuXG4gKi9cblxuLyp2YXIgV2ViU29ja2V0ID0gQnJvd3NlcldlYlNvY2tldDtcbmlmICghV2ViU29ja2V0ICYmIHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgV2ViU29ja2V0ID0gcmVxdWlyZSgnd3MnKTtcbiAgICB9IGNhdGNoIChlKSB7IH1cbn0qL1xuXG4vL3ZhciBTb2NrSlMgPSByZXF1aXJlKCdzb2NranMtY2xpZW50Jyk7XG5cbnZhciBNQVhfUkVUUklFUyA9IDIwMDA7IC8vIEZvcmV2ZXIuLi5cbnZhciBSRVRSWV9USU1FX01TID0gMzAwMDsgLy8gRklYTUU6IEltcGxlbWVudCBleHBvbmVudGlhbCB3YWl0IHRpbWVzLi4uXG5cbnZhciBDT05ORUNUSU5HID0gMDtcbnZhciBPUEVOID0gMTtcbnZhciBDTE9TSU5HID0gMjtcbnZhciBDTE9TRUQgPSAzO1xuXG4vKlxuY29uZmlnID0ge1xuXHRcdHVyaSA6IHdzVXJpLFxuXHRcdHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG5cdFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuXHRcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuXHRcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuXHRcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYobWljcm9zb2Z0RWRnZSkge1xuICAgICAgICBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzKWNhdGNoKG9uRmFpbHVyZSk7XG4gICAgfVxufSwgJ3Bhc3Mgc2Vjb25kIHBhcmFtZXRlciBvbmx5IGlmIHlvdSB3YW50IHN5c3RlbSBhdWRpbycpO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrLCBjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKSkge1xuICAgICAgICAvLyBtaWNyb3NvZnQgZWRnZSA9PiBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSBnZXRTY3JlZW5JZDsiLCIvLyBnbG9iYWwgdmFyaWFibGVzXG52YXIgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbnZhciBzb3VyY2VJZDtcbnZhciBzY3JlZW5DYWxsYmFjaztcbnZhciBpc0ZpcmVmb3ggPSB0eXBlb2Ygd2luZG93Lkluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJztcbnZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG52YXIgaXNDaHJvbWUgPSAhIXdpbmRvdy5jaHJvbWUgJiYgIWlzT3BlcmE7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG59KTtcblxuLy8gYW5kIHRoZSBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgcmVjZWl2ZWQgbWVzc2FnZXNcbmZ1bmN0aW9uIG9uTWVzc2FnZUNhbGxiYWNrKGRhdGEpIHtcbiAgICAvLyBcImNhbmNlbFwiIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgaWYgKGRhdGEgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgaWYgKHNjcmVlbkNhbGxiYWNrKVxuICAgICAgICAgICAgcmV0dXJuIHNjcmVlbkNhbGxiYWNrKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIG5vdGlmaWVkIGhpcyBwcmVzZW5jZVxuICAgIGlmIChkYXRhID09ICdydGNtdWx0aWNvbm5lY3Rpb24tZXh0ZW5zaW9uLWxvYWRlZCcpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnZGVza3RvcCc7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBzaGFyZWQgdGVtcCBzb3VyY2VJZFxuICAgIGlmIChkYXRhLnNvdXJjZUlkICYmIHNjcmVlbkNhbGxiYWNrKSB7XG4gICAgICAgIHNjcmVlbkNhbGxiYWNrKHNvdXJjZUlkID0gZGF0YS5zb3VyY2VJZCwgZGF0YS5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9PT0gdHJ1ZSk7XG4gICAgfVxufVxuXG4vLyB0aGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiBjaHJvbWUgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCAmIGVuYWJsZWQuXG5mdW5jdGlvbiBpc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZShjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spIHJldHVybjtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKSByZXR1cm4gY2FsbGJhY2sodHJ1ZSk7XG5cbiAgICAvLyBhc2sgZXh0ZW5zaW9uIGlmIGl0IGlzIGF2YWlsYWJsZVxuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXJlLXlvdS10aGVyZScsICcqJyk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICB9IGVsc2UgY2FsbGJhY2sodHJ1ZSk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldEN1c3RvbVNvdXJjZUlkKGFyciwgY2FsbGJhY2spIHtcbiAgICBpZiAoIWFyciB8fCAhYXJyLmZvckVhY2gpIHRocm93ICdcImFyclwiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkgYW5kIGl0IG11c3QgYmUgYW4gYXJyYXkuJztcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcblxuICAgIGlmIChzb3VyY2VJZCkgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcblxuICAgIHNjcmVlbkNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgd2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgJ2dldC1jdXN0b20tc291cmNlSWQnOiBhcnJcbiAgICB9LCAnKicpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWRXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXVkaW8tcGx1cy10YWInLCAnKicpO1xufVxuXG5mdW5jdGlvbiBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMoZXh0ZW5zaW9uaWQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCdub3QtY2hyb21lJyk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggIT0gMikge1xuICAgICAgICBjYWxsYmFjayA9IGV4dGVuc2lvbmlkO1xuICAgICAgICBleHRlbnNpb25pZCA9ICdsZmNnZmVwYWZub2JkbG9lY2NobmZhY2xpYmVuam9sZCc7IC8vIGRlZmF1bHQgZXh0ZW5zaW9uLWlkXG4gICAgfVxuICAgIHZhciBpbWFnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIGltYWdlLnNyYyA9ICdjaHJvbWUtZXh0ZW5zaW9uOi8vJyArIGV4dGVuc2lvbmlkICsgJy9pY29uLnBuZyc7XG4gICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xuICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICB9LCAyMDAwKTtcbiAgICB9O1xuICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKCdub3QtaW5zdGFsbGVkJyk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgdHJ1ZSk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gZXhwbGFpbnMgaG93IHRvIHVzZSBhYm92ZSBtZXRob2RzL29iamVjdHNcbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGNhbGxiYWNrLCBjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICBzb3VyY2VJZCA9ICcnO1xuICAgIHZhciBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMgPSB7XG4gICAgICAgIG1vek1lZGlhU291cmNlOiAnd2luZG93JyxcbiAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgfTtcbiAgICBpZiAoaXNGaXJlZm94KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzKTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCBkZWZpbmVzIGdldFVzZXJNZWRpYSBjb25zdHJhaW50c1xuICAgIC8vIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGNhcHR1cmUgY29udGVudCBvZiBzY3JlZW5cbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBjaHJvbWVNZWRpYVNvdXJjZSxcbiAgICAgICAgICAgIG1heFdpZHRoOiBzY3JlZW4ud2lkdGggPiAxOTIwID8gc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgIG1heEhlaWdodDogc2NyZWVuLmhlaWdodCA+IDEwODAgPyBzY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25hbDogW11cbiAgICB9O1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IHZlcmlmaWVzIGNocm9tZSBleHRlbnNpb24gYXZhaWxhYmlsaXR5XG4gICAgLy8gaWYgaW5zdGFsbGVkIGFuZCBhdmFpbGFibGUgdGhlbiBpdCB3aWxsIGludm9rZSBleHRlbnNpb24gQVBJXG4gICAgLy8gb3RoZXJ3aXNlIGl0IHdpbGwgZmFsbGJhY2sgdG8gY29tbWFuZC1saW5lIGJhc2VkIHNjcmVlbiBjYXB0dXJpbmcgQVBJXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJyAmJiAhc291cmNlSWQpIHtcbiAgICAgICAgaWYgKGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbykge1xuICAgICAgICAgICAgZ2V0U291cmNlSWRXaXRoQXVkaW8oZnVuY3Rpb24gKHNvdXJjZUlkLCBjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCBmcmVlaWNlID0gcmVxdWlyZSgnZnJlZWljZScpO1xuaW1wb3J0IHV1aWQgPSByZXF1aXJlKCd1dWlkJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24ge1xuICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgYXVkaW86IGJvb2xlYW4sXG4gICAgICAgIHZpZGVvOiBib29sZWFuXG4gICAgfTtcbiAgICBzaW11bGNhc3Q6IGJvb2xlYW47XG4gICAgb25pY2VjYW5kaWRhdGU6IChldmVudCkgPT4gdm9pZDtcbiAgICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZDtcbiAgICBtZWRpYVN0cmVhbT86IE1lZGlhU3RyZWFtO1xuICAgIG1vZGU/OiBzdHJpbmc7IC8vIHNlbmRvbmx5LCByZWNvbmx5LCBzZW5kcmVjdlxuICAgIGlkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlciB7XG5cbiAgICBwYzogUlRDUGVlckNvbm5lY3Rpb247XG4gICAgaWQ6IHN0cmluZztcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzID0gKCEhdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiYgdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMubGVuZ3RoID4gMCkgPyB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA6IGZyZWVpY2UoKTtcblxuICAgICAgICB0aGlzLnBjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHsgaWNlU2VydmVyczogdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgfSk7XG4gICAgICAgIHRoaXMuaWQgPSAhIWNvbmZpZ3VyYXRpb24uaWQgPyBjb25maWd1cmF0aW9uLmlkIDogdXVpZC52NCgpO1xuXG4gICAgICAgIHRoaXMucGMub25pY2VjYW5kaWRhdGUgPSBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSA9IGV2ZW50LmNhbmRpZGF0ZTtcbiAgICAgICAgICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ub25pY2VjYW5kaWRhdGUoZXZlbnQuY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5wYy5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKDxSVENJY2VDYW5kaWRhdGU+dGhpcy5pY2VDYW5kaWRhdGVMaXN0LnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIHRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QgdGFraW5nIGludG8gYWNjb3VudCB0aGVcbiAgICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICAgKiBwcm9jZXNzOiBnZW5lcmF0ZXMgdGhlIFNEUCBvZmZlciBhbmQgaW52b2tlcyB0aGUgb25zZHBvZmZlciBjYWxsYmFjay4gVGhpc1xuICAgICAqIGNhbGxiYWNrIGlzIGV4cGVjdGVkIHRvIHNlbmQgdGhlIFNEUCBvZmZlciwgaW4gb3JkZXIgdG8gb2J0YWluIGFuIFNEUFxuICAgICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICAgKi9cbiAgICBzdGFydCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdUaGUgcGVlciBjb25uZWN0aW9uIG9iamVjdCBpcyBpbiBcImNsb3NlZFwiIHN0YXRlLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBhbiBpbnZvY2F0aW9uIG9mIHRoZSBkaXNwb3NlIG1ldGhvZCBiZWZvcmUgYWNjZXB0aW5nIGluIHRoZSBkaWFsb2d1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRTdHJlYW0odGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gW0hhY2tdIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDM1NThcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9PT0gJ3NlbmRvbmx5JyAmJlxuICAgICAgICAgICAgICAgIChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS52ZXJzaW9uIS50b1N0cmluZygpLnN1YnN0cmluZygwLCAyKSA9PT0gJzM5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgZnJlZXMgdGhlIHJlc291cmNlcyB1c2VkIGJ5IFdlYlJ0Y1BlZXJcbiAgICAgKi9cbiAgICBkaXNwb3NlKCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIHRoaXMucGMuZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChzdHIgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVN0b3Aoc3RyKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAgICAgICAgICAgLy8gaWYodmlkZW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbSh2aWRlb1N0cmVhbSk7XG4gICAgICAgICAgICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogMSkgRnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIG9mZmVyLCBzZXRzIGl0IGFzIGxvY2FsIGRlc2NyaXB0aW9uIGFuZCByZXR1cm5zIHRoZSBvZmZlciBwYXJhbVxuICAgICAqIHRvIHNlbmQgdG8gT3BlblZpZHUgU2VydmVyICh3aWxsIGJlIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gb2Ygb3RoZXIgcGVlcilcbiAgICAgKi9cbiAgICBnZW5lcmF0ZU9mZmVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgb2ZmZXJBdWRpbywgb2ZmZXJWaWRlbyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICBvZmZlclZpZGVvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlclZpZGVvKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUlRDUGVlckNvbm5lY3Rpb24gY29uc3RyYWludHM6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuXG4gICAgICAgICAgICB0aGlzLnBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpO1xuICAgICAgICAgICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0xvY2FsIGRlc2NyaXB0aW9uIGlzIG5vdCBkZWZpbmVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDIpIEZ1bmN0aW9uIHRvIGludm9rZSB3aGVuIGEgU0RQIG9mZmVyIGlzIHJlY2VpdmVkLiBTZXRzIGl0IGFzIHJlbW90ZSBkZXNjcmlwdGlvbixcbiAgICAgKiBnZW5lcmF0ZXMgYW5kIGFuc3dlciBhbmQgcmV0dXJucyBpdCB0byBzZW5kIGl0IHRvIE9wZW5WaWR1IFNlcnZlclxuICAgICAqL1xuICAgIHByb2Nlc3NPZmZlcihzZHBPZmZlcjogc3RyaW5nKTogUHJvbWlzZTxDb25zdHJhaW5ET01TdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBPZmZlclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU0RQIG9mZmVyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuY3JlYXRlQW5zd2VyKCk7XG4gICAgICAgICAgICAgICAgfSkudGhlbihhbnN3ZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBhbnN3ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbERlc2NyaXB0aW9uID0gdGhpcy5wYy5sb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKDxzdHJpbmc+bG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDMpIEZ1bmN0aW9uIGludm9rZWQgd2hlbiBhIFNEUCBhbnN3ZXIgaXMgcmVjZWl2ZWQuIEZpbmFsIHN0ZXAgaW4gU0RQIG5lZ290aWF0aW9uLCB0aGUgcGVlclxuICAgICAqIGp1c3QgbmVlZHMgdG8gc2V0IHRoZSBhbnN3ZXIgYXMgaXRzIHJlbW90ZSBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIHByb2Nlc3NBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnUlRDUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZS5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdGFibGUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtU3RvcChzdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHtcbiAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclJlY3Zvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRyZWN2IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRyZWN2JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzRW5hYmxlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNJbnRlcnZhbElkOiBOb2RlSlMuVGltZXI7XG4gICAgcHJpdmF0ZSBzdGF0c0ludGVydmFsID0gMTtcbiAgICBwcml2YXRlIHN0YXRzOiBhbnkgPSB7XG4gICAgICAgIGluYm91bmQ6IHtcbiAgICAgICAgICAgIGF1ZGlvOiB7XG4gICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwLFxuICAgICAgICAgICAgICAgIGZyYW1lc0RlY29kZWQ6IDAsXG4gICAgICAgICAgICAgICAgbmFja0NvdW50OiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNFbmNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHsgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWJSdGMgc3RhdHMgZW5hYmxlZCBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGNvbnN0IGluc3RydW1lbnRhdGlvbiA9IEpTT04ucGFyc2UoZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgdGhpcy5zdGF0c0ludGVydmFsID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KGluc3RydW1lbnRhdGlvbikpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRzSW50ZXJ2YWwgKiAxMDAwKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIHN0b3BwZWQgZm9yIGRpc3Bvc2VkIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLFxuICAgICAgICAgICAgICAgIChzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxvY2FsQ2FuZGlkYXRlSWQsIHJlbW90ZUNhbmRpZGF0ZUlkLCBnb29nQ2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gc3RhdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAnbG9jYWxjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlc1tzdGF0LmlkXSA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0LnR5cGUgPT09ICdyZW1vdGVjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAnZ29vZ0NhbmRpZGF0ZVBhaXInICYmIChzdGF0Lmdvb2dBY3RpdmVDb25uZWN0aW9uID09PSAndHJ1ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVJZCA9IHN0YXQubG9jYWxDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzdGF0LnJlbW90ZUNhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaW5hbExvY2FsQ2FuZGlkYXRlID0gbG9jYWxDYW5kaWRhdGVzW2xvY2FsQ2FuZGlkYXRlSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZmluYWxMb2NhbENhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwQWRkcmVzcykgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZS5yYXcgPSAhIWNhbmRbMF0gPyBjYW5kWzBdLmNhbmRpZGF0ZSA6ICdFUlJPUjogQ2Fubm90IGZpbmQgbG9jYWwgY2FuZGlkYXRlIGluIGxpc3Qgb2Ygc2VudCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSBsb2NhbCBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSByZW1vdGVDYW5kaWRhdGVzW3JlbW90ZUNhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucG9ydE51bWJlcikgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIHJlbW90ZSBjYW5kaWRhdGUgaW4gbGlzdCBvZiByZWNlaXZlZCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgcmVtb3RlIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlOiBmaW5hbExvY2FsQ2FuZGlkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZTogZmluYWxSZW1vdGVDYW5kaWRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdTZWxlY3RlZCBJQ0UgY2FuZGlkYXRlIGluZm8gb25seSBhdmFpbGFibGUgZm9yIENocm9tZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBodHRwOiBYTUxIdHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgY29uc3QgdXJsOiBzdHJpbmcgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmh0dHBFbmRwb2ludDtcbiAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIHVybCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcblxuICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7IC8vIENhbGwgYSBmdW5jdGlvbiB3aGVuIHRoZSBzdGF0ZSBjaGFuZ2VzLlxuICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQgJiYgaHR0cC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2ViUnRjIHN0YXRzIHN1Y2Nlc3NmdWxseSBzZW50IHRvICcgKyB1cmwgKyAnIGZvciBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0dHAuc2VuZChqc29uKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmID0gKHN0YXRzKSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQucmVtb3RlSWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGppdCA9IHN0YXQuaml0dGVyICogMTAwMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6IGppdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IChzdGF0LnBhY2tldHNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogJ3BhY2tldHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQubmFja0NvdW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkID0gc3RhdC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lm5hY2tDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QgPSBzdGF0LnBhY2tldHNMb3N0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChzdGF0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgaW5ib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdvdXRib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ3NzcmMnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnYnl0ZXNSZWNlaXZlZCcgaW4gc3RhdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXQubWVkaWFUeXBlID09PSAnYXVkaW8nICYmICdhdWRpb091dHB1dExldmVsJyBpbiBzdGF0KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJyAmJiAncXBTdW0nIGluIHN0YXQpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5ib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBzdGF0Lmdvb2dKaXR0ZXJCdWZmZXJNcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQuZ29vZ05hY2tzU2VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2J5dGVzU2VudCcgaW4gc3RhdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG91dGJvdW5kLXJ0cFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSwgZiwgKGVycm9yKSA9PiB7IGNvbnNvbGUubG9nKGVycm9yKTsgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZSk7XG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG5cbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2Vba2V5XSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2gocmVwb3J0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHN1Y2Nlc3NDYiwgZmFpbHVyZUNiKSB7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhudWxsKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZhaWx1cmVDYik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0sIG51bGwsIGZhaWx1cmVDYik7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iXX0= diff --git a/openvidu-insecure-angular/package-lock.json b/openvidu-insecure-angular/package-lock.json index 8d45ce67..8f619a35 100644 --- a/openvidu-insecure-angular/package-lock.json +++ b/openvidu-insecure-angular/package-lock.json @@ -386,11 +386,6 @@ "semver-intersect": "^1.1.2" } }, - "@types/platform": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/platform/-/platform-1.3.1.tgz", - "integrity": "sha1-WmZhZpPjnzEbPyxkx3zyJJ49gyU=" - }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -2908,14 +2903,6 @@ "map-cache": "^0.2.2" } }, - "freeice": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/freeice/-/freeice-2.2.0.tgz", - "integrity": "sha1-+dKzspZ8C51a8/FFPTXfXobVF8M=", - "requires": { - "normalice": "^1.0.0" - } - }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -2970,7 +2957,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -2991,14 +2979,16 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -3011,17 +3001,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -3113,7 +3106,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": "^2.1.0" } }, "ignore-walk": { @@ -3122,7 +3115,7 @@ "dev": true, "optional": true, "requires": { - "minimatch": "3.0.4" + "minimatch": "^3.0.4" } }, "inflight": { @@ -3138,7 +3131,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -3150,8 +3144,9 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "isarray": { @@ -3164,19 +3159,22 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "5.1.1", "yallist": "3.0.2" @@ -3195,6 +3193,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -3211,9 +3210,9 @@ "dev": true, "optional": true, "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.21", - "sax": "1.2.4" + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" } }, "node-pre-gyp": { @@ -3240,8 +3239,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" + "abbrev": "1", + "osenv": "^0.1.4" } }, "npm-bundled": { @@ -3256,8 +3255,8 @@ "dev": true, "optional": true, "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" } }, "npmlog": { @@ -3275,7 +3274,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3287,6 +3287,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1.0.2" } @@ -3309,8 +3310,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "path-is-absolute": { @@ -3331,10 +3332,10 @@ "dev": true, "optional": true, "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { @@ -3372,7 +3373,8 @@ "safe-buffer": { "version": "5.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3408,10 +3410,11 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -3420,15 +3423,16 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -3470,12 +3474,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -3758,14 +3764,6 @@ } } }, - "hark": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hark/-/hark-1.2.0.tgz", - "integrity": "sha1-FUtSjBkKCDSSDb1Ys+ZZVZBEeEo=", - "requires": { - "wildemitter": "^1.2.0" - } - }, "has": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", @@ -4149,7 +4147,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true }, "internal-ip": { "version": "1.2.0", @@ -5058,11 +5057,6 @@ "trim-newlines": "^1.0.0" } }, - "merge": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", - "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=" - }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -5607,11 +5601,6 @@ "abbrev": "1" } }, - "normalice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/normalice/-/normalice-1.0.1.tgz", - "integrity": "sha1-A0NcLuzVYxprygLaOTDsPjRagPc=" - }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -5843,28 +5832,3848 @@ } }, "openvidu-browser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/openvidu-browser/-/openvidu-browser-2.0.0.tgz", - "integrity": "sha1-1o2kBIx1qrjKfdW4qu7aHNPv5Hs=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/openvidu-browser/-/openvidu-browser-2.2.0.tgz", + "integrity": "sha1-tvUr8+PdKlwpBICf2uIm5rhzTYk=", "requires": { - "@types/node": "^9.6.7", - "@types/platform": "^1.3.1", + "@types/node": "10.3.2", + "@types/platform": "1.3.1", "freeice": "2.2.0", "hark": "1.2.0", - "inherits": "2.0.3", - "merge": "1.2.0", - "platform": "^1.3.5", - "sdp-translator": "0.1.24", - "ua-parser-js": "0.7.17", + "platform": "1.3.5", "uuid": "3.2.1", - "webrtc-adapter": "6.1.4", + "webrtc-adapter": "6.2.1", "wolfy87-eventemitter": "5.2.4" }, "dependencies": { + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" + }, + "@types/fs-extra": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.1.tgz", + "integrity": "sha512-h3wnflb+jMTipvbbZnClgA2BexrT4w0GcfoCz5qyxd0IRsbqhLSyesM6mqZTAnhbVmhyTm5tuxfRu9R+8l+lGw==", + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "5.0.35", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz", + "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==", + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/handlebars": { + "version": "4.0.36", + "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.36.tgz", + "integrity": "sha512-LjNiTX7TY7wtuC6y3QwC93hKMuqYhgV9A1uXBKNvZtVC8ZvyWAjZkJ5BvT0K7RKqORRYRLMrqCxpw5RgS+MdrQ==" + }, + "@types/highlight.js": { + "version": "9.12.2", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.2.tgz", + "integrity": "sha512-y5x0XD/WXDaGSyiTaTcKS4FurULJtSiYbGTeQd0m2LYZGBcZZ/7fM6t5H/DzeUF+kv8y6UfmF6yJABQsHcp9VQ==" + }, + "@types/lodash": { + "version": "4.14.104", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.104.tgz", + "integrity": "sha512-ufQcVg4daO8xQ5kopxRHanqFdL4AI7ondQkV+2f+7mz3gvp0LkBx2zBRC6hfs3T87mzQFmf5Fck7Fi145Ul6NQ==" + }, + "@types/marked": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.3.0.tgz", + "integrity": "sha512-CSf9YWJdX1DkTNu9zcNtdCcn6hkRtB5ILjbhRId4ZOQqx30fXmdecuaXhugQL6eyrhuXtaHJ7PHI+Vm7k9ZJjg==" + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + }, "@types/node": { - "version": "9.6.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.15.tgz", - "integrity": "sha512-16zIiQkIZBc1ZpfrOZZZ/6LKDixPiAIZq5q1YE1stxG4Ic1VmQlkNNWGBydqBFcX8eS+m/Dd4z5HzDa+q0b2Xg==" + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.2.tgz", + "integrity": "sha512-9NfEUDp3tgRhmoxzTpTo+lq+KIVFxZahuRX0LHF/9IzKHaWuoWsIrrJ61zw5cnnlGINX8lqJzXYfQTOICS5Q+A==" + }, + "@types/platform": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/platform/-/platform-1.3.1.tgz", + "integrity": "sha512-XI6JKLFNBmkADRd2FtUYtEuq5LDKTNXwUIodV3ZfTNkA+g4yo+rXXXdZL3fTE24S92BjpiEVaL3f64Fxm2JOgg==" + }, + "@types/shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha512-M2giRw93PxKS7YjU6GZjtdV9HASdB7TWqizBXe4Ju7AqbKlWvTr0gNO92XH56D/gMxqD/jNHLNfC5hA34yGqrQ==", + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "JSONStream": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz", + "integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + }, + "acorn-dynamic-import": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", + "requires": { + "acorn": "^5.0.0" + } + }, + "acorn-node": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.5.2.tgz", + "integrity": "sha512-krFKvw/d1F17AN3XZbybIUzEY4YEPNiGo05AfP3dBlfVKrMHETKpgjpuZkSF8qDNt9UkQcqj7am8yJLseklCMg==", + "requires": { + "acorn": "^5.7.1", + "acorn-dynamic-import": "^3.0.0", + "xtend": "^4.0.1" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + } + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=" + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=" + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + }, + "autoprefixer-core": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/autoprefixer-core/-/autoprefixer-core-5.2.1.tgz", + "integrity": "sha1-5kDEFK5Bmq4hwa1DyOoPPbgqVm0=", + "requires": { + "browserslist": "~0.4.0", + "caniuse-db": "^1.0.30000214", + "num2fraction": "^1.1.0", + "postcss": "~4.1.12" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", + "requires": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "requires": { + "JSONStream": "^1.0.3", + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + } + } + }, + "browserify": { + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.2.tgz", + "integrity": "sha512-fMES05wq1Oukts6ksGUU2TMVHHp06LyQt0SIwbXIHm7waSrQmNBZePsU0iM/4f94zbvb/wHma+D1YrdzWYnF/A==", + "requires": { + "JSONStream": "^1.0.3", + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^1.11.0", + "browserify-zlib": "~0.2.0", + "buffer": "^5.0.2", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.0", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^2.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.0.0", + "labeled-stream-splicer": "^2.0.0", + "mkdirp": "^0.5.0", + "module-deps": "^6.0.0", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^2.0.0", + "stream-http": "^2.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.10.1", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", + "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-0.4.0.tgz", + "integrity": "sha1-O9SrkZncG5FQ1NbbpNnTqrvIbdQ=", + "requires": { + "caniuse-db": "^1.0.30000153" + } + }, + "buffer": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.1.0.tgz", + "integrity": "sha512-YkIRgwsZwJWTnyQrsBTWefizHh+8GYj3kbL1BTiAQ/9pwpino0G7B2gp5tx/FUBqUlvtxV85KNR3mwfAtv15Yw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=" + }, + "cached-path-relative": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=" + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caniuse-db": { + "version": "1.0.30000856", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000856.tgz", + "integrity": "sha1-++u5mr4VpWVPx3R+u1MVvf3jNY8=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "optional": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "optional": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "optional": true + } + } + }, + "coffeescript": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", + "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=" + }, + "color-convert": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "requires": { + "color-name": "1.1.1" + } + }, + "color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "continuable-cache": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=" + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.9.tgz", + "integrity": "sha1-vWf5bAfvtjA7f+lMHpefiEeOCjk=", + "requires": { + "lru-cache": "^2.5.0" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "csproj2ts": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/csproj2ts/-/csproj2ts-1.1.0.tgz", + "integrity": "sha512-sk0RTT51t4lUNQ7UfZrqjQx7q4g0m3iwNA6mvyh7gLsgQYvwKzfdyoAgicC9GqJvkoIkU0UmndV9c7VZ8pJ45Q==", + "requires": { + "es6-promise": "^4.1.1", + "lodash": "^4.17.4", + "semver": "^5.4.1", + "xml2js": "^0.4.19" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } + }, + "dargs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", + "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "requires": { + "JSONStream": "^1.0.3", + "shasum": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "requires": { + "repeating": "^2.0.0" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + }, + "detective": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.1.0.tgz", + "integrity": "sha512-TFHMqfOvxlgrfVzTEkNBSh9SvSNX/HfF4OFI2QFGCyPm02EsyILqnUeb5P6q7JZ3SFNTBL5t2sePRgrN4epUWQ==", + "requires": { + "acorn-node": "^1.3.0", + "defined": "^1.0.0", + "minimist": "^1.1.1" + } + }, + "diff": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.3.2.tgz", + "integrity": "sha1-/Qeh8fiRUZ2ZBaTJqJ3PWnC2YDc=" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "requires": { + "readable-stream": "^2.0.2" + } + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "error": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "requires": { + "string-template": "~0.2.1", + "xtend": "~4.0.0" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es6-promise": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz", + "integrity": "sha1-lu258v2wGZWCKyY92KratnSBgbw=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=" + }, + "events": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", + "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "^2.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-sync-cmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", + "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=" + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "requires": { + "glob": "~5.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "^1.0.1" + } + }, + "freeice": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/freeice/-/freeice-2.2.0.tgz", + "integrity": "sha1-+dKzspZ8C51a8/FFPTXfXobVF8M=", + "requires": { + "normalice": "^1.0.0" + } + }, + "fs-extra": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "requires": { + "globule": "^1.0.0" + } + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "^2.0.0" + } + }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grunt": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.3.tgz", + "integrity": "sha512-/JzmZNPfKorlCrrmxWqQO4JVodO+DVd5XX4DkocL/1WlLlKVLE9+SdEIempOAxDhWPysLle6afvn/hg7Ck2k9g==", + "requires": { + "coffeescript": "~1.10.0", + "dateformat": "~1.0.12", + "eventemitter2": "~0.4.13", + "exit": "~0.1.1", + "findup-sync": "~0.3.0", + "glob": "~7.0.0", + "grunt-cli": "~1.2.0", + "grunt-known-options": "~1.1.0", + "grunt-legacy-log": "~2.0.0", + "grunt-legacy-util": "~1.1.1", + "iconv-lite": "~0.4.13", + "js-yaml": "~3.5.2", + "minimatch": "~3.0.2", + "mkdirp": "~0.5.1", + "nopt": "~3.0.6", + "path-is-absolute": "~1.0.0", + "rimraf": "~2.6.2" + }, + "dependencies": { + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "grunt-autoprefixer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/grunt-autoprefixer/-/grunt-autoprefixer-3.0.4.tgz", + "integrity": "sha1-/kLiR7z6ucKSoSwGLa1PNb3pAsU=", + "requires": { + "autoprefixer-core": "^5.1.7", + "chalk": "~1.0.0", + "diff": "~1.3.0", + "postcss": "^4.1.11" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz", + "integrity": "sha1-s89O0P9Tl8mcdbj2edsvUoMfltw=", + "requires": { + "ansi-styles": "^2.0.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^1.0.3", + "strip-ansi": "^2.0.1", + "supports-color": "^1.3.0" + } + }, + "supports-color": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", + "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=" + } + } + }, + "grunt-cli": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", + "requires": { + "findup-sync": "~0.3.0", + "grunt-known-options": "~1.1.0", + "nopt": "~3.0.6", + "resolve": "~1.1.0" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + } + } + }, + "grunt-contrib-copy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", + "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=", + "requires": { + "chalk": "^1.1.1", + "file-sync-cmp": "^0.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "grunt-contrib-sass": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-sass/-/grunt-contrib-sass-1.0.0.tgz", + "integrity": "sha1-gGg4JRy8DhqU1k1RXN00z2dNcBs=", + "requires": { + "async": "^0.9.0", + "chalk": "^1.0.0", + "cross-spawn": "^0.2.3", + "dargs": "^4.0.0", + "which": "^1.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "grunt-contrib-uglify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-3.3.0.tgz", + "integrity": "sha512-W9O7lJE3PlD8VCc5fyaf98QV7f5wEDiU4PBIh0+/6UBbk2LhgzEFS0/p+taH5UD3+PlEn7QPN0o06Z0To6SqXw==", + "requires": { + "chalk": "^1.0.0", + "maxmin": "^1.1.0", + "uglify-js": "~3.3.0", + "uri-path": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "uglify-js": { + "version": "3.3.28", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.28.tgz", + "integrity": "sha512-68Rc/aA6cswiaQ5SrE979UJcXX+ADA1z33/ZsPd+fbAiVdjZ16OXdbtGO+rJUUBgK6qdf3SOPhQf3K/ybF5Miw==", + "requires": { + "commander": "~2.15.0", + "source-map": "~0.6.1" + } + } + } + }, + "grunt-contrib-watch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", + "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", + "requires": { + "async": "^2.6.0", + "gaze": "^1.1.0", + "lodash": "^4.17.10", + "tiny-lr": "^1.1.1" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + } + } + }, + "grunt-known-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz", + "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=" + }, + "grunt-legacy-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz", + "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==", + "requires": { + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.0.0", + "hooker": "~0.2.3", + "lodash": "~4.17.5" + } + }, + "grunt-legacy-log-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz", + "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==", + "requires": { + "chalk": "~2.4.1", + "lodash": "~4.17.10" + } + }, + "grunt-legacy-util": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz", + "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==", + "requires": { + "async": "~1.5.2", + "exit": "~0.1.1", + "getobject": "~0.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.10", + "underscore.string": "~3.3.4", + "which": "~1.3.0" + } + }, + "grunt-string-replace": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/grunt-string-replace/-/grunt-string-replace-1.3.1.tgz", + "integrity": "sha1-YzoDvHhIKg4OH5339kWBH8H7sWI=", + "requires": { + "async": "^2.0.0", + "chalk": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "grunt-ts": { + "version": "6.0.0-beta.19", + "resolved": "https://registry.npmjs.org/grunt-ts/-/grunt-ts-6.0.0-beta.19.tgz", + "integrity": "sha512-YRC8yXnm9DxAbucfFO32aVQraL9xeimWwOTNIsoHyyEE/FR/AHo9uzxhvSp0k6u2OM1iwS5JpDw48bdQmC0imQ==", + "requires": { + "chokidar": "^1.6.1", + "csproj2ts": "^1.1.0", + "detect-indent": "^4.0.0", + "detect-newline": "^2.1.0", + "es6-promise": "~0.1.1", + "jsmin2": "^1.2.1", + "lodash": "^4.17.4", + "ncp": "0.5.1", + "rimraf": "2.2.6", + "semver": "^5.3.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "es6-promise": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-0.1.2.tgz", + "integrity": "sha1-8RLCn+paCZhTn8tqL9IUQ9KPBfc=" + }, + "rimraf": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", + "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=" + } + } + }, + "gzip-size": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", + "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=", + "requires": { + "browserify-zlib": "^0.1.4", + "concat-stream": "^1.4.1" + }, + "dependencies": { + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "requires": { + "pako": "~0.2.0" + } + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + } + } + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "requires": { + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": ">=0.0.4" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "optional": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + } + } + } + } + }, + "hark": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hark/-/hark-1.2.0.tgz", + "integrity": "sha512-3j2ENaCG3XCuDF2MsRkoJyqoTzdTjDxPAENdpYXoAmK2XMJVcf1RVfriOC8FwJJhEvVeTcd7WaQ+cI66jP9Buw==", + "requires": { + "wildemitter": "^1.2.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-1.0.3.tgz", + "integrity": "sha1-wLWxYV2eOCsP9nFp2We0JeSMpTg=", + "requires": { + "ansi-regex": "^1.1.0", + "get-stdin": "^4.0.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.4.tgz", + "integrity": "sha512-A6RlQvvZEtFS5fLU43IDu0QUmBy+fDO9VMdTXvufKwIkt/rFfvICAViCax5fbDO4zdNzaC3/27ZhKUok5bAJyw==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "highlight.js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=" + }, + "hosted-git-info": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==" + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=" + }, + "http-parser-js": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=" + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "^2.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "requires": { + "source-map": "~0.5.3" + } + }, + "insert-module-globals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", + "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", + "requires": { + "JSONStream": "^1.0.3", + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "js-base64": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz", + "integrity": "sha1-8OgK4DmkvWVLXygfyT8EqRSn/M4=" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", + "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=", + "requires": { + "argparse": "^1.0.2", + "esprima": "^2.6.0" + } + }, + "jsmin2": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jsmin2/-/jsmin2-1.2.1.tgz", + "integrity": "sha1-iPvi+/dfCpH2YCD9mBzWk/S/5X4=" + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "labeled-stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", + "integrity": "sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg==", + "requires": { + "inherits": "^2.0.1", + "isarray": "^2.0.4", + "stream-splicer": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", + "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==" + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "optional": true + }, + "livereload-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", + "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==" + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "marked": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + }, + "maxmin": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", + "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=", + "requires": { + "chalk": "^1.0.0", + "figures": "^1.0.1", + "gzip-size": "^1.0.0", + "pretty-bytes": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "module-deps": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.1.0.tgz", + "integrity": "sha512-NPs5N511VD1rrVJihSso/LiBShRbJALYBKzDW91uZYy7BpjnO4bGnZL3HjZ9yKcFdZUWwaYjDz9zxbuP7vKMuQ==", + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "cached-path-relative": "^1.0.0", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.0.2", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "optional": true + }, + "ncp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.5.1.tgz", + "integrity": "sha1-dDmFMW49tFkoG1hxaehFc1oFQ58=" + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "normalice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/normalice/-/normalice-1.0.1.tgz", + "integrity": "sha1-A0NcLuzVYxprygLaOTDsPjRagPc=" + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + } + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "platform": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", + "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==" + }, + "postcss": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-4.1.16.tgz", + "integrity": "sha1-TESbTIr53zyvbTf44eV10DYXWNw=", + "requires": { + "es6-promise": "~2.3.0", + "js-base64": "~2.1.8", + "source-map": "~0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.1.0" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "randomatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "raw-body": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", + "requires": { + "bytes": "1", + "string_decoder": "0.10" + }, + "dependencies": { + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "requires": { + "readable-stream": "^2.0.2" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "requires": { + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "^1.0.0" + } + }, + "resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "requires": { + "path-parse": "^1.0.5" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "optional": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rtcpeerconnection-shim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.11.tgz", + "integrity": "sha512-Vns4aLKXTrLZCjDOlPZL1nymFiSpqs15TeF+wG1TSLO1kXRrCuT5SjL+Zb8RCP7t3JNfnCuTn+qMlCGQu5NvhQ==", + "requires": { + "sdp": "^2.6.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-json-parse": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "sdp": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-2.7.4.tgz", + "integrity": "sha512-0+wTfgvUUEGcvvFoHIC0aiGbx6gzwAUm8FkKt5Oqqkjf9mEEDLgwnoDKX7MYTGXrNNwzikVbutJ+OVNAGmJBQw==" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "requires": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, + "shelljs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", + "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", + "requires": { + "ansi-regex": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "requires": { + "minimist": "^1.1.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "requires": { + "acorn-node": "^1.2.0" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "requires": { + "process": "~0.11.0" + } + }, + "tiny-lr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", + "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", + "requires": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "tsconfig": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz", + "integrity": "sha1-X0J45wGACWeo/Dg/0ZZIh48qbjo=", + "requires": { + "any-promise": "^1.3.0", + "parse-json": "^2.2.0", + "strip-bom": "^2.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "tsify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tsify/-/tsify-4.0.0.tgz", + "integrity": "sha512-A33g5azPh2KDo/gbcSHpSo2m8l5FYC3SdjD5qNpBT+LP758HIGXT6cLko+aJhyFDRU5nCT/zQvfIq/5GQNRsoA==", + "requires": { + "convert-source-map": "^1.1.0", + "fs.realpath": "^1.0.0", + "object-assign": "^4.1.0", + "semver": "^5.1.0", + "through2": "^2.0.0", + "tsconfig": "^5.0.3" + } + }, + "tslib": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.2.tgz", + "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw==" + }, + "tslint": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.10.0.tgz", + "integrity": "sha1-EeJrzLiK+gLdDZlWyuPUVAtfVMM=", + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.12.1" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } + } + }, + "tsutils": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.27.1.tgz", + "integrity": "sha512-AE/7uzp32MmaHvNNFES85hhUDHFdFZp6OAiZcd6y4ZKKIg6orJTm8keYWBhIhrJQH3a4LzNKat7ZPXZt5aTf6w==", + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedoc": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.11.1.tgz", + "integrity": "sha512-jdNIoHm5wkZqxQTe/g9AQ3LKnZyrzHXqu6A/c9GUOeJyBWLxNr7/Dm3rwFvLksuxRNwTvY/0HRDU9sJTa9WQSg==", + "requires": { + "@types/fs-extra": "5.0.1", + "@types/handlebars": "4.0.36", + "@types/highlight.js": "9.12.2", + "@types/lodash": "4.14.104", + "@types/marked": "0.3.0", + "@types/minimatch": "3.0.3", + "@types/shelljs": "0.7.8", + "fs-extra": "^5.0.0", + "handlebars": "^4.0.6", + "highlight.js": "^9.0.0", + "lodash": "^4.17.5", + "marked": "^0.3.17", + "minimatch": "^3.0.0", + "progress": "^2.0.0", + "shelljs": "^0.8.1", + "typedoc-default-themes": "^0.5.0" + }, + "dependencies": { + "typescript": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.1.tgz", + "integrity": "sha512-h6pM2f/GDchCFlldnriOhs1QHuwbnmj6/v7499eMHqPeW4V2G0elua2eIc2nu8v2NdHV0Gm+tzX83Hr6nUFjQA==" + } + } + }, + "typedoc-default-themes": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz", + "integrity": "sha1-bcJDPnjti+qOiHo6zeLzF4W9Yic=" + }, + "typedoc-plugin-sourcefile-url": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typedoc-plugin-sourcefile-url/-/typedoc-plugin-sourcefile-url-1.0.3.tgz", + "integrity": "sha1-+7zEtxvZLS95TRwWmkgAQilrH+Y=" + }, + "typescript": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.1.tgz", + "integrity": "sha512-h6pM2f/GDchCFlldnriOhs1QHuwbnmj6/v7499eMHqPeW4V2G0elua2eIc2nu8v2NdHV0Gm+tzX83Hr6nUFjQA==" + }, + "uglify-js": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.0.tgz", + "integrity": "sha512-Jcf5naPkX3rVPSQpRn9Vm6Rr572I1gTtR9LnqKgXjmOgfYQ/QS0V2WRStFR53Bdj520M66aCZqt9uzYXgtGrJQ==", + "requires": { + "commander": "~2.15.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==" + }, + "undeclared-identifiers": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz", + "integrity": "sha512-13EaeocO4edF/3JKime9rD7oB6QI8llAGhgn5fKOPyfkJbRb6NFv9pYV6dFEmpa4uRjKeBqLZP8GpuzqHlKDMQ==", + "requires": { + "acorn-node": "^1.3.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "underscore.string": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz", + "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=", + "requires": { + "sprintf-js": "^1.0.3", + "util-deprecate": "^1.0.2" + } + }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" + }, + "uri-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", + "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vm-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.0.1.tgz", + "integrity": "sha512-EqzLchIMYLBjRPoqVsEkZOa/4Vr2RfOWbd58F+I/Gj79AYTrsseMunxbbSkbYfrqZaXSuPBBXNSOhtJgg0PpmA==" + }, + "webrtc-adapter": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-6.2.1.tgz", + "integrity": "sha1-TQ7aWS8n1fMojqiuEcEkWsFW1nY=", + "requires": { + "rtcpeerconnection-shim": "^1.2.10", + "sdp": "^2.7.0" + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "wildemitter": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/wildemitter/-/wildemitter-1.2.0.tgz", + "integrity": "sha1-Kd06ctaZw+J53QIcPNIVC4LJohE=" + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "optional": true + }, + "wolfy87-eventemitter": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.4.tgz", + "integrity": "sha512-yUOUSIzZxqBeu6VdnigqYHwwjy5N3CRX5XSHh/YcVpy+Qsx+HkHaEWdmdyAr3NvyBYDraOa5EfNIbu47T5QzIA==" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "optional": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "optional": true + } + } } } }, @@ -6210,11 +10019,6 @@ "find-up": "^2.1.0" } }, - "platform": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", - "integrity": "sha1-+2lYxpbgfikY0u7aDwvJRI1zNEQ=" - }, "portfinder": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", @@ -6907,14 +10711,6 @@ "inherits": "^2.0.1" } }, - "rtcpeerconnection-shim": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.11.tgz", - "integrity": "sha1-3yskVgIDZdrya/jBNVI7yi3rJSs=", - "requires": { - "sdp": "^2.6.0" - } - }, "run-queue": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", @@ -7065,24 +10861,6 @@ } } }, - "sdp": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/sdp/-/sdp-2.7.3.tgz", - "integrity": "sha1-7Rd+tAdKoyE+FQ50qastBq5uXb8=" - }, - "sdp-transform": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/sdp-transform/-/sdp-transform-1.5.3.tgz", - "integrity": "sha1-im0Pi9aZzjq8MQuksc3lmJKKCBY=" - }, - "sdp-translator": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/sdp-translator/-/sdp-translator-0.1.24.tgz", - "integrity": "sha1-g/uNY0pj8VzZlEI33ZC9QGkGxvM=", - "requires": { - "sdp-transform": "1.5.*" - } - }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -8111,11 +11889,6 @@ "integrity": "sha1-LWFaHvSu5PV0Qlzf9wJu34GRmDY=", "dev": true }, - "ua-parser-js": { - "version": "0.7.17", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", - "integrity": "sha1-6exflJi57JEOeuOsYmqAXE0J7Kw=" - }, "uglify-js": { "version": "3.3.25", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.25.tgz", @@ -8425,7 +12198,8 @@ "uuid": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha1-EsUou51Y0LkmXZovbw/ovhf/HxQ=" + "integrity": "sha1-EsUou51Y0LkmXZovbw/ovhf/HxQ=", + "dev": true }, "validate-npm-package-license": { "version": "3.0.3", @@ -8771,15 +12545,6 @@ "webpack-core": "^0.6.8" } }, - "webrtc-adapter": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-6.1.4.tgz", - "integrity": "sha1-b7E1if0pwaEGG4DPhvbysaDEVDE=", - "requires": { - "rtcpeerconnection-shim": "^1.2.9", - "sdp": "^2.7.0" - } - }, "websocket-driver": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", @@ -8826,11 +12591,6 @@ "string-width": "^1.0.2" } }, - "wildemitter": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/wildemitter/-/wildemitter-1.2.0.tgz", - "integrity": "sha1-Kd06ctaZw+J53QIcPNIVC4LJohE=" - }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -8838,11 +12598,6 @@ "dev": true, "optional": true }, - "wolfy87-eventemitter": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.4.tgz", - "integrity": "sha1-UCHSlS02EcvNGVFJcR2bWVzRHUg=" - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/openvidu-insecure-angular/package.json b/openvidu-insecure-angular/package.json index a930e078..56902799 100644 --- a/openvidu-insecure-angular/package.json +++ b/openvidu-insecure-angular/package.json @@ -1,6 +1,6 @@ { "name": "openvidu-insecure-angular", - "version": "0.0.0", + "version": "2.2.0", "license": "Apache-2.0", "scripts": { "start": "ng serve" @@ -14,7 +14,7 @@ "@angular/platform-browser": "6.0.2", "@angular/platform-browser-dynamic": "6.0.2", "core-js": "2.5.6", - "openvidu-browser": "2.1.0", + "openvidu-browser": "2.2.0", "zone.js": "0.8.26" }, "devDependencies": { diff --git a/openvidu-insecure-js/web/index.html b/openvidu-insecure-js/web/index.html index 1a28a890..d8168f91 100644 --- a/openvidu-insecure-js/web/index.html +++ b/openvidu-insecure-js/web/index.html @@ -14,7 +14,7 @@ - + diff --git a/openvidu-insecure-js/web/openvidu-browser-2.1.0.js b/openvidu-insecure-js/web/openvidu-browser-2.1.0.js deleted file mode 100644 index 3f2f3477..00000000 --- a/openvidu-insecure-js/web/openvidu-browser-2.1.0.js +++ /dev/null @@ -1,10290 +0,0 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - // At least give some kind of context to the user - var err = new Error('Unhandled "error" event. (' + er + ')'); - err.context = er; - throw err; - } - return false; - } - - handler = events[type]; - - if (!handler) - return false; - - var isFn = typeof handler === 'function'; - len = arguments.length; - switch (len) { - // fast cases - case 1: - emitNone(handler, isFn, this); - break; - case 2: - emitOne(handler, isFn, this, arguments[1]); - break; - case 3: - emitTwo(handler, isFn, this, arguments[1], arguments[2]); - break; - case 4: - emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); - break; - // slower - default: - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - emitMany(handler, isFn, this, args); - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = target._events; - if (!events) { - events = target._events = objectCreate(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener) { - target.emit('newListener', type, - listener.listener ? listener.listener : listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (!existing) { - // Optimize the case of one listener. Don't need the extra array object. - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - } else { - // If we've already got an array, just append. - if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - } - - // Check for listener leak - if (!existing.warned) { - m = $getMaxListeners(target); - if (m && m > 0 && existing.length > m) { - existing.warned = true; - var w = new Error('Possible EventEmitter memory leak detected. ' + - existing.length + ' "' + String(type) + '" listeners ' + - 'added. Use emitter.setMaxListeners() to ' + - 'increase limit.'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - if (typeof console === 'object' && console.warn) { - console.warn('%s: %s', w.name, w.message); - } - } - } - } - - return target; -} - -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - switch (arguments.length) { - case 0: - return this.listener.call(this.target); - case 1: - return this.listener.call(this.target, arguments[0]); - case 2: - return this.listener.call(this.target, arguments[0], arguments[1]); - case 3: - return this.listener.call(this.target, arguments[0], arguments[1], - arguments[2]); - default: - var args = new Array(arguments.length); - for (var i = 0; i < args.length; ++i) - args[i] = arguments[i]; - this.listener.apply(this.target, args); - } - } -} - -function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; - var wrapped = bind.call(onceWrapper, state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -EventEmitter.prototype.once = function once(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - -// Emits a 'removeListener' event if and only if the listener was removed. -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - var list, events, position, i, originalListener; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = this._events; - if (!events) - return this; - - list = events[type]; - if (!list) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - position = -1; - - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else - spliceOne(list, position); - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener) - this.emit('removeListener', type, originalListener || listener); - } - - return this; - }; - -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - var listeners, events, i; - - events = this._events; - if (!events) - return this; - - // not listening for removeListener, no need to emit - if (!events.removeListener) { - if (arguments.length === 0) { - this._events = objectCreate(null); - this._eventsCount = 0; - } else if (events[type]) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else - delete events[type]; - } - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - var keys = objectKeys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = objectCreate(null); - this._eventsCount = 0; - return this; - } - - listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - var events = target._events; - - if (!events) - return []; - - var evlistener = events[type]; - if (!evlistener) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); -} - -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } -}; - -EventEmitter.prototype.listenerCount = listenerCount; -function listenerCount(type) { - var events = this._events; - - if (events) { - var evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener) { - return evlistener.length; - } - } - - return 0; -} - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; -}; - -// About 1.5x faster than the two-arg version of Array#splice(). -function spliceOne(list, index) { - for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) - list[i] = list[k]; - list.pop(); -} - -function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) - copy[i] = arr[i]; - return copy; -} - -function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; -} - -function objectCreatePolyfill(proto) { - var F = function() {}; - F.prototype = proto; - return new F; -} -function objectKeysPolyfill(obj) { - var keys = []; - for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { - keys.push(k); - } - return k; -} -function functionBindPolyfill(context) { - var fn = this; - return function () { - return fn.apply(context, arguments); - }; -} - -},{}],2:[function(require,module,exports){ -/* jshint node: true */ -'use strict'; - -var normalice = require('normalice'); - -/** - # freeice - - The `freeice` module is a simple way of getting random STUN or TURN server - for your WebRTC application. The list of servers (just STUN at this stage) - were sourced from this [gist](https://gist.github.com/zziuni/3741933). - - ## Example Use - - The following demonstrates how you can use `freeice` with - [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): - - <<< examples/quickconnect.js - - As the `freeice` module generates ice servers in a list compliant with the - WebRTC spec you will be able to use it with raw `RTCPeerConnection` - constructors and other WebRTC libraries. - - ## Hey, don't use my STUN/TURN server! - - If for some reason your free STUN or TURN server ends up in the - list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or - [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) - that is used in this module, you can feel - free to open an issue on this repository and those servers will be removed - within 24 hours (or sooner). This is the quickest and probably the most - polite way to have something removed (and provides us some visibility - if someone opens a pull request requesting that a server is added). - - ## Please add my server! - - If you have a server that you wish to add to the list, that's awesome! I'm - sure I speak on behalf of a whole pile of WebRTC developers who say thanks. - To get it into the list, feel free to either open a pull request or if you - find that process a bit daunting then just create an issue requesting - the addition of the server (make sure you provide all the details, and if - you have a Terms of Service then including that in the PR/issue would be - awesome). - - ## I know of a free server, can I add it? - - Sure, if you do your homework and make sure it is ok to use (I'm currently - in the process of reviewing the terms of those STUN servers included from - the original list). If it's ok to go, then please see the previous entry - for how to add it. - - ## Current List of Servers - - * current as at the time of last `README.md` file generation - - ### STUN - - <<< stun.json - - ### TURN - - <<< turn.json - -**/ - -var freeice = module.exports = function(opts) { - // if a list of servers has been provided, then use it instead of defaults - var servers = { - stun: (opts || {}).stun || require('./stun.json'), - turn: (opts || {}).turn || require('./turn.json') - }; - - var stunCount = (opts || {}).stunCount || 2; - var turnCount = (opts || {}).turnCount || 0; - var selected; - - function getServers(type, count) { - var out = []; - var input = [].concat(servers[type]); - var idx; - - while (input.length && out.length < count) { - idx = (Math.random() * input.length) | 0; - out = out.concat(input.splice(idx, 1)); - } - - return out.map(function(url) { - //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up - if ((typeof url !== 'string') && (! (url instanceof String))) { - return url; - } else { - return normalice(type + ':' + url); - } - }); - } - - // add stun servers - selected = [].concat(getServers('stun', stunCount)); - - if (turnCount) { - selected = selected.concat(getServers('turn', turnCount)); - } - - return selected; -}; - -},{"./stun.json":3,"./turn.json":4,"normalice":8}],3:[function(require,module,exports){ -module.exports=[ - "stun.l.google.com:19302", - "stun1.l.google.com:19302", - "stun2.l.google.com:19302", - "stun3.l.google.com:19302", - "stun4.l.google.com:19302", - "stun.ekiga.net", - "stun.ideasip.com", - "stun.schlund.de", - "stun.stunprotocol.org:3478", - "stun.voiparound.com", - "stun.voipbuster.com", - "stun.voipstunt.com", - "stun.voxgratia.org", - "stun.services.mozilla.com" -] - -},{}],4:[function(require,module,exports){ -module.exports=[] - -},{}],5:[function(require,module,exports){ -var WildEmitter = require('wildemitter'); - -function getMaxVolume (analyser, fftBins) { - var maxVolume = -Infinity; - analyser.getFloatFrequencyData(fftBins); - - for(var i=4, ii=fftBins.length; i < ii; i++) { - if (fftBins[i] > maxVolume && fftBins[i] < 0) { - maxVolume = fftBins[i]; - } - }; - - return maxVolume; -} - - -var audioContextType; -if (typeof window !== 'undefined') { - audioContextType = window.AudioContext || window.webkitAudioContext; -} -// use a single audio context due to hardware limits -var audioContext = null; -module.exports = function(stream, options) { - var harker = new WildEmitter(); - - - // make it not break in non-supported browsers - if (!audioContextType) return harker; - - //Config - var options = options || {}, - smoothing = (options.smoothing || 0.1), - interval = (options.interval || 50), - threshold = options.threshold, - play = options.play, - history = options.history || 10, - running = true; - - //Setup Audio Context - if (!audioContext) { - audioContext = new audioContextType(); - } - var sourceNode, fftBins, analyser; - - analyser = audioContext.createAnalyser(); - analyser.fftSize = 512; - analyser.smoothingTimeConstant = smoothing; - fftBins = new Float32Array(analyser.frequencyBinCount); - - if (stream.jquery) stream = stream[0]; - if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { - //Audio Tag - sourceNode = audioContext.createMediaElementSource(stream); - if (typeof play === 'undefined') play = true; - threshold = threshold || -50; - } else { - //WebRTC Stream - sourceNode = audioContext.createMediaStreamSource(stream); - threshold = threshold || -50; - } - - sourceNode.connect(analyser); - if (play) analyser.connect(audioContext.destination); - - harker.speaking = false; - - harker.suspend = function() { - audioContext.suspend(); - } - harker.resume = function() { - audioContext.resume(); - } - Object.defineProperty(harker, 'state', { get: function() { - return audioContext.state; - }}); - audioContext.onstatechange = function() { - harker.emit('state_change', audioContext.state); - } - - harker.setThreshold = function(t) { - threshold = t; - }; - - harker.setInterval = function(i) { - interval = i; - }; - - harker.stop = function() { - running = false; - harker.emit('volume_change', -100, threshold); - if (harker.speaking) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - analyser.disconnect(); - sourceNode.disconnect(); - }; - harker.speakingHistory = []; - for (var i = 0; i < history; i++) { - harker.speakingHistory.push(0); - } - - // Poll the analyser node to determine if speaking - // and emit events if changed - var looper = function() { - setTimeout(function() { - - //check if stop has been called - if(!running) { - return; - } - - var currentVolume = getMaxVolume(analyser, fftBins); - - harker.emit('volume_change', currentVolume, threshold); - - var history = 0; - if (currentVolume > threshold && !harker.speaking) { - // trigger quickly, short history - for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history >= 2) { - harker.speaking = true; - harker.emit('speaking'); - } - } else if (currentVolume < threshold && harker.speaking) { - for (var i = 0; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history == 0) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - } - harker.speakingHistory.shift(); - harker.speakingHistory.push(0 + (currentVolume > threshold)); - - looper(); - }, interval); - }; - looper(); - - - return harker; -} - -},{"wildemitter":24}],6:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],7:[function(require,module,exports){ -/*! - * @name JavaScript/NodeJS Merge v1.2.0 - * @author yeikos - * @repository https://github.com/yeikos/js.merge - - * Copyright 2014 yeikos - MIT license - * https://raw.github.com/yeikos/js.merge/master/LICENSE - */ - -;(function(isNode) { - - /** - * Merge one or more objects - * @param bool? clone - * @param mixed,... arguments - * @return object - */ - - var Public = function(clone) { - - return merge(clone === true, false, arguments); - - }, publicName = 'merge'; - - /** - * Merge two or more objects recursively - * @param bool? clone - * @param mixed,... arguments - * @return object - */ - - Public.recursive = function(clone) { - - return merge(clone === true, true, arguments); - - }; - - /** - * Clone the input removing any reference - * @param mixed input - * @return mixed - */ - - Public.clone = function(input) { - - var output = input, - type = typeOf(input), - index, size; - - if (type === 'array') { - - output = []; - size = input.length; - - for (index=0;index 1) { - url = parts[1]; - parts = parts[0].split(':'); - - // add the output credential and username - output.username = parts[0]; - output.credential = (input || {}).credential || parts[1] || ''; - } - - output.url = protocol + url; - output.urls = [ output.url ]; - - return output; -}; - -},{}],9:[function(require,module,exports){ -(function (global){ -/*! - * Platform.js - * Copyright 2014-2018 Benjamin Tan - * Copyright 2011-2013 John-David Dalton - * Available under MIT license - */ -;(function() { - 'use strict'; - - /** Used to determine if values are of the language type `Object`. */ - var objectTypes = { - 'function': true, - 'object': true - }; - - /** Used as a reference to the global object. */ - var root = (objectTypes[typeof window] && window) || this; - - /** Backup possible global object. */ - var oldRoot = root; - - /** Detect free variable `exports`. */ - var freeExports = objectTypes[typeof exports] && exports; - - /** Detect free variable `module`. */ - var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; - - /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ - var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; - if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { - root = freeGlobal; - } - - /** - * Used as the maximum length of an array-like object. - * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) - * for more details. - */ - var maxSafeInteger = Math.pow(2, 53) - 1; - - /** Regular expression to detect Opera. */ - var reOpera = /\bOpera/; - - /** Possible global object. */ - var thisBinding = this; - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** Used to check for own properties of an object. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Used to resolve the internal `[[Class]]` of values. */ - var toString = objectProto.toString; - - /*--------------------------------------------------------------------------*/ - - /** - * Capitalizes a string value. - * - * @private - * @param {string} string The string to capitalize. - * @returns {string} The capitalized string. - */ - function capitalize(string) { - string = String(string); - return string.charAt(0).toUpperCase() + string.slice(1); - } - - /** - * A utility function to clean up the OS name. - * - * @private - * @param {string} os The OS name to clean up. - * @param {string} [pattern] A `RegExp` pattern matching the OS name. - * @param {string} [label] A label for the OS. - */ - function cleanupOS(os, pattern, label) { - // Platform tokens are defined at: - // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - var data = { - '10.0': '10', - '6.4': '10 Technical Preview', - '6.3': '8.1', - '6.2': '8', - '6.1': 'Server 2008 R2 / 7', - '6.0': 'Server 2008 / Vista', - '5.2': 'Server 2003 / XP 64-bit', - '5.1': 'XP', - '5.01': '2000 SP1', - '5.0': '2000', - '4.0': 'NT', - '4.90': 'ME' - }; - // Detect Windows version from platform tokens. - if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && - (data = data[/[\d.]+$/.exec(os)])) { - os = 'Windows ' + data; - } - // Correct character case and cleanup string. - os = String(os); - - if (pattern && label) { - os = os.replace(RegExp(pattern, 'i'), label); - } - - os = format( - os.replace(/ ce$/i, ' CE') - .replace(/\bhpw/i, 'web') - .replace(/\bMacintosh\b/, 'Mac OS') - .replace(/_PowerPC\b/i, ' OS') - .replace(/\b(OS X) [^ \d]+/i, '$1') - .replace(/\bMac (OS X)\b/, '$1') - .replace(/\/(\d)/, ' $1') - .replace(/_/g, '.') - .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') - .replace(/\bx86\.64\b/gi, 'x86_64') - .replace(/\b(Windows Phone) OS\b/, '$1') - .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') - .split(' on ')[0] - ); - - return os; - } - - /** - * An iteration utility for arrays and objects. - * - * @private - * @param {Array|Object} object The object to iterate over. - * @param {Function} callback The function called per iteration. - */ - function each(object, callback) { - var index = -1, - length = object ? object.length : 0; - - if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { - while (++index < length) { - callback(object[index], index, object); - } - } else { - forOwn(object, callback); - } - } - - /** - * Trim and conditionally capitalize string values. - * - * @private - * @param {string} string The string to format. - * @returns {string} The formatted string. - */ - function format(string) { - string = trim(string); - return /^(?:webOS|i(?:OS|P))/.test(string) - ? string - : capitalize(string); - } - - /** - * Iterates over an object's own properties, executing the `callback` for each. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} callback The function executed per own property. - */ - function forOwn(object, callback) { - for (var key in object) { - if (hasOwnProperty.call(object, key)) { - callback(object[key], key, object); - } - } - } - - /** - * Gets the internal `[[Class]]` of a value. - * - * @private - * @param {*} value The value. - * @returns {string} The `[[Class]]`. - */ - function getClassOf(value) { - return value == null - ? capitalize(value) - : toString.call(value).slice(8, -1); - } - - /** - * Host objects can return type values that are different from their actual - * data type. The objects we are concerned with usually return non-primitive - * types of "object", "function", or "unknown". - * - * @private - * @param {*} object The owner of the property. - * @param {string} property The property to check. - * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. - */ - function isHostType(object, property) { - var type = object != null ? typeof object[property] : 'number'; - return !/^(?:boolean|number|string|undefined)$/.test(type) && - (type == 'object' ? !!object[property] : true); - } - - /** - * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. - * - * @private - * @param {string} string The string to qualify. - * @returns {string} The qualified string. - */ - function qualify(string) { - return String(string).replace(/([ -])(?!$)/g, '$1?'); - } - - /** - * A bare-bones `Array#reduce` like utility function. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {*} The accumulated result. - */ - function reduce(array, callback) { - var accumulator = null; - each(array, function(value, index) { - accumulator = callback(accumulator, value, index, array); - }); - return accumulator; - } - - /** - * Removes leading and trailing whitespace from a string. - * - * @private - * @param {string} string The string to trim. - * @returns {string} The trimmed string. - */ - function trim(string) { - return String(string).replace(/^ +| +$/g, ''); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Creates a new platform object. - * - * @memberOf platform - * @param {Object|string} [ua=navigator.userAgent] The user agent string or - * context object. - * @returns {Object} A platform object. - */ - function parse(ua) { - - /** The environment context object. */ - var context = root; - - /** Used to flag when a custom context is provided. */ - var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; - - // Juggle arguments. - if (isCustomContext) { - context = ua; - ua = null; - } - - /** Browser navigator object. */ - var nav = context.navigator || {}; - - /** Browser user agent string. */ - var userAgent = nav.userAgent || ''; - - ua || (ua = userAgent); - - /** Used to flag when `thisBinding` is the [ModuleScope]. */ - var isModuleScope = isCustomContext || thisBinding == oldRoot; - - /** Used to detect if browser is like Chrome. */ - var likeChrome = isCustomContext - ? !!nav.likeChrome - : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); - - /** Internal `[[Class]]` value shortcuts. */ - var objectClass = 'Object', - airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', - enviroClass = isCustomContext ? objectClass : 'Environment', - javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), - phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; - - /** Detect Java environments. */ - var java = /\bJava/.test(javaClass) && context.java; - - /** Detect Rhino. */ - var rhino = java && getClassOf(context.environment) == enviroClass; - - /** A character to represent alpha. */ - var alpha = java ? 'a' : '\u03b1'; - - /** A character to represent beta. */ - var beta = java ? 'b' : '\u03b2'; - - /** Browser document object. */ - var doc = context.document || {}; - - /** - * Detect Opera browser (Presto-based). - * http://www.howtocreate.co.uk/operaStuff/operaObject.html - * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini - */ - var opera = context.operamini || context.opera; - - /** Opera `[[Class]]`. */ - var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) - ? operaClass - : (opera = null); - - /*------------------------------------------------------------------------*/ - - /** Temporary variable used over the script's lifetime. */ - var data; - - /** The CPU architecture. */ - var arch = ua; - - /** Platform description array. */ - var description = []; - - /** Platform alpha/beta indicator. */ - var prerelease = null; - - /** A flag to indicate that environment features should be used to resolve the platform. */ - var useFeatures = ua == userAgent; - - /** The browser/environment version. */ - var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); - - /** A flag to indicate if the OS ends with "/ Version" */ - var isSpecialCasedOS; - - /* Detectable layout engines (order is important). */ - var layout = getLayout([ - { 'label': 'EdgeHTML', 'pattern': 'Edge' }, - 'Trident', - { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, - 'iCab', - 'Presto', - 'NetFront', - 'Tasman', - 'KHTML', - 'Gecko' - ]); - - /* Detectable browser names (order is important). */ - var name = getName([ - 'Adobe AIR', - 'Arora', - 'Avant Browser', - 'Breach', - 'Camino', - 'Electron', - 'Epiphany', - 'Fennec', - 'Flock', - 'Galeon', - 'GreenBrowser', - 'iCab', - 'Iceweasel', - 'K-Meleon', - 'Konqueror', - 'Lunascape', - 'Maxthon', - { 'label': 'Microsoft Edge', 'pattern': 'Edge' }, - 'Midori', - 'Nook Browser', - 'PaleMoon', - 'PhantomJS', - 'Raven', - 'Rekonq', - 'RockMelt', - { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' }, - 'SeaMonkey', - { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Sleipnir', - 'SlimBrowser', - { 'label': 'SRWare Iron', 'pattern': 'Iron' }, - 'Sunrise', - 'Swiftfox', - 'Waterfox', - 'WebPositive', - 'Opera Mini', - { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, - 'Opera', - { 'label': 'Opera', 'pattern': 'OPR' }, - 'Chrome', - { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, - { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, - { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' }, - { 'label': 'IE', 'pattern': 'IEMobile' }, - { 'label': 'IE', 'pattern': 'MSIE' }, - 'Safari' - ]); - - /* Detectable products (order is important). */ - var product = getProduct([ - { 'label': 'BlackBerry', 'pattern': 'BB10' }, - 'BlackBerry', - { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, - { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, - { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, - { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, - { 'label': 'Galaxy S5', 'pattern': 'SM-G900' }, - { 'label': 'Galaxy S6', 'pattern': 'SM-G920' }, - { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' }, - { 'label': 'Galaxy S7', 'pattern': 'SM-G930' }, - { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' }, - 'Google TV', - 'Lumia', - 'iPad', - 'iPod', - 'iPhone', - 'Kindle', - { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Nexus', - 'Nook', - 'PlayBook', - 'PlayStation Vita', - 'PlayStation', - 'TouchPad', - 'Transformer', - { 'label': 'Wii U', 'pattern': 'WiiU' }, - 'Wii', - 'Xbox One', - { 'label': 'Xbox 360', 'pattern': 'Xbox' }, - 'Xoom' - ]); - - /* Detectable manufacturers. */ - var manufacturer = getManufacturer({ - 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, - 'Archos': {}, - 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, - 'Asus': { 'Transformer': 1 }, - 'Barnes & Noble': { 'Nook': 1 }, - 'BlackBerry': { 'PlayBook': 1 }, - 'Google': { 'Google TV': 1, 'Nexus': 1 }, - 'HP': { 'TouchPad': 1 }, - 'HTC': {}, - 'LG': {}, - 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, - 'Motorola': { 'Xoom': 1 }, - 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, - 'Nokia': { 'Lumia': 1 }, - 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, - 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 } - }); - - /* Detectable operating systems (order is important). */ - var os = getOS([ - 'Windows Phone', - 'Android', - 'CentOS', - { 'label': 'Chrome OS', 'pattern': 'CrOS' }, - 'Debian', - 'Fedora', - 'FreeBSD', - 'Gentoo', - 'Haiku', - 'Kubuntu', - 'Linux Mint', - 'OpenBSD', - 'Red Hat', - 'SuSE', - 'Ubuntu', - 'Xubuntu', - 'Cygwin', - 'Symbian OS', - 'hpwOS', - 'webOS ', - 'webOS', - 'Tablet OS', - 'Tizen', - 'Linux', - 'Mac OS X', - 'Macintosh', - 'Mac', - 'Windows 98;', - 'Windows ' - ]); - - /*------------------------------------------------------------------------*/ - - /** - * Picks the layout engine from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected layout engine. - */ - function getLayout(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the manufacturer from an array of guesses. - * - * @private - * @param {Array} guesses An object of guesses. - * @returns {null|string} The detected manufacturer. - */ - function getManufacturer(guesses) { - return reduce(guesses, function(result, value, key) { - // Lookup the manufacturer by product or scan the UA for the manufacturer. - return result || ( - value[product] || - value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || - RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) - ) && key; - }); - } - - /** - * Picks the browser name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected browser name. - */ - function getName(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the OS name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected OS name. - */ - function getOS(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) - )) { - result = cleanupOS(result, pattern, guess.label || guess); - } - return result; - }); - } - - /** - * Picks the product name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected product name. - */ - function getProduct(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || - RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) || - RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) - )) { - // Split by forward slash and append product version if needed. - if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { - result[0] += ' ' + result[1]; - } - // Correct character case and cleanup string. - guess = guess.label || guess; - result = format(result[0] - .replace(RegExp(pattern, 'i'), guess) - .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') - .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); - } - return result; - }); - } - - /** - * Resolves the version using an array of UA patterns. - * - * @private - * @param {Array} patterns An array of UA patterns. - * @returns {null|string} The detected version. - */ - function getVersion(patterns) { - return reduce(patterns, function(result, pattern) { - return result || (RegExp(pattern + - '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; - }); - } - - /** - * Returns `platform.description` when the platform object is coerced to a string. - * - * @name toString - * @memberOf platform - * @returns {string} Returns `platform.description` if available, else an empty string. - */ - function toStringPlatform() { - return this.description || ''; - } - - /*------------------------------------------------------------------------*/ - - // Convert layout to an array so we can add extra details. - layout && (layout = [layout]); - - // Detect product names that contain their manufacturer's name. - if (manufacturer && !product) { - product = getProduct([manufacturer]); - } - // Clean up Google TV. - if ((data = /\bGoogle TV\b/.exec(product))) { - product = data[0]; - } - // Detect simulators. - if (/\bSimulator\b/i.test(ua)) { - product = (product ? product + ' ' : '') + 'Simulator'; - } - // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. - if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { - description.push('running in Turbo/Uncompressed mode'); - } - // Detect IE Mobile 11. - if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) { - data = parse(ua.replace(/like iPhone OS/, '')); - manufacturer = data.manufacturer; - product = data.product; - } - // Detect iOS. - else if (/^iP/.test(product)) { - name || (name = 'Safari'); - os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) - ? ' ' + data[1].replace(/_/g, '.') - : ''); - } - // Detect Kubuntu. - else if (name == 'Konqueror' && !/buntu/i.test(os)) { - os = 'Kubuntu'; - } - // Detect Android browsers. - else if ((manufacturer && manufacturer != 'Google' && - ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) || - (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) { - name = 'Android Browser'; - os = /\bAndroid\b/.test(os) ? os : 'Android'; - } - // Detect Silk desktop/accelerated modes. - else if (name == 'Silk') { - if (!/\bMobi/i.test(ua)) { - os = 'Android'; - description.unshift('desktop mode'); - } - if (/Accelerated *= *true/i.test(ua)) { - description.unshift('accelerated'); - } - } - // Detect PaleMoon identifying as Firefox. - else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { - description.push('identifying as Firefox ' + data[1]); - } - // Detect Firefox OS and products running Firefox. - else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { - os || (os = 'Firefox OS'); - product || (product = data[1]); - } - // Detect false positives for Firefox/Safari. - else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { - // Escape the `/` for Firefox 1. - if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { - // Clear name of false positives. - name = null; - } - // Reassign a generic name. - if ((data = product || manufacturer || os) && - (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { - name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; - } - } - // Add Chrome version to description for Electron. - else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) { - description.push('Chromium ' + data); - } - // Detect non-Opera (Presto-based) versions (order is important). - if (!version) { - version = getVersion([ - '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))', - 'Version', - qualify(name), - '(?:Firefox|Minefield|NetFront)' - ]); - } - // Detect stubborn layout engines. - if ((data = - layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || - /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || - /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || - !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || - layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' - )) { - layout = [data]; - } - // Detect Windows Phone 7 desktop mode. - if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { - name += ' Mobile'; - os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); - description.unshift('desktop mode'); - } - // Detect Windows Phone 8.x desktop mode. - else if (/\bWPDesktop\b/i.test(ua)) { - name = 'IE Mobile'; - os = 'Windows Phone 8.x'; - description.unshift('desktop mode'); - version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); - } - // Detect IE 11 identifying as other browsers. - else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { - if (name) { - description.push('identifying as ' + name + (version ? ' ' + version : '')); - } - name = 'IE'; - version = data[1]; - } - // Leverage environment features. - if (useFeatures) { - // Detect server-side environments. - // Rhino has a global function while others have a global object. - if (isHostType(context, 'global')) { - if (java) { - data = java.lang.System; - arch = data.getProperty('os.arch'); - os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); - } - if (rhino) { - try { - version = context.require('ringo/engine').version.join('.'); - name = 'RingoJS'; - } catch(e) { - if ((data = context.system) && data.global.system == context.system) { - name = 'Narwhal'; - os || (os = data[0].os || null); - } - } - if (!name) { - name = 'Rhino'; - } - } - else if ( - typeof context.process == 'object' && !context.process.browser && - (data = context.process) - ) { - if (typeof data.versions == 'object') { - if (typeof data.versions.electron == 'string') { - description.push('Node ' + data.versions.node); - name = 'Electron'; - version = data.versions.electron; - } else if (typeof data.versions.nw == 'string') { - description.push('Chromium ' + version, 'Node ' + data.versions.node); - name = 'NW.js'; - version = data.versions.nw; - } - } - if (!name) { - name = 'Node.js'; - arch = data.arch; - os = data.platform; - version = /[\d.]+/.exec(data.version); - version = version ? version[0] : null; - } - } - } - // Detect Adobe AIR. - else if (getClassOf((data = context.runtime)) == airRuntimeClass) { - name = 'Adobe AIR'; - os = data.flash.system.Capabilities.os; - } - // Detect PhantomJS. - else if (getClassOf((data = context.phantom)) == phantomClass) { - name = 'PhantomJS'; - version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); - } - // Detect IE compatibility modes. - else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { - // We're in compatibility mode when the Trident version + 4 doesn't - // equal the document mode. - version = [version, doc.documentMode]; - if ((data = +data[1] + 4) != version[1]) { - description.push('IE ' + version[1] + ' mode'); - layout && (layout[1] = ''); - version[1] = data; - } - version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; - } - // Detect IE 11 masking as other browsers. - else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) { - description.push('masking as ' + name + ' ' + version); - name = 'IE'; - version = '11.0'; - layout = ['Trident']; - os = 'Windows'; - } - os = os && format(os); - } - // Detect prerelease phases. - if (version && (data = - /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || - /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || - /\bMinefield\b/i.test(ua) && 'a' - )) { - prerelease = /b/i.test(data) ? 'beta' : 'alpha'; - version = version.replace(RegExp(data + '\\+?$'), '') + - (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); - } - // Detect Firefox Mobile. - if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) { - name = 'Firefox Mobile'; - } - // Obscure Maxthon's unreliable version. - else if (name == 'Maxthon' && version) { - version = version.replace(/\.[\d.]+/, '.x'); - } - // Detect Xbox 360 and Xbox One. - else if (/\bXbox\b/i.test(product)) { - if (product == 'Xbox 360') { - os = null; - } - if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { - description.unshift('mobile mode'); - } - } - // Add mobile postfix. - else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && - (os == 'Windows CE' || /Mobi/i.test(ua))) { - name += ' Mobile'; - } - // Detect IE platform preview. - else if (name == 'IE' && useFeatures) { - try { - if (context.external === null) { - description.unshift('platform preview'); - } - } catch(e) { - description.unshift('embedded'); - } - } - // Detect BlackBerry OS version. - // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp - else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = - (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || - version - )) { - data = [data, /BB10/.test(ua)]; - os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; - version = null; - } - // Detect Opera identifying/masking itself as another browser. - // http://www.opera.com/support/kb/view/843/ - else if (this != forOwn && product != 'Wii' && ( - (useFeatures && opera) || - (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || - (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || - (name == 'IE' && ( - (os && !/^Win/.test(os) && version > 5.5) || - /\bWindows XP\b/.test(os) && version > 8 || - version == 8 && !/\bTrident\b/.test(ua) - )) - ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { - // When "identifying", the UA contains both Opera and the other browser's name. - data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); - if (reOpera.test(name)) { - if (/\bIE\b/.test(data) && os == 'Mac OS') { - os = null; - } - data = 'identify' + data; - } - // When "masking", the UA contains only the other browser's name. - else { - data = 'mask' + data; - if (operaClass) { - name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); - } else { - name = 'Opera'; - } - if (/\bIE\b/.test(data)) { - os = null; - } - if (!useFeatures) { - version = null; - } - } - layout = ['Presto']; - description.push(data); - } - // Detect WebKit Nightly and approximate Chrome/Safari versions. - if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - // Correct build number for numeric comparison. - // (e.g. "532.5" becomes "532.05") - data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; - // Nightly builds are postfixed with a "+". - if (name == 'Safari' && data[1].slice(-1) == '+') { - name = 'WebKit Nightly'; - prerelease = 'alpha'; - version = data[1].slice(0, -1); - } - // Clear incorrect browser versions. - else if (version == data[1] || - version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - version = null; - } - // Use the full Chrome version when available. - data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]; - // Detect Blink layout engine. - if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { - layout = ['Blink']; - } - // Detect JavaScriptCore. - // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi - if (!useFeatures || (!likeChrome && !data[1])) { - layout && (layout[1] = 'like Safari'); - data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8'); - } else { - layout && (layout[1] = 'like Chrome'); - data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); - } - // Add the postfix of ".x" or "+" for approximate versions. - layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); - // Obscure version for some Safari 1-2 releases. - if (name == 'Safari' && (!version || parseInt(version) > 45)) { - version = data; - } - } - // Detect Opera desktop modes. - if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { - name += ' '; - description.unshift('desktop mode'); - if (data == 'zvav') { - name += 'Mini'; - version = null; - } else { - name += 'Mobile'; - } - os = os.replace(RegExp(' *' + data + '$'), ''); - } - // Detect Chrome desktop mode. - else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { - description.unshift('desktop mode'); - name = 'Chrome Mobile'; - version = null; - - if (/\bOS X\b/.test(os)) { - manufacturer = 'Apple'; - os = 'iOS 4.3+'; - } else { - os = null; - } - } - // Strip incorrect OS versions. - if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && - ua.indexOf('/' + data + '-') > -1) { - os = trim(os.replace(data, '')); - } - // Add layout engine. - if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( - /Browser|Lunascape|Maxthon/.test(name) || - name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || - /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) { - // Don't add layout details to description if they are falsey. - (data = layout[layout.length - 1]) && description.push(data); - } - // Combine contextual information. - if (description.length) { - description = ['(' + description.join('; ') + ')']; - } - // Append manufacturer to description. - if (manufacturer && product && product.indexOf(manufacturer) < 0) { - description.push('on ' + manufacturer); - } - // Append product to description. - if (product) { - description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); - } - // Parse the OS into an object. - if (os) { - data = / ([\d.+]+)$/.exec(os); - isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; - os = { - 'architecture': 32, - 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, - 'version': data ? data[1] : null, - 'toString': function() { - var version = this.version; - return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); - } - }; - } - // Add browser/OS architecture. - if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { - if (os) { - os.architecture = 64; - os.family = os.family.replace(RegExp(' *' + data), ''); - } - if ( - name && (/\bWOW64\b/i.test(ua) || - (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) - ) { - description.unshift('32-bit'); - } - } - // Chrome 39 and above on OS X is always 64-bit. - else if ( - os && /^OS X/.test(os.family) && - name == 'Chrome' && parseFloat(version) >= 39 - ) { - os.architecture = 64; - } - - ua || (ua = null); - - /*------------------------------------------------------------------------*/ - - /** - * The platform object. - * - * @name platform - * @type Object - */ - var platform = {}; - - /** - * The platform description. - * - * @memberOf platform - * @type string|null - */ - platform.description = ua; - - /** - * The name of the browser's layout engine. - * - * The list of common layout engines include: - * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit" - * - * @memberOf platform - * @type string|null - */ - platform.layout = layout && layout[0]; - - /** - * The name of the product's manufacturer. - * - * The list of manufacturers include: - * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry", - * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo", - * "Nokia", "Samsung" and "Sony" - * - * @memberOf platform - * @type string|null - */ - platform.manufacturer = manufacturer; - - /** - * The name of the browser/environment. - * - * The list of common browser names include: - * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE", - * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk", - * "Opera Mini" and "Opera" - * - * Mobile versions of some browsers have "Mobile" appended to their name: - * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile" - * - * @memberOf platform - * @type string|null - */ - platform.name = name; - - /** - * The alpha/beta release indicator. - * - * @memberOf platform - * @type string|null - */ - platform.prerelease = prerelease; - - /** - * The name of the product hosting the browser. - * - * The list of common products include: - * - * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle", - * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer" - * - * @memberOf platform - * @type string|null - */ - platform.product = product; - - /** - * The browser's user agent string. - * - * @memberOf platform - * @type string|null - */ - platform.ua = ua; - - /** - * The browser/environment version. - * - * @memberOf platform - * @type string|null - */ - platform.version = name && version; - - /** - * The name of the operating system. - * - * @memberOf platform - * @type Object - */ - platform.os = os || { - - /** - * The CPU architecture the OS is built for. - * - * @memberOf platform.os - * @type number|null - */ - 'architecture': null, - - /** - * The family of the OS. - * - * Common values include: - * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", - * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", - * "Android", "iOS" and "Windows Phone" - * - * @memberOf platform.os - * @type string|null - */ - 'family': null, - - /** - * The version of the OS. - * - * @memberOf platform.os - * @type string|null - */ - 'version': null, - - /** - * Returns the OS string. - * - * @memberOf platform.os - * @returns {string} The OS string. - */ - 'toString': function() { return 'null'; } - }; - - platform.parse = parse; - platform.toString = toStringPlatform; - - if (platform.version) { - description.unshift(version); - } - if (platform.name) { - description.unshift(name); - } - if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { - description.push(product ? '(' + os + ')' : 'on ' + os); - } - if (description.length) { - platform.description = description.join(' '); - } - return platform; - } - - /*--------------------------------------------------------------------------*/ - - // Export platform. - var platform = parse(); - - // Some AMD build optimizers, like r.js, check for condition patterns like the following: - if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose platform on the global object to prevent errors when platform is - // loaded by a script tag in the presence of an AMD loader. - // See http://requirejs.org/docs/errors.html#mismatch for more details. - root.platform = platform; - - // Define as an anonymous module so platform can be aliased through path mapping. - define(function() { - return platform; - }); - } - // Check for `exports` after `define` in case a build optimizer adds an `exports` object. - else if (freeExports && freeModule) { - // Export for CommonJS support. - forOwn(platform, function(value, key) { - freeExports[key] = value; - }); - } - else { - // Export to the global object. - root.platform = platform; - } -}.call(this)); - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],10:[function(require,module,exports){ -var grammar = module.exports = { - v: [{ - name: 'version', - reg: /^(\d*)$/ - }], - o: [{ //o=- 20518 0 IN IP4 203.0.113.1 - // NB: sessionId will be a String in most cases because it is huge - name: 'origin', - reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, - names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], - format: "%s %s %d %s IP%d %s" - }], - // default parsing of these only (though some of these feel outdated) - s: [{ name: 'name' }], - i: [{ name: 'description' }], - u: [{ name: 'uri' }], - e: [{ name: 'email' }], - p: [{ name: 'phone' }], - z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly.. - r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly - //k: [{}], // outdated thing ignored - t: [{ //t=0 0 - name: 'timing', - reg: /^(\d*) (\d*)/, - names: ['start', 'stop'], - format: "%d %d" - }], - c: [{ //c=IN IP4 10.47.197.26 - name: 'connection', - reg: /^IN IP(\d) (\S*)/, - names: ['version', 'ip'], - format: "IN IP%d %s" - }], - b: [{ //b=AS:4000 - push: 'bandwidth', - reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, - names: ['type', 'limit'], - format: "%s:%s" - }], - m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31 - // NB: special - pushes to session - // TODO: rtp/fmtp should be filtered by the payloads found here? - reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/, - names: ['type', 'port', 'protocol', 'payloads'], - format: "%s %d %s %s" - }], - a: [ - { //a=rtpmap:110 opus/48000/2 - push: 'rtp', - reg: /^rtpmap:(\d*) ([\w\-]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, - names: ['payload', 'codec', 'rate', 'encoding'], - format: function (o) { - return (o.encoding) ? - "rtpmap:%d %s/%s/%s": - o.rate ? - "rtpmap:%d %s/%s": - "rtpmap:%d %s"; - } - }, - { - //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 - //a=fmtp:111 minptime=10; useinbandfec=1 - push: 'fmtp', - reg: /^fmtp:(\d*) ([\S| ]*)/, - names: ['payload', 'config'], - format: "fmtp:%d %s" - }, - { //a=control:streamid=0 - name: 'control', - reg: /^control:(.*)/, - format: "control:%s" - }, - { //a=rtcp:65179 IN IP4 193.84.77.194 - name: 'rtcp', - reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, - names: ['port', 'netType', 'ipVer', 'address'], - format: function (o) { - return (o.address != null) ? - "rtcp:%d %s IP%d %s": - "rtcp:%d"; - } - }, - { //a=rtcp-fb:98 trr-int 100 - push: 'rtcpFbTrrInt', - reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, - names: ['payload', 'value'], - format: "rtcp-fb:%d trr-int %d" - }, - { //a=rtcp-fb:98 nack rpsi - push: 'rtcpFb', - reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, - names: ['payload', 'type', 'subtype'], - format: function (o) { - return (o.subtype != null) ? - "rtcp-fb:%s %s %s": - "rtcp-fb:%s %s"; - } - }, - { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset - //a=extmap:1/recvonly URI-gps-string - push: 'ext', - reg: /^extmap:([\w_\/]*) (\S*)(?: (\S*))?/, - names: ['value', 'uri', 'config'], // value may include "/direction" suffix - format: function (o) { - return (o.config != null) ? - "extmap:%s %s %s": - "extmap:%s %s"; - } - }, - { - //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 - push: 'crypto', - reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, - names: ['id', 'suite', 'config', 'sessionConfig'], - format: function (o) { - return (o.sessionConfig != null) ? - "crypto:%d %s %s %s": - "crypto:%d %s %s"; - } - }, - { //a=setup:actpass - name: 'setup', - reg: /^setup:(\w*)/, - format: "setup:%s" - }, - { //a=mid:1 - name: 'mid', - reg: /^mid:([^\s]*)/, - format: "mid:%s" - }, - { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a - name: 'msid', - reg: /^msid:(.*)/, - format: "msid:%s" - }, - { //a=ptime:20 - name: 'ptime', - reg: /^ptime:(\d*)/, - format: "ptime:%d" - }, - { //a=maxptime:60 - name: 'maxptime', - reg: /^maxptime:(\d*)/, - format: "maxptime:%d" - }, - { //a=sendrecv - name: 'direction', - reg: /^(sendrecv|recvonly|sendonly|inactive)/ - }, - { //a=ice-lite - name: 'icelite', - reg: /^(ice-lite)/ - }, - { //a=ice-ufrag:F7gI - name: 'iceUfrag', - reg: /^ice-ufrag:(\S*)/, - format: "ice-ufrag:%s" - }, - { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g - name: 'icePwd', - reg: /^ice-pwd:(\S*)/, - format: "ice-pwd:%s" - }, - { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 - name: 'fingerprint', - reg: /^fingerprint:(\S*) (\S*)/, - names: ['type', 'hash'], - format: "fingerprint:%s %s" - }, - { - //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host - //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 - //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 - //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 - //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 - push:'candidates', - reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?/, - names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation'], - format: function (o) { - var str = "candidate:%s %d %s %d %s %d typ %s"; - - str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v"; - - // NB: candidate has three optional chunks, so %void middles one if it's missing - str += (o.tcptype != null) ? " tcptype %s" : "%v"; - - if (o.generation != null) { - str += " generation %d"; - } - return str; - } - }, - { //a=end-of-candidates (keep after the candidates line for readability) - name: 'endOfCandidates', - reg: /^(end-of-candidates)/ - }, - { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... - name: 'remoteCandidates', - reg: /^remote-candidates:(.*)/, - format: "remote-candidates:%s" - }, - { //a=ice-options:google-ice - name: 'iceOptions', - reg: /^ice-options:(\S*)/, - format: "ice-options:%s" - }, - { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 - push: "ssrcs", - reg: /^ssrc:(\d*) ([\w_]*):(.*)/, - names: ['id', 'attribute', 'value'], - format: "ssrc:%d %s:%s" - }, - { //a=ssrc-group:FEC 1 2 - push: "ssrcGroups", - reg: /^ssrc-group:(\w*) (.*)/, - names: ['semantics', 'ssrcs'], - format: "ssrc-group:%s %s" - }, - { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV - name: "msidSemantic", - reg: /^msid-semantic:\s?(\w*) (\S*)/, - names: ['semantic', 'token'], - format: "msid-semantic: %s %s" // space after ":" is not accidental - }, - { //a=group:BUNDLE audio video - push: 'groups', - reg: /^group:(\w*) (.*)/, - names: ['type', 'mids'], - format: "group:%s %s" - }, - { //a=rtcp-mux - name: 'rtcpMux', - reg: /^(rtcp-mux)/ - }, - { //a=rtcp-rsize - name: 'rtcpRsize', - reg: /^(rtcp-rsize)/ - }, - { // any a= that we don't understand is kepts verbatim on media.invalid - push: 'invalid', - names: ["value"] - } - ] -}; - -// set sensible defaults to avoid polluting the grammar with boring details -Object.keys(grammar).forEach(function (key) { - var objs = grammar[key]; - objs.forEach(function (obj) { - if (!obj.reg) { - obj.reg = /(.*)/; - } - if (!obj.format) { - obj.format = "%s"; - } - }); -}); - -},{}],11:[function(require,module,exports){ -var parser = require('./parser'); -var writer = require('./writer'); - -exports.write = writer; -exports.parse = parser.parse; -exports.parseFmtpConfig = parser.parseFmtpConfig; -exports.parsePayloads = parser.parsePayloads; -exports.parseRemoteCandidates = parser.parseRemoteCandidates; - -},{"./parser":12,"./writer":13}],12:[function(require,module,exports){ -var toIntIfInt = function (v) { - return String(Number(v)) === v ? Number(v) : v; -}; - -var attachProperties = function (match, location, names, rawName) { - if (rawName && !names) { - location[rawName] = toIntIfInt(match[1]); - } - else { - for (var i = 0; i < names.length; i += 1) { - if (match[i+1] != null) { - location[names[i]] = toIntIfInt(match[i+1]); - } - } - } -}; - -var parseReg = function (obj, location, content) { - var needsBlank = obj.name && obj.names; - if (obj.push && !location[obj.push]) { - location[obj.push] = []; - } - else if (needsBlank && !location[obj.name]) { - location[obj.name] = {}; - } - var keyLocation = obj.push ? - {} : // blank object that will be pushed - needsBlank ? location[obj.name] : location; // otherwise, named location or root - - attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name); - - if (obj.push) { - location[obj.push].push(keyLocation); - } -}; - -var grammar = require('./grammar'); -var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/); - -exports.parse = function (sdp) { - var session = {} - , media = [] - , location = session; // points at where properties go under (one of the above) - - // parse lines we understand - sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) { - var type = l[0]; - var content = l.slice(2); - if (type === 'm') { - media.push({rtp: [], fmtp: []}); - location = media[media.length-1]; // point at latest media line - } - - for (var j = 0; j < (grammar[type] || []).length; j += 1) { - var obj = grammar[type][j]; - if (obj.reg.test(content)) { - return parseReg(obj, location, content); - } - } - }); - - session.media = media; // link it up - return session; -}; - -var fmtpReducer = function (acc, expr) { - var s = expr.split('='); - if (s.length === 2) { - acc[s[0]] = toIntIfInt(s[1]); - } - return acc; -}; - -exports.parseFmtpConfig = function (str) { - return str.split(/\;\s?/).reduce(fmtpReducer, {}); -}; - -exports.parsePayloads = function (str) { - return str.split(' ').map(Number); -}; - -exports.parseRemoteCandidates = function (str) { - var candidates = []; - var parts = str.split(' ').map(toIntIfInt); - for (var i = 0; i < parts.length; i += 3) { - candidates.push({ - component: parts[i], - ip: parts[i + 1], - port: parts[i + 2] - }); - } - return candidates; -}; - -},{"./grammar":10}],13:[function(require,module,exports){ -var grammar = require('./grammar'); - -// customized util.format - discards excess arguments and can void middle ones -var formatRegExp = /%[sdv%]/g; -var format = function (formatStr) { - var i = 1; - var args = arguments; - var len = args.length; - return formatStr.replace(formatRegExp, function (x) { - if (i >= len) { - return x; // missing argument - } - var arg = args[i]; - i += 1; - switch (x) { - case '%%': - return '%'; - case '%s': - return String(arg); - case '%d': - return Number(arg); - case '%v': - return ''; - } - }); - // NB: we discard excess arguments - they are typically undefined from makeLine -}; - -var makeLine = function (type, obj, location) { - var str = obj.format instanceof Function ? - (obj.format(obj.push ? location : location[obj.name])) : - obj.format; - - var args = [type + '=' + str]; - if (obj.names) { - for (var i = 0; i < obj.names.length; i += 1) { - var n = obj.names[i]; - if (obj.name) { - args.push(location[obj.name][n]); - } - else { // for mLine and push attributes - args.push(location[obj.names[i]]); - } - } - } - else { - args.push(location[obj.name]); - } - return format.apply(null, args); -}; - -// RFC specified order -// TODO: extend this with all the rest -var defaultOuterOrder = [ - 'v', 'o', 's', 'i', - 'u', 'e', 'p', 'c', - 'b', 't', 'r', 'z', 'a' -]; -var defaultInnerOrder = ['i', 'c', 'b', 'a']; - - -module.exports = function (session, opts) { - opts = opts || {}; - // ensure certain properties exist - if (session.version == null) { - session.version = 0; // "v=0" must be there (only defined version atm) - } - if (session.name == null) { - session.name = " "; // "s= " must be there if no meaningful name set - } - session.media.forEach(function (mLine) { - if (mLine.payloads == null) { - mLine.payloads = ""; - } - }); - - var outerOrder = opts.outerOrder || defaultOuterOrder; - var innerOrder = opts.innerOrder || defaultInnerOrder; - var sdp = []; - - // loop through outerOrder for matching properties on session - outerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in session && session[obj.name] != null) { - sdp.push(makeLine(type, obj, session)); - } - else if (obj.push in session && session[obj.push] != null) { - session[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - - // then for each media line, follow the innerOrder - session.media.forEach(function (mLine) { - sdp.push(makeLine('m', grammar.m[0], mLine)); - - innerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in mLine && mLine[obj.name] != null) { - sdp.push(makeLine(type, obj, mLine)); - } - else if (obj.push in mLine && mLine[obj.push] != null) { - mLine[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - }); - - return sdp.join('\r\n') + '\r\n'; -}; - -},{"./grammar":10}],14:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -module.exports = function arrayEquals(array) { - // if the other array is a falsy value, return - if (!array) - return false; - - // compare lengths - can save a lot of time - if (this.length != array.length) - return false; - - for (var i = 0, l = this.length; i < l; i++) { - // Check if we have nested arrays - if (this[i] instanceof Array && array[i] instanceof Array) { - // recurse into the nested arrays - if (!arrayEquals.apply(this[i], [array[i]])) - return false; - } else if (this[i] != array[i]) { - // Warning - two different object instances will never be equal: - // {x:20} != {x:20} - return false; - } - } - return true; -}; - - -},{}],15:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -exports.Interop = require('./interop'); - -},{"./interop":16}],16:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* global RTCSessionDescription */ -/* global RTCIceCandidate */ -/* jshint -W097 */ -"use strict"; - -var transform = require('./transform'); -var arrayEquals = require('./array-equals'); - -function Interop() { - - /** - * This map holds the most recent Unified Plan offer/answer SDP that was - * converted to Plan B, with the SDP type ('offer' or 'answer') as keys and - * the SDP string as values. - * - * @type {{}} - */ - this.cache = { - mlB2UMap : {}, - mlU2BMap : {} - }; -} - -module.exports = Interop; - -/** - * Changes the candidate args to match with the related Unified Plan - */ -Interop.prototype.candidateToUnifiedPlan = function(candidate) { - var cand = new RTCIceCandidate(candidate); - - cand.sdpMLineIndex = this.cache.mlB2UMap[cand.sdpMLineIndex]; - /* TODO: change sdpMid to (audio|video)-SSRC */ - - return cand; -}; - -/** - * Changes the candidate args to match with the related Plan B - */ -Interop.prototype.candidateToPlanB = function(candidate) { - var cand = new RTCIceCandidate(candidate); - - if (cand.sdpMid.indexOf('audio') === 0) { - cand.sdpMid = 'audio'; - } else if (cand.sdpMid.indexOf('video') === 0) { - cand.sdpMid = 'video'; - } else { - throw new Error('candidate with ' + cand.sdpMid + ' not allowed'); - } - - cand.sdpMLineIndex = this.cache.mlU2BMap[cand.sdpMLineIndex]; - - return cand; -}; - -/** - * Returns the index of the first m-line with the given media type and with a - * direction which allows sending, in the last Unified Plan description with - * type "answer" converted to Plan B. Returns {null} if there is no saved - * answer, or if none of its m-lines with the given type allow sending. - * @param type the media type ("audio" or "video"). - * @returns {*} - */ -Interop.prototype.getFirstSendingIndexFromAnswer = function(type) { - if (!this.cache.answer) { - return null; - } - - var session = transform.parse(this.cache.answer); - if (session && session.media && Array.isArray(session.media)){ - for (var i = 0; i < session.media.length; i++) { - if (session.media[i].type == type && - (!session.media[i].direction /* default to sendrecv */ || - session.media[i].direction === 'sendrecv' || - session.media[i].direction === 'sendonly')){ - return i; - } - } - } - - return null; -}; - -/** - * This method transforms a Unified Plan SDP to an equivalent Plan B SDP. A - * PeerConnection wrapper transforms the SDP to Plan B before passing it to the - * application. - * - * @param desc - * @returns {*} - */ -Interop.prototype.toPlanB = function(desc) { - var self = this; - //#region Preliminary input validation. - - if (typeof desc !== 'object' || desc === null || - typeof desc.sdp !== 'string') { - console.warn('An empty description was passed as an argument.'); - return desc; - } - - // Objectify the SDP for easier manipulation. - var session = transform.parse(desc.sdp); - - // If the SDP contains no media, there's nothing to transform. - if (typeof session.media === 'undefined' || - !Array.isArray(session.media) || session.media.length === 0) { - console.warn('The description has no media.'); - return desc; - } - - // Try some heuristics to "make sure" this is a Unified Plan SDP. Plan B - // SDP has a video, an audio and a data "channel" at most. - if (session.media.length <= 3 && session.media.every(function(m) { - return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; - })) { - console.warn('This description does not look like Unified Plan.'); - return desc; - } - - //#endregion - - // HACK https://bugzilla.mozilla.org/show_bug.cgi?id=1113443 - var sdp = desc.sdp; - var rewrite = false; - for (var i = 0; i < session.media.length; i++) { - var uLine = session.media[i]; - uLine.rtp.forEach(function(rtp) { - if (rtp.codec === 'NULL') - { - rewrite = true; - var offer = transform.parse(self.cache.offer); - rtp.codec = offer.media[i].rtp[0].codec; - } - }); - } - if (rewrite) { - sdp = transform.write(session); - } - - // Unified Plan SDP is our "precious". Cache it for later use in the Plan B - // -> Unified Plan transformation. - this.cache[desc.type] = sdp; - - //#region Convert from Unified Plan to Plan B. - - // We rebuild the session.media array. - var media = session.media; - session.media = []; - - // Associative array that maps channel types to channel objects for fast - // access to channel objects by their type, e.g. type2bl['audio']->channel - // obj. - var type2bl = {}; - - // Used to build the group:BUNDLE value after the channels construction - // loop. - var types = []; - - media.forEach(function(uLine) { - // rtcp-mux is required in the Plan B SDP. - if ((typeof uLine.rtcpMux !== 'string' || - uLine.rtcpMux !== 'rtcp-mux') && - uLine.direction !== 'inactive') { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'without the rtcp-mux attribute were found.'); - } - - // If we don't have a channel for this uLine.type OR the selected is - // inactive, then select this uLine as the channel basis. - if (typeof type2bl[uLine.type] === 'undefined' || - type2bl[uLine.type].direction === 'inactive') { - type2bl[uLine.type] = uLine; - } - - if (uLine.protocol != type2bl[uLine.type].protocol) { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'have different protocols and this library does not have ' + - 'support for that'); - } - - if (uLine.payloads != type2bl[uLine.type].payloads) { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'have different payloads and this library does not have ' + - 'support for that'); - } - - }); - - // Implode the Unified Plan m-lines/tracks into Plan B channels. - media.forEach(function(uLine) { - if (uLine.type === 'application') { - session.media.push(uLine); - types.push(uLine.mid); - return; - } - - // Add sources to the channel and handle a=msid. - if (typeof uLine.sources === 'object') { - Object.keys(uLine.sources).forEach(function(ssrc) { - if (typeof type2bl[uLine.type].sources !== 'object') - type2bl[uLine.type].sources = {}; - - // Assign the sources to the channel. - type2bl[uLine.type].sources[ssrc] = - uLine.sources[ssrc]; - - if (typeof uLine.msid !== 'undefined') { - // In Plan B the msid is an SSRC attribute. Also, we don't - // care about the obsolete label and mslabel attributes. - // - // Note that it is not guaranteed that the uLine will - // have an msid. recvonly channels in particular don't have - // one. - type2bl[uLine.type].sources[ssrc].msid = - uLine.msid; - } - // NOTE ssrcs in ssrc groups will share msids, as - // draft-uberti-rtcweb-plan-00 mandates. - }); - } - - // Add ssrc groups to the channel. - if (typeof uLine.ssrcGroups !== 'undefined' && - Array.isArray(uLine.ssrcGroups)) { - - // Create the ssrcGroups array, if it's not defined. - if (typeof type2bl[uLine.type].ssrcGroups === 'undefined' || - !Array.isArray(type2bl[uLine.type].ssrcGroups)) { - type2bl[uLine.type].ssrcGroups = []; - } - - type2bl[uLine.type].ssrcGroups = - type2bl[uLine.type].ssrcGroups.concat( - uLine.ssrcGroups); - } - - if (type2bl[uLine.type] === uLine) { - // Plan B mids are in ['audio', 'video', 'data'] - uLine.mid = uLine.type; - - // Plan B doesn't support/need the bundle-only attribute. - delete uLine.bundleOnly; - - // In Plan B the msid is an SSRC attribute. - delete uLine.msid; - - if (uLine.type == media[0].type) { - types.unshift(uLine.type); - // Add the channel to the new media array. - session.media.unshift(uLine); - } else { - types.push(uLine.type); - // Add the channel to the new media array. - session.media.push(uLine); - } - } - }); - - if (typeof session.groups !== 'undefined') { - // We regenerate the BUNDLE group with the new mids. - session.groups.some(function(group) { - if (group.type === 'BUNDLE') { - group.mids = types.join(' '); - return true; - } - }); - } - - // msid semantic - session.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - var resStr = transform.write(session); - - return new RTCSessionDescription({ - type: desc.type, - sdp: resStr - }); - - //#endregion -}; - -/* follow rules defined in RFC4145 */ -function addSetupAttr(uLine) { - if (typeof uLine.setup === 'undefined') { - return; - } - - if (uLine.setup === "active") { - uLine.setup = "passive"; - } else if (uLine.setup === "passive") { - uLine.setup = "active"; - } -} - -/** - * This method transforms a Plan B SDP to an equivalent Unified Plan SDP. A - * PeerConnection wrapper transforms the SDP to Unified Plan before passing it - * to FF. - * - * @param desc - * @returns {*} - */ -Interop.prototype.toUnifiedPlan = function(desc) { - var self = this; - //#region Preliminary input validation. - - if (typeof desc !== 'object' || desc === null || - typeof desc.sdp !== 'string') { - console.warn('An empty description was passed as an argument.'); - return desc; - } - - var session = transform.parse(desc.sdp); - - // If the SDP contains no media, there's nothing to transform. - if (typeof session.media === 'undefined' || - !Array.isArray(session.media) || session.media.length === 0) { - console.warn('The description has no media.'); - return desc; - } - - // Try some heuristics to "make sure" this is a Plan B SDP. Plan B SDP has - // a video, an audio and a data "channel" at most. - if (session.media.length > 3 || !session.media.every(function(m) { - return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; - })) { - console.warn('This description does not look like Plan B.'); - return desc; - } - - // Make sure this Plan B SDP can be converted to a Unified Plan SDP. - var mids = []; - session.media.forEach(function(m) { - mids.push(m.mid); - }); - - var hasBundle = false; - if (typeof session.groups !== 'undefined' && - Array.isArray(session.groups)) { - hasBundle = session.groups.every(function(g) { - return g.type !== 'BUNDLE' || - arrayEquals.apply(g.mids.sort(), [mids.sort()]); - }); - } - - if (!hasBundle) { - var mustBeBundle = false; - - session.media.forEach(function(m) { - if (m.direction !== 'inactive') { - mustBeBundle = true; - } - }); - - if (mustBeBundle) { - throw new Error("Cannot convert to Unified Plan because m-lines that" + - " are not bundled were found."); - } - } - - //#endregion - - - //#region Convert from Plan B to Unified Plan. - - // Unfortunately, a Plan B offer/answer doesn't have enough information to - // rebuild an equivalent Unified Plan offer/answer. - // - // For example, if this is a local answer (in Unified Plan style) that we - // convert to Plan B prior to handing it over to the application (the - // PeerConnection wrapper called us, for instance, after a successful - // createAnswer), we want to remember the m-line at which we've seen the - // (local) SSRC. That's because when the application wants to do call the - // SLD method, forcing us to do the inverse transformation (from Plan B to - // Unified Plan), we need to know to which m-line to assign the (local) - // SSRC. We also need to know all the other m-lines that the original - // answer had and include them in the transformed answer as well. - // - // Another example is if this is a remote offer that we convert to Plan B - // prior to giving it to the application, we want to remember the mid at - // which we've seen the (remote) SSRC. - // - // In the iteration that follows, we use the cached Unified Plan (if it - // exists) to assign mids to ssrcs. - - var type; - if (desc.type === 'answer') { - type = 'offer'; - } else if (desc.type === 'offer') { - type = 'answer'; - } else { - throw new Error("Type '" + desc.type + "' not supported."); - } - - var cached; - if (typeof this.cache[type] !== 'undefined') { - cached = transform.parse(this.cache[type]); - } - - var recvonlySsrcs = { - audio: {}, - video: {} - }; - - // A helper map that sends mids to m-line objects. We use it later to - // rebuild the Unified Plan style session.media array. - var mid2ul = {}; - var bIdx = 0; - var uIdx = 0; - - var sources2ul = {}; - - var candidates; - var iceUfrag; - var icePwd; - var fingerprint; - var payloads = {}; - var rtcpFb = {}; - var rtp = {}; - - session.media.forEach(function(bLine) { - if ((typeof bLine.rtcpMux !== 'string' || - bLine.rtcpMux !== 'rtcp-mux') && - bLine.direction !== 'inactive') { - throw new Error("Cannot convert to Unified Plan because m-lines " + - "without the rtcp-mux attribute were found."); - } - - if (bLine.type === 'application') { - mid2ul[bLine.mid] = bLine; - return; - } - - // With rtcp-mux and bundle all the channels should have the same ICE - // stuff. - var sources = bLine.sources; - var ssrcGroups = bLine.ssrcGroups; - var port = bLine.port; - - /* Chrome adds different candidates even using bundle, so we concat the candidates list */ - if (typeof bLine.candidates != 'undefined') { - if (typeof candidates != 'undefined') { - candidates = candidates.concat(bLine.candidates); - } else { - candidates = bLine.candidates; - } - } - - if ((typeof iceUfrag != 'undefined') && (typeof bLine.iceUfrag != 'undefined') && (iceUfrag != bLine.iceUfrag)) { - throw new Error("Only BUNDLE supported, iceUfrag must be the same for all m-lines.\n" + - "\tLast iceUfrag: " + iceUfrag + "\n" + - "\tNew iceUfrag: " + bLine.iceUfrag - ); - } - - if (typeof bLine.iceUfrag != 'undefined') { - iceUfrag = bLine.iceUfrag; - } - - if ((typeof icePwd != 'undefined') && (typeof bLine.icePwd != 'undefined') && (icePwd != bLine.icePwd)) { - throw new Error("Only BUNDLE supported, icePwd must be the same for all m-lines.\n" + - "\tLast icePwd: " + icePwd + "\n" + - "\tNew icePwd: " + bLine.icePwd - ); - } - - if (typeof bLine.icePwd != 'undefined') { - icePwd = bLine.icePwd; - } - - if ((typeof fingerprint != 'undefined') && (typeof bLine.fingerprint != 'undefined') && - (fingerprint.type != bLine.fingerprint.type || fingerprint.hash != bLine.fingerprint.hash)) { - throw new Error("Only BUNDLE supported, fingerprint must be the same for all m-lines.\n" + - "\tLast fingerprint: " + JSON.stringify(fingerprint) + "\n" + - "\tNew fingerprint: " + JSON.stringify(bLine.fingerprint) - ); - } - - if (typeof bLine.fingerprint != 'undefined') { - fingerprint = bLine.fingerprint; - } - - payloads[bLine.type] = bLine.payloads; - rtcpFb[bLine.type] = bLine.rtcpFb; - rtp[bLine.type] = bLine.rtp; - - // inverted ssrc group map - var ssrc2group = {}; - if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) { - ssrcGroups.forEach(function (ssrcGroup) { - // XXX This might brake if an SSRC is in more than one group - // for some reason. - if (typeof ssrcGroup.ssrcs !== 'undefined' && - Array.isArray(ssrcGroup.ssrcs)) { - ssrcGroup.ssrcs.forEach(function (ssrc) { - if (typeof ssrc2group[ssrc] === 'undefined') { - ssrc2group[ssrc] = []; - } - - ssrc2group[ssrc].push(ssrcGroup); - }); - } - }); - } - - // ssrc to m-line index. - var ssrc2ml = {}; - - if (typeof sources === 'object') { - - // We'll use the "bLine" object as a prototype for each new "mLine" - // that we create, but first we need to clean it up a bit. - delete bLine.sources; - delete bLine.ssrcGroups; - delete bLine.candidates; - delete bLine.iceUfrag; - delete bLine.icePwd; - delete bLine.fingerprint; - delete bLine.port; - delete bLine.mid; - - // Explode the Plan B channel sources with one m-line per source. - Object.keys(sources).forEach(function(ssrc) { - - // The (unified) m-line for this SSRC. We either create it from - // scratch or, if it's a grouped SSRC, we re-use a related - // mline. In other words, if the source is grouped with another - // source, put the two together in the same m-line. - var uLine; - - // We assume here that we are the answerer in the O/A, so any - // offers which we translate come from the remote side, while - // answers are local. So the check below is to make that we - // handle receive-only SSRCs in a special way only if they come - // from the remote side. - if (desc.type==='offer') { - // We want to detect SSRCs which are used by a remote peer - // in an m-line with direction=recvonly (i.e. they are - // being used for RTCP only). - // This information would have gotten lost if the remote - // peer used Unified Plan and their local description was - // translated to Plan B. So we use the lack of an MSID - // attribute to deduce a "receive only" SSRC. - if (!sources[ssrc].msid) { - recvonlySsrcs[bLine.type][ssrc] = sources[ssrc]; - // Receive-only SSRCs must not create new m-lines. We - // will assign them to an existing m-line later. - return; - } - } - - if (typeof ssrc2group[ssrc] !== 'undefined' && - Array.isArray(ssrc2group[ssrc])) { - ssrc2group[ssrc].some(function (ssrcGroup) { - // ssrcGroup.ssrcs *is* an Array, no need to check - // again here. - return ssrcGroup.ssrcs.some(function (related) { - if (typeof ssrc2ml[related] === 'object') { - uLine = ssrc2ml[related]; - return true; - } - }); - }); - } - - if (typeof uLine === 'object') { - // the m-line already exists. Just add the source. - uLine.sources[ssrc] = sources[ssrc]; - delete sources[ssrc].msid; - } else { - // Use the "bLine" as a prototype for the "uLine". - uLine = Object.create(bLine); - ssrc2ml[ssrc] = uLine; - - if (typeof sources[ssrc].msid !== 'undefined') { - // Assign the msid of the source to the m-line. Note - // that it is not guaranteed that the source will have - // msid. In particular "recvonly" sources don't have an - // msid. Note that "recvonly" is a term only defined - // for m-lines. - uLine.msid = sources[ssrc].msid; - delete sources[ssrc].msid; - } - - // We assign one SSRC per media line. - uLine.sources = {}; - uLine.sources[ssrc] = sources[ssrc]; - uLine.ssrcGroups = ssrc2group[ssrc]; - - // Use the cached Unified Plan SDP (if it exists) to assign - // SSRCs to mids. - if (typeof cached !== 'undefined' && - typeof cached.media !== 'undefined' && - Array.isArray(cached.media)) { - - cached.media.forEach(function (m) { - if (typeof m.sources === 'object') { - Object.keys(m.sources).forEach(function (s) { - if (s === ssrc) { - uLine.mid = m.mid; - } - }); - } - }); - } - - if (typeof uLine.mid === 'undefined') { - - // If this is an SSRC that we see for the first time - // assign it a new mid. This is typically the case when - // this method is called to transform a remote - // description for the first time or when there is a - // new SSRC in the remote description because a new - // peer has joined the conference. Local SSRCs should - // have already been added to the map in the toPlanB - // method. - // - // Because FF generates answers in Unified Plan style, - // we MUST already have a cached answer with all the - // local SSRCs mapped to some m-line/mid. - - uLine.mid = [bLine.type, '-', ssrc].join(''); - } - - // Include the candidates in the 1st media line. - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - uLine.port = port; - - mid2ul[uLine.mid] = uLine; - sources2ul[uIdx] = uLine.sources; - - self.cache.mlU2BMap[uIdx] = bIdx; - if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { - self.cache.mlB2UMap[bIdx] = uIdx; - } - uIdx++; - } - }); - } else { - var uLine = bLine; - - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - uLine.port = port; - - mid2ul[uLine.mid] = uLine; - - self.cache.mlU2BMap[uIdx] = bIdx; - if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { - self.cache.mlB2UMap[bIdx] = uIdx; - } - } - - bIdx++; - }); - - // Rebuild the media array in the right order and add the missing mLines - // (missing from the Plan B SDP). - session.media = []; - mids = []; // reuse - - if (desc.type === 'answer') { - - // The media lines in the answer must match the media lines in the - // offer. The order is important too. Here we assume that Firefox is - // the answerer, so we merely have to use the reconstructed (unified) - // answer to update the cached (unified) answer accordingly. - // - // In the general case, one would have to use the cached (unified) - // offer to find the m-lines that are missing from the reconstructed - // answer, potentially grabbing them from the cached (unified) answer. - // One has to be careful with this approach because inactive m-lines do - // not always have an mid, making it tricky (impossible?) to find where - // exactly and which m-lines are missing from the reconstructed answer. - - for (var i = 0; i < cached.media.length; i++) { - var uLine = cached.media[i]; - - delete uLine.msid; - delete uLine.sources; - delete uLine.ssrcGroups; - - if (typeof sources2ul[i] === 'undefined') { - if (!uLine.direction - || uLine.direction === 'sendrecv') - uLine.direction = 'recvonly'; - else if (uLine.direction === 'sendonly') - uLine.direction = 'inactive'; - } else { - if (!uLine.direction - || uLine.direction === 'sendrecv') - uLine.direction = 'sendrecv'; - else if (uLine.direction === 'recvonly') - uLine.direction = 'sendonly'; - } - - uLine.sources = sources2ul[i]; - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - - uLine.rtp = rtp[uLine.type]; - uLine.payloads = payloads[uLine.type]; - uLine.rtcpFb = rtcpFb[uLine.type]; - - session.media.push(uLine); - - if (typeof uLine.mid === 'string') { - // inactive lines don't/may not have an mid. - mids.push(uLine.mid); - } - } - } else { - - // SDP offer/answer (and the JSEP spec) forbids removing an m-section - // under any circumstances. If we are no longer interested in sending a - // track, we just remove the msid and ssrc attributes and set it to - // either a=recvonly (as the reofferer, we must use recvonly if the - // other side was previously sending on the m-section, but we can also - // leave the possibility open if it wasn't previously in use), or - // a=inactive. - - if (typeof cached !== 'undefined' && - typeof cached.media !== 'undefined' && - Array.isArray(cached.media)) { - cached.media.forEach(function(uLine) { - mids.push(uLine.mid); - if (typeof mid2ul[uLine.mid] !== 'undefined') { - session.media.push(mid2ul[uLine.mid]); - } else { - delete uLine.msid; - delete uLine.sources; - delete uLine.ssrcGroups; - - if (!uLine.direction - || uLine.direction === 'sendrecv') { - uLine.direction = 'sendonly'; - } - if (!uLine.direction - || uLine.direction === 'recvonly') { - uLine.direction = 'inactive'; - } - - addSetupAttr (uLine); - session.media.push(uLine); - } - }); - } - - // Add all the remaining (new) m-lines of the transformed SDP. - Object.keys(mid2ul).forEach(function(mid) { - if (mids.indexOf(mid) === -1) { - mids.push(mid); - if (mid2ul[mid].direction === 'recvonly') { - // This is a remote recvonly channel. Add its SSRC to the - // appropriate sendrecv or sendonly channel. - // TODO(gp) what if we don't have sendrecv/sendonly - // channel? - - var done = false; - - session.media.some(function (uLine) { - if ((uLine.direction === 'sendrecv' || - uLine.direction === 'sendonly') && - uLine.type === mid2ul[mid].type) { - // mid2ul[mid] shouldn't have any ssrc-groups - Object.keys(mid2ul[mid].sources).forEach( - function (ssrc) { - uLine.sources[ssrc] = - mid2ul[mid].sources[ssrc]; - }); - - done = true; - return true; - } - }); - - if (!done) { - session.media.push(mid2ul[mid]); - } - } else { - session.media.push(mid2ul[mid]); - } - } - }); - } - - // After we have constructed the Plan Unified m-lines we can figure out - // where (in which m-line) to place the 'recvonly SSRCs'. - // Note: we assume here that we are the answerer in the O/A, so any offers - // which we translate come from the remote side, while answers are local - // (and so our last local description is cached as an 'answer'). - ["audio", "video"].forEach(function (type) { - if (!session || !session.media || !Array.isArray(session.media)) - return; - - var idx = null; - if (Object.keys(recvonlySsrcs[type]).length > 0) { - idx = self.getFirstSendingIndexFromAnswer(type); - if (idx === null){ - // If this is the first offer we receive, we don't have a - // cached answer. Assume that we will be sending media using - // the first m-line for each media type. - - for (var i = 0; i < session.media.length; i++) { - if (session.media[i].type === type) { - idx = i; - break; - } - } - } - } - - if (idx && session.media.length > idx) { - var mLine = session.media[idx]; - Object.keys(recvonlySsrcs[type]).forEach(function(ssrc) { - if (mLine.sources && mLine.sources[ssrc]) { - console.warn("Replacing an existing SSRC."); - } - if (!mLine.sources) { - mLine.sources = {}; - } - - mLine.sources[ssrc] = recvonlySsrcs[type][ssrc]; - }); - } - }); - - if (typeof session.groups !== 'undefined') { - // We regenerate the BUNDLE group (since we regenerated the mids) - session.groups.some(function(group) { - if (group.type === 'BUNDLE') { - group.mids = mids.join(' '); - return true; - } - }); - } - - // msid semantic - session.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - var resStr = transform.write(session); - - // Cache the transformed SDP (Unified Plan) for later re-use in this - // function. - this.cache[desc.type] = resStr; - - return new RTCSessionDescription({ - type: desc.type, - sdp: resStr - }); - - //#endregion -}; - -},{"./array-equals":14,"./transform":17}],17:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var transform = require('sdp-transform'); - -exports.write = function(session, opts) { - - if (typeof session !== 'undefined' && - typeof session.media !== 'undefined' && - Array.isArray(session.media)) { - - session.media.forEach(function (mLine) { - // expand sources to ssrcs - if (typeof mLine.sources !== 'undefined' && - Object.keys(mLine.sources).length !== 0) { - mLine.ssrcs = []; - Object.keys(mLine.sources).forEach(function (ssrc) { - var source = mLine.sources[ssrc]; - Object.keys(source).forEach(function (attribute) { - mLine.ssrcs.push({ - id: ssrc, - attribute: attribute, - value: source[attribute] - }); - }); - }); - delete mLine.sources; - } - - // join ssrcs in ssrc groups - if (typeof mLine.ssrcGroups !== 'undefined' && - Array.isArray(mLine.ssrcGroups)) { - mLine.ssrcGroups.forEach(function (ssrcGroup) { - if (typeof ssrcGroup.ssrcs !== 'undefined' && - Array.isArray(ssrcGroup.ssrcs)) { - ssrcGroup.ssrcs = ssrcGroup.ssrcs.join(' '); - } - }); - } - }); - } - - // join group mids - if (typeof session !== 'undefined' && - typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { - - session.groups.forEach(function (g) { - if (typeof g.mids !== 'undefined' && Array.isArray(g.mids)) { - g.mids = g.mids.join(' '); - } - }); - } - - return transform.write(session, opts); -}; - -exports.parse = function(sdp) { - var session = transform.parse(sdp); - - if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && - Array.isArray(session.media)) { - - session.media.forEach(function (mLine) { - // group sources attributes by ssrc - if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) { - mLine.sources = {}; - mLine.ssrcs.forEach(function (ssrc) { - if (!mLine.sources[ssrc.id]) - mLine.sources[ssrc.id] = {}; - mLine.sources[ssrc.id][ssrc.attribute] = ssrc.value; - }); - - delete mLine.ssrcs; - } - - // split ssrcs in ssrc groups - if (typeof mLine.ssrcGroups !== 'undefined' && - Array.isArray(mLine.ssrcGroups)) { - mLine.ssrcGroups.forEach(function (ssrcGroup) { - if (typeof ssrcGroup.ssrcs === 'string') { - ssrcGroup.ssrcs = ssrcGroup.ssrcs.split(' '); - } - }); - } - }); - } - // split group mids - if (typeof session !== 'undefined' && - typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { - - session.groups.forEach(function (g) { - if (typeof g.mids === 'string') { - g.mids = g.mids.split(' '); - } - }); - } - - return session; -}; - - -},{"sdp-transform":11}],18:[function(require,module,exports){ -/*! - * UAParser.js v0.7.18 - * Lightweight JavaScript-based User-Agent string parser - * https://github.com/faisalman/ua-parser-js - * - * Copyright © 2012-2016 Faisal Salman - * Dual licensed under GPLv2 or MIT - */ - -(function (window, undefined) { - - 'use strict'; - - ////////////// - // Constants - ///////////// - - - var LIBVERSION = '0.7.18', - EMPTY = '', - UNKNOWN = '?', - FUNC_TYPE = 'function', - UNDEF_TYPE = 'undefined', - OBJ_TYPE = 'object', - STR_TYPE = 'string', - MAJOR = 'major', // deprecated - MODEL = 'model', - NAME = 'name', - TYPE = 'type', - VENDOR = 'vendor', - VERSION = 'version', - ARCHITECTURE= 'architecture', - CONSOLE = 'console', - MOBILE = 'mobile', - TABLET = 'tablet', - SMARTTV = 'smarttv', - WEARABLE = 'wearable', - EMBEDDED = 'embedded'; - - - /////////// - // Helper - ////////// - - - var util = { - extend : function (regexes, extensions) { - var margedRegexes = {}; - for (var i in regexes) { - if (extensions[i] && extensions[i].length % 2 === 0) { - margedRegexes[i] = extensions[i].concat(regexes[i]); - } else { - margedRegexes[i] = regexes[i]; - } - } - return margedRegexes; - }, - has : function (str1, str2) { - if (typeof str1 === "string") { - return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; - } else { - return false; - } - }, - lowerize : function (str) { - return str.toLowerCase(); - }, - major : function (version) { - return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g,'').split(".")[0] : undefined; - }, - trim : function (str) { - return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); - } - }; - - - /////////////// - // Map helper - ////////////// - - - var mapper = { - - rgx : function (ua, arrays) { - - //var result = {}, - var i = 0, j, k, p, q, matches, match;//, args = arguments; - - /*// construct object barebones - for (p = 0; p < args[1].length; p++) { - q = args[1][p]; - result[typeof q === OBJ_TYPE ? q[0] : q] = undefined; - }*/ - - // loop through all regexes maps - while (i < arrays.length && !matches) { - - var regex = arrays[i], // even sequence (0,2,4,..) - props = arrays[i + 1]; // odd sequence (1,3,5,..) - j = k = 0; - - // try matching uastring with regexes - while (j < regex.length && !matches) { - - matches = regex[j++].exec(ua); - - if (!!matches) { - for (p = 0; p < props.length; p++) { - match = matches[++k]; - q = props[p]; - // check if given property is actually array - if (typeof q === OBJ_TYPE && q.length > 0) { - if (q.length == 2) { - if (typeof q[1] == FUNC_TYPE) { - // assign modified match - this[q[0]] = q[1].call(this, match); - } else { - // assign given value, ignore regex match - this[q[0]] = q[1]; - } - } else if (q.length == 3) { - // check whether function or regex - if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { - // call function (usually string mapper) - this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; - } else { - // sanitize match using given regex - this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; - } - } else if (q.length == 4) { - this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; - } - } else { - this[q] = match ? match : undefined; - } - } - } - } - i += 2; - } - // console.log(this); - //return this; - }, - - str : function (str, map) { - - for (var i in map) { - // check if array - if (typeof map[i] === OBJ_TYPE && map[i].length > 0) { - for (var j = 0; j < map[i].length; j++) { - if (util.has(map[i][j], str)) { - return (i === UNKNOWN) ? undefined : i; - } - } - } else if (util.has(map[i], str)) { - return (i === UNKNOWN) ? undefined : i; - } - } - return str; - } - }; - - - /////////////// - // String map - ////////////// - - - var maps = { - - browser : { - oldsafari : { - version : { - '1.0' : '/8', - '1.2' : '/1', - '1.3' : '/3', - '2.0' : '/412', - '2.0.2' : '/416', - '2.0.3' : '/417', - '2.0.4' : '/419', - '?' : '/' - } - } - }, - - device : { - amazon : { - model : { - 'Fire Phone' : ['SD', 'KF'] - } - }, - sprint : { - model : { - 'Evo Shift 4G' : '7373KT' - }, - vendor : { - 'HTC' : 'APA', - 'Sprint' : 'Sprint' - } - } - }, - - os : { - windows : { - version : { - 'ME' : '4.90', - 'NT 3.11' : 'NT3.51', - 'NT 4.0' : 'NT4.0', - '2000' : 'NT 5.0', - 'XP' : ['NT 5.1', 'NT 5.2'], - 'Vista' : 'NT 6.0', - '7' : 'NT 6.1', - '8' : 'NT 6.2', - '8.1' : 'NT 6.3', - '10' : ['NT 6.4', 'NT 10.0'], - 'RT' : 'ARM' - } - } - } - }; - - - ////////////// - // Regex map - ///////////// - - - var regexes = { - - browser : [[ - - // Presto based - /(opera\smini)\/([\w\.-]+)/i, // Opera Mini - /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet - /(opera).+version\/([\w\.]+)/i, // Opera > 9.80 - /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 - ], [NAME, VERSION], [ - - /(opios)[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0 - ], [[NAME, 'Opera Mini'], VERSION], [ - - /\s(opr)\/([\w\.]+)/i // Opera Webkit - ], [[NAME, 'Opera'], VERSION], [ - - // Mixed - /(kindle)\/([\w\.]+)/i, // Kindle - /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]*)/i, - // Lunascape/Maxthon/Netfront/Jasmine/Blazer - - // Trident based - /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i, - // Avant/IEMobile/SlimBrowser/Baidu - /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer - - // Webkit/KHTML based - /(rekonq)\/([\w\.]*)/i, // Rekonq - /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark)\/([\w\.-]+)/i - // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser - ], [NAME, VERSION], [ - - /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11 - ], [[NAME, 'IE'], VERSION], [ - - /(edge|edgios|edgea)\/((\d+)?[\w\.]+)/i // Microsoft Edge - ], [[NAME, 'Edge'], VERSION], [ - - /(yabrowser)\/([\w\.]+)/i // Yandex - ], [[NAME, 'Yandex'], VERSION], [ - - /(puffin)\/([\w\.]+)/i // Puffin - ], [[NAME, 'Puffin'], VERSION], [ - - /((?:[\s\/])uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i - // UCBrowser - ], [[NAME, 'UCBrowser'], VERSION], [ - - /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon - ], [[NAME, /_/g, ' '], VERSION], [ - - /(micromessenger)\/([\w\.]+)/i // WeChat - ], [[NAME, 'WeChat'], VERSION], [ - - /(qqbrowserlite)\/([\w\.]+)/i // QQBrowserLite - ], [NAME, VERSION], [ - - /(QQ)\/([\d\.]+)/i // QQ, aka ShouQ - ], [NAME, VERSION], [ - - /m?(qqbrowser)[\/\s]?([\w\.]+)/i // QQBrowser - ], [NAME, VERSION], [ - - /(BIDUBrowser)[\/\s]?([\w\.]+)/i // Baidu Browser - ], [NAME, VERSION], [ - - /(2345Explorer)[\/\s]?([\w\.]+)/i // 2345 Browser - ], [NAME, VERSION], [ - - /(MetaSr)[\/\s]?([\w\.]+)/i // SouGouBrowser - ], [NAME], [ - - /(LBBROWSER)/i // LieBao Browser - ], [NAME], [ - - /xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser - ], [VERSION, [NAME, 'MIUI Browser']], [ - - /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android - ], [VERSION, [NAME, 'Facebook']], [ - - /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless - ], [VERSION, [NAME, 'Chrome Headless']], [ - - /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView - ], [[NAME, /(.+)/, '$1 WebView'], VERSION], [ - - /((?:oculus|samsung)browser)\/([\w\.]+)/i - ], [[NAME, /(.+(?:g|us))(.+)/, '$1 $2'], VERSION], [ // Oculus / Samsung Browser - - /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)*/i // Android Browser - ], [VERSION, [NAME, 'Android Browser']], [ - - /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i - // Chrome/OmniWeb/Arora/Tizen/Nokia - ], [NAME, VERSION], [ - - /(dolfin)\/([\w\.]+)/i // Dolphin - ], [[NAME, 'Dolphin'], VERSION], [ - - /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS - ], [[NAME, 'Chrome'], VERSION], [ - - /(coast)\/([\w\.]+)/i // Opera Coast - ], [[NAME, 'Opera Coast'], VERSION], [ - - /fxios\/([\w\.-]+)/i // Firefox for iOS - ], [VERSION, [NAME, 'Firefox']], [ - - /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari - ], [VERSION, [NAME, 'Mobile Safari']], [ - - /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile - ], [VERSION, NAME], [ - - /webkit.+?(gsa)\/([\w\.]+).+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Google Search Appliance on iOS - ], [[NAME, 'GSA'], VERSION], [ - - /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 - ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [ - - /(konqueror)\/([\w\.]+)/i, // Konqueror - /(webkit|khtml)\/([\w\.]+)/i - ], [NAME, VERSION], [ - - // Gecko based - /(navigator|netscape)\/([\w\.-]+)/i // Netscape - ], [[NAME, 'Netscape'], VERSION], [ - /(swiftfox)/i, // Swiftfox - /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i, - // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror - /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([\w\.-]+)$/i, - - // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix - /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla - - // Other - /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i, - // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir - /(links)\s\(([\w\.]+)/i, // Links - /(gobrowser)\/?([\w\.]*)/i, // GoBrowser - /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser - /(mosaic)[\/\s]([\w\.]+)/i // Mosaic - ], [NAME, VERSION] - - /* ///////////////////// - // Media players BEGIN - //////////////////////// - - , [ - - /(apple(?:coremedia|))\/((\d+)[\w\._]+)/i, // Generic Apple CoreMedia - /(coremedia) v((\d+)[\w\._]+)/i - ], [NAME, VERSION], [ - - /(aqualung|lyssna|bsplayer)\/((\d+)?[\w\.-]+)/i // Aqualung/Lyssna/BSPlayer - ], [NAME, VERSION], [ - - /(ares|ossproxy)\s((\d+)[\w\.-]+)/i // Ares/OSSProxy - ], [NAME, VERSION], [ - - /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/((\d+)[\w\.-]+)/i, - // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC - // NSPlayer/PSP-InternetRadioPlayer/Videos - /(clementine|music player daemon)\s((\d+)[\w\.-]+)/i, // Clementine/MPD - /(lg player|nexplayer)\s((\d+)[\d\.]+)/i, - /player\/(nexplayer|lg player)\s((\d+)[\w\.-]+)/i // NexPlayer/LG Player - ], [NAME, VERSION], [ - /(nexplayer)\s((\d+)[\w\.-]+)/i // Nexplayer - ], [NAME, VERSION], [ - - /(flrp)\/((\d+)[\w\.-]+)/i // Flip Player - ], [[NAME, 'Flip Player'], VERSION], [ - - /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i - // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit - ], [NAME], [ - - /(gstreamer) souphttpsrc (?:\([^\)]+\)){0,1} libsoup\/((\d+)[\w\.-]+)/i - // Gstreamer - ], [NAME, VERSION], [ - - /(htc streaming player)\s[\w_]+\s\/\s((\d+)[\d\.]+)/i, // HTC Streaming Player - /(java|python-urllib|python-requests|wget|libcurl)\/((\d+)[\w\.-_]+)/i, - // Java/urllib/requests/wget/cURL - /(lavf)((\d+)[\d\.]+)/i // Lavf (FFMPEG) - ], [NAME, VERSION], [ - - /(htc_one_s)\/((\d+)[\d\.]+)/i // HTC One S - ], [[NAME, /_/g, ' '], VERSION], [ - - /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+){0,1})/i - // MPlayer SVN - ], [NAME, VERSION], [ - - /(mplayer)(?:\s|\/|[unkow-]+)((\d+)[\w\.-]+)/i // MPlayer - ], [NAME, VERSION], [ - - /(mplayer)/i, // MPlayer (no other info) - /(yourmuze)/i, // YourMuze - /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime - ], [NAME], [ - - /(nero (?:home|scout))\/((\d+)[\w\.-]+)/i // Nero Home/Nero Scout - ], [NAME, VERSION], [ - - /(nokia\d+)\/((\d+)[\w\.-]+)/i // Nokia - ], [NAME, VERSION], [ - - /\s(songbird)\/((\d+)[\w\.-]+)/i // Songbird/Philips-Songbird - ], [NAME, VERSION], [ - - /(winamp)3 version ((\d+)[\w\.-]+)/i, // Winamp - /(winamp)\s((\d+)[\w\.-]+)/i, - /(winamp)mpeg\/((\d+)[\w\.-]+)/i - ], [NAME, VERSION], [ - - /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) - // inlight radio - ], [NAME], [ - - /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/((\d+)[\w\.-]+)/i - // QuickTime/RealMedia/RadioApp/RadioClientApplication/ - // SoundTap/Totem/Stagefright/Streamium - ], [NAME, VERSION], [ - - /(smp)((\d+)[\d\.]+)/i // SMP - ], [NAME, VERSION], [ - - /(vlc) media player - version ((\d+)[\w\.]+)/i, // VLC Videolan - /(vlc)\/((\d+)[\w\.-]+)/i, - /(xbmc|gvfs|xine|xmms|irapp)\/((\d+)[\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp - /(foobar2000)\/((\d+)[\d\.]+)/i, // Foobar2000 - /(itunes)\/((\d+)[\d\.]+)/i // iTunes - ], [NAME, VERSION], [ - - /(wmplayer)\/((\d+)[\w\.-]+)/i, // Windows Media Player - /(windows-media-player)\/((\d+)[\w\.-]+)/i - ], [[NAME, /-/g, ' '], VERSION], [ - - /windows\/((\d+)[\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i - // Windows Media Server - ], [VERSION, [NAME, 'Windows']], [ - - /(com\.riseupradioalarm)\/((\d+)[\d\.]*)/i // RiseUP Radio Alarm - ], [NAME, VERSION], [ - - /(rad.io)\s((\d+)[\d\.]+)/i, // Rad.io - /(radio.(?:de|at|fr))\s((\d+)[\d\.]+)/i - ], [[NAME, 'rad.io'], VERSION] - - ////////////////////// - // Media players END - ////////////////////*/ - - ], - - cpu : [[ - - /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 - ], [[ARCHITECTURE, 'amd64']], [ - - /(ia32(?=;))/i // IA32 (quicktime) - ], [[ARCHITECTURE, util.lowerize]], [ - - /((?:i[346]|x)86)[;\)]/i // IA32 - ], [[ARCHITECTURE, 'ia32']], [ - - // PocketPC mistakenly identified as PowerPC - /windows\s(ce|mobile);\sppc;/i - ], [[ARCHITECTURE, 'arm']], [ - - /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC - ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [ - - /(sun4\w)[;\)]/i // SPARC - ], [[ARCHITECTURE, 'sparc']], [ - - /((?:avr32|ia64(?=;))|68k(?=\))|arm(?:64|(?=v\d+;))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)/i - // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC - ], [[ARCHITECTURE, util.lowerize]] - ], - - device : [[ - - /\((ipad|playbook);[\w\s\);-]+(rim|apple)/i // iPad/PlayBook - ], [MODEL, VENDOR, [TYPE, TABLET]], [ - - /applecoremedia\/[\w\.]+ \((ipad)/ // iPad - ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ - - /(apple\s{0,1}tv)/i // Apple TV - ], [[MODEL, 'Apple TV'], [VENDOR, 'Apple']], [ - - /(archos)\s(gamepad2?)/i, // Archos - /(hp).+(touchpad)/i, // HP TouchPad - /(hp).+(tablet)/i, // HP Tablet - /(kindle)\/([\w\.]+)/i, // Kindle - /\s(nook)[\w\s]+build\/(\w+)/i, // Nook - /(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /(kf[A-z]+)\sbuild\/.+silk\//i // Kindle Fire HD - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ - /(sd|kf)[0349hijorstuw]+\sbuild\/.+silk\//i // Fire Phone - ], [[MODEL, mapper.str, maps.device.amazon.model], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ - - /\((ip[honed|\s\w*]+);.+(apple)/i // iPod/iPhone - ], [MODEL, VENDOR, [TYPE, MOBILE]], [ - /\((ip[honed|\s\w*]+);/i // iPod/iPhone - ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ - - /(blackberry)[\s-]?(\w+)/i, // BlackBerry - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]*)/i, - // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron - /(hp)\s([\w\s]+\w)/i, // HP iPAQ - /(asus)-?(\w+)/i // Asus - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /\(bb10;\s(\w+)/i // BlackBerry 10 - ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ - // Asus Tablets - /android.+(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7|padfone)/i - ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [ - - /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony - /(sony)?(?:sgp.+)\sbuild\//i - ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [ - /android.+\s([c-g]\d{4}|so[-l]\w+)\sbuild\//i - ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - - /\s(ouya)\s/i, // Ouya - /(nintendo)\s([wids3u]+)/i // Nintendo - ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ - - /android.+;\s(shield)\sbuild/i // Nvidia - ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ - - /(playstation\s[34portablevi]+)/i // Playstation - ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ - - /(sprint\s(\w+))/i // Sprint Phones - ], [[VENDOR, mapper.str, maps.device.sprint.vendor], [MODEL, mapper.str, maps.device.sprint.model], [TYPE, MOBILE]], [ - - /(lenovo)\s?(S(?:5000|6000)+(?:[-][\w+]))/i // Lenovo tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC - /(zte)-(\w*)/i, // ZTE - /(alcatel|geeksphone|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]*)/i - // Alcatel/GeeksPhone/Lenovo/Nexian/Panasonic/Sony - ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ - - /(nexus\s9)/i // HTC Nexus 9 - ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ - - /d\/huawei([\w\s-]+)[;\)]/i, - /(nexus\s6p)/i // Huawei - ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ - - /(microsoft);\s(lumia[\s\w]+)/i // Microsoft Lumia - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /[\s\(;](xbox(?:\sone)?)[\s\);]/i // Microsoft Xbox - ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [ - /(kin\.[onetw]{3})/i // Microsoft Kin - ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ - - // Motorola - /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?:?(\s4g)?)[\w\s]+build\//i, - /mot[\s-]?(\w*)/i, - /(XT\d{3,4}) build\//i, - /(nexus\s6)/i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ - /android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [ - - /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices - ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ - - /hbbtv.+maple;(\d+)/i - ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [ - - /\(dtv[\);].+(aquos)/i // Sharp - ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [ - - /android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10))/i, - /((SM-T\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung - /smart-tv.+(samsung)/i - ], [VENDOR, [TYPE, SMARTTV], MODEL], [ - /((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+))/i, - /(sam[sung]*)[\s-]*(\w+-?[\w-]*)/i, - /sec-((sgh\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [ - - /sie-(\w*)/i // Siemens - ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ - - /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia - /(nokia)[\s_-]?([\w-]*)/i - ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [ - - /android\s3\.[\s\w;-]{10}(a\d{3})/i // Acer - ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ - - /android.+([vl]k\-?\d{3})\s+build/i // LG Tablet - ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [ - /android\s3\.[\s\w;-]{10}(lg?)-([06cv9]{3,4})/i // LG Tablet - ], [[VENDOR, 'LG'], MODEL, [TYPE, TABLET]], [ - /(lg) netcast\.tv/i // LG SmartTV - ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ - /(nexus\s[45])/i, // LG - /lg[e;\s\/-]+(\w*)/i, - /android.+lg(\-?[\d\w]+)\s+build/i - ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [ - - /android.+(ideatab[a-z0-9\-\s]+)/i // Lenovo - ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ - - /linux;.+((jolla));/i // Jolla - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /((pebble))app\/[\d\.]+\s/i // Pebble - ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ - - /android.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /crkey/i // Google Chromecast - ], [[MODEL, 'Chromecast'], [VENDOR, 'Google']], [ - - /android.+;\s(glass)\s\d/i // Google Glass - ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [ - - /android.+;\s(pixel c)\s/i // Google Pixel C - ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ - - /android.+;\s(pixel xl|pixel)\s/i // Google Pixel - ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ - - /android.+;\s(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models - /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi - /android.+(mi[\s\-_]*(?:one|one[\s_]plus|note lte)?[\s_]*(?:\d?\w?)[\s_]*(?:plus)?)\s+build/i, // Xiaomi Mi - /android.+(redmi[\s\-_]*(?:note)?(?:[\s_]*[\w\s]+))\s+build/i // Redmi Phones - ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ - /android.+(mi[\s\-_]*(?:pad)(?:[\s_]*[\w\s]+))\s+build/i // Mi Pad tablets - ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ - /android.+;\s(m[1-5]\snote)\sbuild/i // Meizu Tablet - ], [MODEL, [VENDOR, 'Meizu'], [TYPE, TABLET]], [ - - /android.+a000(1)\s+build/i, // OnePlus - /android.+oneplus\s(a\d{4})\s+build/i - ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(RCT[\d\w]+)\s+build/i // RCA Tablets - ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ - - /android.+[;\/\s]+(Venue[\d\s]{2,7})\s+build/i // Dell Venue Tablets - ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Q[T|M][\d\w]+)\s+build/i // Verizon Tablet - ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ - - /android.+[;\/]\s+(Barnes[&\s]+Noble\s+|BN[RT])(V?.*)\s+build/i // Barnes & Noble Tablet - ], [[VENDOR, 'Barnes & Noble'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s+(TM\d{3}.*\b)\s+build/i // Barnes & Noble Tablet - ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ - - /android.+;\s(k88)\sbuild/i // ZTE K Series Tablet - ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(gen\d{3})\s+build.*49h/i // Swiss GEN Mobile - ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(zur\d{3})\s+build/i // Swiss ZUR Tablet - ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((Zeki)?TB.*\b)\s+build/i // Zeki Tablets - ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ - - /(android).+[;\/]\s+([YR]\d{2})\s+build/i, - /android.+[;\/]\s+(Dragon[\-\s]+Touch\s+|DT)(\w{5})\sbuild/i // Dragon Touch Tablet - ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*(NS-?\w{0,9})\sbuild/i // Insignia Tablets - ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((NX|Next)-?\w{0,9})\s+build/i // NextBook Tablets - ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Xtreme\_)?(V(1[045]|2[015]|30|40|60|7[05]|90))\s+build/i - ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones - - /android.+[;\/]\s*(LVTEL\-)?(V1[12])\s+build/i // LvTel Phones - ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(V(100MD|700NA|7011|917G).*\b)\s+build/i // Envizen Tablets - ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Le[\s\-]+Pan)[\s\-]+(\w{1,9})\s+build/i // Le Pan Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Trio[\s\-]*.*)\s+build/i // MachSpeed Tablets - ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Trinity)[\-\s]*(T\d{3})\s+build/i // Trinity Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*TU_(1491)\s+build/i // Rotor Tablets - ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ - - /android.+(KS(.+))\s+build/i // Amazon Kindle Tablets - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ - - /android.+(Gigaset)[\s\-]+(Q\w{1,9})\s+build/i // Gigaset Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet - /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile - ], [[TYPE, util.lowerize], VENDOR, MODEL], [ - - /(android[\w\.\s\-]{0,9});.+build/i // Generic Android Device - ], [MODEL, [VENDOR, 'Generic']] - - - /*////////////////////////// - // TODO: move to string map - //////////////////////////// - - /(C6603)/i // Sony Xperia Z C6603 - ], [[MODEL, 'Xperia Z C6603'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - /(C6903)/i // Sony Xperia Z 1 - ], [[MODEL, 'Xperia Z 1'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - - /(SM-G900[F|H])/i // Samsung Galaxy S5 - ], [[MODEL, 'Galaxy S5'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G7102)/i // Samsung Galaxy Grand 2 - ], [[MODEL, 'Galaxy Grand 2'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G530H)/i // Samsung Galaxy Grand Prime - ], [[MODEL, 'Galaxy Grand Prime'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G313HZ)/i // Samsung Galaxy V - ], [[MODEL, 'Galaxy V'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-T805)/i // Samsung Galaxy Tab S 10.5 - ], [[MODEL, 'Galaxy Tab S 10.5'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ - /(SM-G800F)/i // Samsung Galaxy S5 Mini - ], [[MODEL, 'Galaxy S5 Mini'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-T311)/i // Samsung Galaxy Tab 3 8.0 - ], [[MODEL, 'Galaxy Tab 3 8.0'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ - - /(T3C)/i // Advan Vandroid T3C - ], [MODEL, [VENDOR, 'Advan'], [TYPE, TABLET]], [ - /(ADVAN T1J\+)/i // Advan Vandroid T1J+ - ], [[MODEL, 'Vandroid T1J+'], [VENDOR, 'Advan'], [TYPE, TABLET]], [ - /(ADVAN S4A)/i // Advan Vandroid S4A - ], [[MODEL, 'Vandroid S4A'], [VENDOR, 'Advan'], [TYPE, MOBILE]], [ - - /(V972M)/i // ZTE V972M - ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [ - - /(i-mobile)\s(IQ\s[\d\.]+)/i // i-mobile IQ - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /(IQ6.3)/i // i-mobile IQ IQ 6.3 - ], [[MODEL, 'IQ 6.3'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ - /(i-mobile)\s(i-style\s[\d\.]+)/i // i-mobile i-STYLE - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /(i-STYLE2.1)/i // i-mobile i-STYLE 2.1 - ], [[MODEL, 'i-STYLE 2.1'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ - - /(mobiistar touch LAI 512)/i // mobiistar touch LAI 512 - ], [[MODEL, 'Touch LAI 512'], [VENDOR, 'mobiistar'], [TYPE, MOBILE]], [ - - ///////////// - // END TODO - ///////////*/ - - ], - - engine : [[ - - /windows.+\sedge\/([\w\.]+)/i // EdgeHTML - ], [VERSION, [NAME, 'EdgeHTML']], [ - - /(presto)\/([\w\.]+)/i, // Presto - /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m - /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links - /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab - ], [NAME, VERSION], [ - - /rv\:([\w\.]{1,9}).+(gecko)/i // Gecko - ], [VERSION, NAME] - ], - - os : [[ - - // Windows based - /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes) - ], [NAME, VERSION], [ - /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT - /(windows\sphone(?:\sos)*)[\s\/]?([\d\.\s\w]*)/i, // Windows Phone - /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i - ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ - /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i - ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ - - // Mobile/Embedded OS - /\((bb)(10);/i // BlackBerry 10 - ], [[NAME, 'BlackBerry'], VERSION], [ - /(blackberry)\w*\/?([\w\.]*)/i, // Blackberry - /(tizen)[\/\s]([\w\.]+)/i, // Tizen - /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]*)/i, - // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki - /linux;.+(sailfish);/i // Sailfish OS - ], [NAME, VERSION], [ - /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]*)/i // Symbian - ], [[NAME, 'Symbian'], VERSION], [ - /\((series40);/i // Series 40 - ], [NAME], [ - /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS - ], [[NAME, 'Firefox OS'], VERSION], [ - - // Console - /(nintendo|playstation)\s([wids34portablevu]+)/i, // Nintendo/Playstation - - // GNU/Linux based - /(mint)[\/\s\(]?(\w*)/i, // Mint - /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux - /(joli|[kxln]?ubuntu|debian|suse|opensuse|gentoo|(?=\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?(?!chrom)([\w\.-]*)/i, - // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware - // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus - /(hurd|linux)\s?([\w\.]*)/i, // Hurd/Linux - /(gnu)\s?([\w\.]*)/i // GNU - ], [NAME, VERSION], [ - - /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS - ], [[NAME, 'Chromium OS'], VERSION],[ - - // Solaris - /(sunos)\s?([\w\.\d]*)/i // Solaris - ], [[NAME, 'Solaris'], VERSION], [ - - // BSD based - /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]*)/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly - ], [NAME, VERSION],[ - - /(haiku)\s(\w+)/i // Haiku - ], [NAME, VERSION],[ - - /cfnetwork\/.+darwin/i, - /ip[honead]{2,4}(?:.*os\s([\w]+)\slike\smac|;\sopera)/i // iOS - ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ - - /(mac\sos\sx)\s?([\w\s\.]*)/i, - /(macintosh|mac(?=_powerpc)\s)/i // Mac OS - ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ - - // Other - /((?:open)?solaris)[\/\s-]?([\w\.]*)/i, // Solaris - /(aix)\s((\d)(?=\.|\)|\s)[\w\.])*/i, // AIX - /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i, - // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS - /(unix)\s?([\w\.]*)/i // UNIX - ], [NAME, VERSION] - ] - }; - - - ///////////////// - // Constructor - //////////////// - /* - var Browser = function (name, version) { - this[NAME] = name; - this[VERSION] = version; - }; - var CPU = function (arch) { - this[ARCHITECTURE] = arch; - }; - var Device = function (vendor, model, type) { - this[VENDOR] = vendor; - this[MODEL] = model; - this[TYPE] = type; - }; - var Engine = Browser; - var OS = Browser; - */ - var UAParser = function (uastring, extensions) { - - if (typeof uastring === 'object') { - extensions = uastring; - uastring = undefined; - } - - if (!(this instanceof UAParser)) { - return new UAParser(uastring, extensions).getResult(); - } - - var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); - var rgxmap = extensions ? util.extend(regexes, extensions) : regexes; - //var browser = new Browser(); - //var cpu = new CPU(); - //var device = new Device(); - //var engine = new Engine(); - //var os = new OS(); - - this.getBrowser = function () { - var browser = { name: undefined, version: undefined }; - mapper.rgx.call(browser, ua, rgxmap.browser); - browser.major = util.major(browser.version); // deprecated - return browser; - }; - this.getCPU = function () { - var cpu = { architecture: undefined }; - mapper.rgx.call(cpu, ua, rgxmap.cpu); - return cpu; - }; - this.getDevice = function () { - var device = { vendor: undefined, model: undefined, type: undefined }; - mapper.rgx.call(device, ua, rgxmap.device); - return device; - }; - this.getEngine = function () { - var engine = { name: undefined, version: undefined }; - mapper.rgx.call(engine, ua, rgxmap.engine); - return engine; - }; - this.getOS = function () { - var os = { name: undefined, version: undefined }; - mapper.rgx.call(os, ua, rgxmap.os); - return os; - }; - this.getResult = function () { - return { - ua : this.getUA(), - browser : this.getBrowser(), - engine : this.getEngine(), - os : this.getOS(), - device : this.getDevice(), - cpu : this.getCPU() - }; - }; - this.getUA = function () { - return ua; - }; - this.setUA = function (uastring) { - ua = uastring; - //browser = new Browser(); - //cpu = new CPU(); - //device = new Device(); - //engine = new Engine(); - //os = new OS(); - return this; - }; - return this; - }; - - UAParser.VERSION = LIBVERSION; - UAParser.BROWSER = { - NAME : NAME, - MAJOR : MAJOR, // deprecated - VERSION : VERSION - }; - UAParser.CPU = { - ARCHITECTURE : ARCHITECTURE - }; - UAParser.DEVICE = { - MODEL : MODEL, - VENDOR : VENDOR, - TYPE : TYPE, - CONSOLE : CONSOLE, - MOBILE : MOBILE, - SMARTTV : SMARTTV, - TABLET : TABLET, - WEARABLE: WEARABLE, - EMBEDDED: EMBEDDED - }; - UAParser.ENGINE = { - NAME : NAME, - VERSION : VERSION - }; - UAParser.OS = { - NAME : NAME, - VERSION : VERSION - }; - //UAParser.Utils = util; - - /////////// - // Export - ////////// - - - // check js environment - if (typeof(exports) !== UNDEF_TYPE) { - // nodejs env - if (typeof module !== UNDEF_TYPE && module.exports) { - exports = module.exports = UAParser; - } - // TODO: test!!!!!!!! - /* - if (require && require.main === module && process) { - // cli - var jsonize = function (arr) { - var res = []; - for (var i in arr) { - res.push(new UAParser(arr[i]).getResult()); - } - process.stdout.write(JSON.stringify(res, null, 2) + '\n'); - }; - if (process.stdin.isTTY) { - // via args - jsonize(process.argv.slice(2)); - } else { - // via pipe - var str = ''; - process.stdin.on('readable', function() { - var read = process.stdin.read(); - if (read !== null) { - str += read; - } - }); - process.stdin.on('end', function () { - jsonize(str.replace(/\n$/, '').split('\n')); - }); - } - } - */ - exports.UAParser = UAParser; - } else { - // requirejs env (optional) - if (typeof(define) === FUNC_TYPE && define.amd) { - define(function () { - return UAParser; - }); - } else if (window) { - // browser env - window.UAParser = UAParser; - } - } - - // jQuery/Zepto specific (optional) - // Note: - // In AMD env the global scope should be kept clean, but jQuery is an exception. - // jQuery always exports to global scope, unless jQuery.noConflict(true) is used, - // and we should catch that. - var $ = window && (window.jQuery || window.Zepto); - if (typeof $ !== UNDEF_TYPE) { - var parser = new UAParser(); - $.ua = parser.getResult(); - $.ua.get = function () { - return parser.getUA(); - }; - $.ua.set = function (uastring) { - parser.setUA(uastring); - var result = parser.getResult(); - for (var prop in result) { - $.ua[prop] = result[prop]; - } - }; - } - -})(typeof window === 'object' ? window : this); - -},{}],19:[function(require,module,exports){ -var v1 = require('./v1'); -var v4 = require('./v4'); - -var uuid = v4; -uuid.v1 = v1; -uuid.v4 = v4; - -module.exports = uuid; - -},{"./v1":22,"./v4":23}],20:[function(require,module,exports){ -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = []; -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1); -} - -function bytesToUuid(buf, offset) { - var i = offset || 0; - var bth = byteToHex; - return bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]]; -} - -module.exports = bytesToUuid; - -},{}],21:[function(require,module,exports){ -// Unique ID creation requires a high quality random # generator. In the -// browser this is a little complicated due to unknown quality of Math.random() -// and inconsistent support for the `crypto` API. We do the best we can via -// feature-detection - -// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. -var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) || - (typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto)); -if (getRandomValues) { - // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto - var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef - - module.exports = function whatwgRNG() { - getRandomValues(rnds8); - return rnds8; - }; -} else { - // Math.random()-based (RNG) - // - // If all else fails, use Math.random(). It's fast, but is of unspecified - // quality. - var rnds = new Array(16); - - module.exports = function mathRNG() { - for (var i = 0, r; i < 16; i++) { - if ((i & 0x03) === 0) r = Math.random() * 0x100000000; - rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; - } - - return rnds; - }; -} - -},{}],22:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); - -// **`v1()` - Generate time-based UUID** -// -// Inspired by https://github.com/LiosK/UUID.js -// and http://docs.python.org/library/uuid.html - -var _nodeId; -var _clockseq; - -// Previous uuid creation time -var _lastMSecs = 0; -var _lastNSecs = 0; - -// See https://github.com/broofa/node-uuid for API details -function v1(options, buf, offset) { - var i = buf && offset || 0; - var b = buf || []; - - options = options || {}; - var node = options.node || _nodeId; - var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; - - // node and clockseq need to be initialized to random values if they're not - // specified. We do this lazily to minimize issues related to insufficient - // system entropy. See #189 - if (node == null || clockseq == null) { - var seedBytes = rng(); - if (node == null) { - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - node = _nodeId = [ - seedBytes[0] | 0x01, - seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] - ]; - } - if (clockseq == null) { - // Per 4.2.2, randomize (14 bit) clockseq - clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; - } - } - - // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); - - // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; - - // Time since last uuid creation (in msecs) - var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; - - // Per 4.2.1.2, Bump clockseq on clock regression - if (dt < 0 && options.clockseq === undefined) { - clockseq = clockseq + 1 & 0x3fff; - } - - // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { - nsecs = 0; - } - - // Per 4.2.1.2 Throw error if too many uuids are requested - if (nsecs >= 10000) { - throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; - - // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - msecs += 12219292800000; - - // `time_low` - var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; - - // `time_mid` - var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; - - // `time_high_and_version` - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - b[i++] = tmh >>> 16 & 0xff; - - // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - b[i++] = clockseq >>> 8 | 0x80; - - // `clock_seq_low` - b[i++] = clockseq & 0xff; - - // `node` - for (var n = 0; n < 6; ++n) { - b[i + n] = node[n]; - } - - return buf ? buf : bytesToUuid(b); -} - -module.exports = v1; - -},{"./lib/bytesToUuid":20,"./lib/rng":21}],23:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); - -function v4(options, buf, offset) { - var i = buf && offset || 0; - - if (typeof(options) == 'string') { - buf = options === 'binary' ? new Array(16) : null; - options = null; - } - options = options || {}; - - var rnds = options.random || (options.rng || rng)(); - - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = (rnds[6] & 0x0f) | 0x40; - rnds[8] = (rnds[8] & 0x3f) | 0x80; - - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ++ii) { - buf[i + ii] = rnds[ii]; - } - } - - return buf || bytesToUuid(rnds); -} - -module.exports = v4; - -},{"./lib/bytesToUuid":20,"./lib/rng":21}],24:[function(require,module,exports){ -/* -WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based -on @visionmedia's Emitter from UI Kit. - -Why? I wanted it standalone. - -I also wanted support for wildcard emitters like this: - -emitter.on('*', function (eventName, other, event, payloads) { - -}); - -emitter.on('somenamespace*', function (eventName, payloads) { - -}); - -Please note that callbacks triggered by wildcard registered events also get -the event name as the first argument. -*/ - -module.exports = WildEmitter; - -function WildEmitter() { } - -WildEmitter.mixin = function (constructor) { - var prototype = constructor.prototype || constructor; - - prototype.isWildEmitter= true; - - // Listen on the given `event` with `fn`. Store a group name if present. - prototype.on = function (event, groupName, fn) { - this.callbacks = this.callbacks || {}; - var hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - func._groupName = group; - (this.callbacks[event] = this.callbacks[event] || []).push(func); - return this; - }; - - // Adds an `event` listener that will be invoked a single - // time then automatically removed. - prototype.once = function (event, groupName, fn) { - var self = this, - hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - function on() { - self.off(event, on); - func.apply(this, arguments); - } - this.on(event, group, on); - return this; - }; - - // Unbinds an entire group - prototype.releaseGroup = function (groupName) { - this.callbacks = this.callbacks || {}; - var item, i, len, handlers; - for (item in this.callbacks) { - handlers = this.callbacks[item]; - for (i = 0, len = handlers.length; i < len; i++) { - if (handlers[i]._groupName === groupName) { - //console.log('removing'); - // remove it and shorten the array we're looping through - handlers.splice(i, 1); - i--; - len--; - } - } - } - return this; - }; - - // Remove the given callback for `event` or all - // registered callbacks. - prototype.off = function (event, fn) { - this.callbacks = this.callbacks || {}; - var callbacks = this.callbacks[event], - i; - - if (!callbacks) return this; - - // remove all handlers - if (arguments.length === 1) { - delete this.callbacks[event]; - return this; - } - - // remove specific handler - i = callbacks.indexOf(fn); - callbacks.splice(i, 1); - if (callbacks.length === 0) { - delete this.callbacks[event]; - } - return this; - }; - - /// Emit `event` with the given args. - // also calls any `*` handlers - prototype.emit = function (event) { - this.callbacks = this.callbacks || {}; - var args = [].slice.call(arguments, 1), - callbacks = this.callbacks[event], - specialCallbacks = this.getWildcardCallbacks(event), - i, - len, - item, - listeners; - - if (callbacks) { - listeners = callbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, args); - } - } - - if (specialCallbacks) { - len = specialCallbacks.length; - listeners = specialCallbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, [event].concat(args)); - } - } - - return this; - }; - - // Helper for for finding special wildcard event handlers that match the event - prototype.getWildcardCallbacks = function (eventName) { - this.callbacks = this.callbacks || {}; - var item, - split, - result = []; - - for (item in this.callbacks) { - split = item.split('*'); - if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { - result = result.concat(this.callbacks[item]); - } - } - return result; - }; - -}; - -WildEmitter.mixin(WildEmitter); - -},{}],25:[function(require,module,exports){ -/*! - * EventEmitter v5.2.4 - git.io/ee - * Unlicense - http://unlicense.org/ - * Oliver Caldwell - http://oli.me.uk/ - * @preserve - */ - -;(function (exports) { - 'use strict'; - - /** - * Class for managing events. - * Can be extended to provide event functionality in other classes. - * - * @class EventEmitter Manages event registering and emitting. - */ - function EventEmitter() {} - - // Shortcuts to improve speed and size - var proto = EventEmitter.prototype; - var originalGlobalValue = exports.EventEmitter; - - /** - * Finds the index of the listener for the event in its storage array. - * - * @param {Function[]} listeners Array of listeners to search through. - * @param {Function} listener Method to look for. - * @return {Number} Index of the specified listener, -1 if not found - * @api private - */ - function indexOfListener(listeners, listener) { - var i = listeners.length; - while (i--) { - if (listeners[i].listener === listener) { - return i; - } - } - - return -1; - } - - /** - * Alias a method while keeping the context correct, to allow for overwriting of target method. - * - * @param {String} name The name of the target method. - * @return {Function} The aliased method - * @api private - */ - function alias(name) { - return function aliasClosure() { - return this[name].apply(this, arguments); - }; - } - - /** - * Returns the listener array for the specified event. - * Will initialise the event object and listener arrays if required. - * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. - * Each property in the object response is an array of listener functions. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Function[]|Object} All listener functions for the event. - */ - proto.getListeners = function getListeners(evt) { - var events = this._getEvents(); - var response; - var key; - - // Return a concatenated array of all matching events if - // the selector is a regular expression. - if (evt instanceof RegExp) { - response = {}; - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - response[key] = events[key]; - } - } - } - else { - response = events[evt] || (events[evt] = []); - } - - return response; - }; - - /** - * Takes a list of listener objects and flattens it into a list of listener functions. - * - * @param {Object[]} listeners Raw listener objects. - * @return {Function[]} Just the listener functions. - */ - proto.flattenListeners = function flattenListeners(listeners) { - var flatListeners = []; - var i; - - for (i = 0; i < listeners.length; i += 1) { - flatListeners.push(listeners[i].listener); - } - - return flatListeners; - }; - - /** - * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Object} All listener functions for an event in an object. - */ - proto.getListenersAsObject = function getListenersAsObject(evt) { - var listeners = this.getListeners(evt); - var response; - - if (listeners instanceof Array) { - response = {}; - response[evt] = listeners; - } - - return response || listeners; - }; - - function isValidListener (listener) { - if (typeof listener === 'function' || listener instanceof RegExp) { - return true - } else if (listener && typeof listener === 'object') { - return isValidListener(listener.listener) - } else { - return false - } - } - - /** - * Adds a listener function to the specified event. - * The listener will not be added if it is a duplicate. - * If the listener returns true then it will be removed after it is called. - * If you pass a regular expression as the event name then the listener will be added to all events that match it. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListener = function addListener(evt, listener) { - if (!isValidListener(listener)) { - throw new TypeError('listener must be a function'); - } - - var listeners = this.getListenersAsObject(evt); - var listenerIsWrapped = typeof listener === 'object'; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { - listeners[key].push(listenerIsWrapped ? listener : { - listener: listener, - once: false - }); - } - } - - return this; - }; - - /** - * Alias of addListener - */ - proto.on = alias('addListener'); - - /** - * Semi-alias of addListener. It will add a listener that will be - * automatically removed after its first execution. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addOnceListener = function addOnceListener(evt, listener) { - return this.addListener(evt, { - listener: listener, - once: true - }); - }; - - /** - * Alias of addOnceListener. - */ - proto.once = alias('addOnceListener'); - - /** - * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. - * You need to tell it what event names should be matched by a regex. - * - * @param {String} evt Name of the event to create. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvent = function defineEvent(evt) { - this.getListeners(evt); - return this; - }; - - /** - * Uses defineEvent to define multiple events. - * - * @param {String[]} evts An array of event names to define. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvents = function defineEvents(evts) { - for (var i = 0; i < evts.length; i += 1) { - this.defineEvent(evts[i]); - } - return this; - }; - - /** - * Removes a listener function from the specified event. - * When passed a regular expression as the event name, it will remove the listener from all events that match it. - * - * @param {String|RegExp} evt Name of the event to remove the listener from. - * @param {Function} listener Method to remove from the event. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListener = function removeListener(evt, listener) { - var listeners = this.getListenersAsObject(evt); - var index; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key)) { - index = indexOfListener(listeners[key], listener); - - if (index !== -1) { - listeners[key].splice(index, 1); - } - } - } - - return this; - }; - - /** - * Alias of removeListener - */ - proto.off = alias('removeListener'); - - /** - * Adds listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. - * You can also pass it a regular expression to add the array of listeners to all events that match it. - * Yeah, this function does quite a bit. That's probably a bad thing. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListeners = function addListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(false, evt, listeners); - }; - - /** - * Removes listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be removed. - * You can also pass it a regular expression to remove the listeners from all events that match it. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListeners = function removeListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(true, evt, listeners); - }; - - /** - * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. - * The first argument will determine if the listeners are removed (true) or added (false). - * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be added/removed. - * You can also pass it a regular expression to manipulate the listeners of all events that match it. - * - * @param {Boolean} remove True if you want to remove listeners, false if you want to add. - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add/remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { - var i; - var value; - var single = remove ? this.removeListener : this.addListener; - var multiple = remove ? this.removeListeners : this.addListeners; - - // If evt is an object then pass each of its properties to this method - if (typeof evt === 'object' && !(evt instanceof RegExp)) { - for (i in evt) { - if (evt.hasOwnProperty(i) && (value = evt[i])) { - // Pass the single listener straight through to the singular method - if (typeof value === 'function') { - single.call(this, i, value); - } - else { - // Otherwise pass back to the multiple function - multiple.call(this, i, value); - } - } - } - } - else { - // So evt must be a string - // And listeners must be an array of listeners - // Loop over it and pass each one to the multiple method - i = listeners.length; - while (i--) { - single.call(this, evt, listeners[i]); - } - } - - return this; - }; - - /** - * Removes all listeners from a specified event. - * If you do not specify an event then all listeners will be removed. - * That means every event will be emptied. - * You can also pass a regex to remove all events that match it. - * - * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeEvent = function removeEvent(evt) { - var type = typeof evt; - var events = this._getEvents(); - var key; - - // Remove different things depending on the state of evt - if (type === 'string') { - // Remove all listeners for the specified event - delete events[evt]; - } - else if (evt instanceof RegExp) { - // Remove all events matching the regex. - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - delete events[key]; - } - } - } - else { - // Remove all listeners in all events - delete this._events; - } - - return this; - }; - - /** - * Alias of removeEvent. - * - * Added to mirror the node API. - */ - proto.removeAllListeners = alias('removeEvent'); - - /** - * Emits an event of your choice. - * When emitted, every listener attached to that event will be executed. - * If you pass the optional argument array then those arguments will be passed to every listener upon execution. - * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. - * So they will not arrive within the array on the other side, they will be separate. - * You can also pass a regular expression to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {Array} [args] Optional array of arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emitEvent = function emitEvent(evt, args) { - var listenersMap = this.getListenersAsObject(evt); - var listeners; - var listener; - var i; - var key; - var response; - - for (key in listenersMap) { - if (listenersMap.hasOwnProperty(key)) { - listeners = listenersMap[key].slice(0); - - for (i = 0; i < listeners.length; i++) { - // If the listener returns true then it shall be removed from the event - // The function is executed either with a basic call or an apply if there is an args array - listener = listeners[i]; - - if (listener.once === true) { - this.removeListener(evt, listener.listener); - } - - response = listener.listener.apply(this, args || []); - - if (response === this._getOnceReturnValue()) { - this.removeListener(evt, listener.listener); - } - } - } - } - - return this; - }; - - /** - * Alias of emitEvent - */ - proto.trigger = alias('emitEvent'); - - /** - * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. - * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {...*} Optional additional arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emit = function emit(evt) { - var args = Array.prototype.slice.call(arguments, 1); - return this.emitEvent(evt, args); - }; - - /** - * Sets the current value to check against when executing listeners. If a - * listeners return value matches the one set here then it will be removed - * after execution. This value defaults to true. - * - * @param {*} value The new value to check for when executing listeners. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.setOnceReturnValue = function setOnceReturnValue(value) { - this._onceReturnValue = value; - return this; - }; - - /** - * Fetches the current value to check against when executing listeners. If - * the listeners return value matches this one then it should be removed - * automatically. It will return true by default. - * - * @return {*|Boolean} The current value to check for or the default, true. - * @api private - */ - proto._getOnceReturnValue = function _getOnceReturnValue() { - if (this.hasOwnProperty('_onceReturnValue')) { - return this._onceReturnValue; - } - else { - return true; - } - }; - - /** - * Fetches the events object and creates one if required. - * - * @return {Object} The events storage object. - * @api private - */ - proto._getEvents = function _getEvents() { - return this._events || (this._events = {}); - }; - - /** - * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. - * - * @return {Function} Non conflicting EventEmitter class. - */ - EventEmitter.noConflict = function noConflict() { - exports.EventEmitter = originalGlobalValue; - return EventEmitter; - }; - - // Expose the class either via AMD, CommonJS or the global object - if (typeof define === 'function' && define.amd) { - define(function () { - return EventEmitter; - }); - } - else if (typeof module === 'object' && module.exports){ - module.exports = EventEmitter; - } - else { - exports.EventEmitter = EventEmitter; - } -}(this || {})); - -},{}],26:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var OpenVidu_1 = require("./OpenVidu/OpenVidu"); -if (window) { - window['OpenVidu'] = OpenVidu_1.OpenVidu; -} - -},{"./OpenVidu/OpenVidu":29}],27:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Stream_1 = require("./Stream"); -var Connection = (function () { - function Connection(session, opts) { - this.session = session; - this.disposed = false; - var msg = "'Connection' created "; - if (!!opts) { - msg += "(remote) with 'connectionId' [" + opts.id + ']'; - } - else { - msg += '(local)'; - } - console.info(msg); - this.options = opts; - if (!!opts) { - this.connectionId = opts.id; - if (opts.metadata) { - this.data = opts.metadata; - } - if (opts.streams) { - this.initRemoteStreams(opts.streams); - } - } - this.creationTime = new Date().getTime(); - } - Connection.prototype.sendIceCandidate = function (candidate) { - console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate)); - this.session.openvidu.sendRequest('onIceCandidate', { - endpointName: this.connectionId, - candidate: candidate.candidate, - sdpMid: candidate.sdpMid, - sdpMLineIndex: candidate.sdpMLineIndex - }, function (error, response) { - if (error) { - console.error('Error sending ICE candidate: ' - + JSON.stringify(error)); - } - }); - }; - Connection.prototype.initRemoteStreams = function (options) { - var _this = this; - options.forEach(function (opts) { - var streamOptions = { - id: opts.id, - connection: _this, - frameRate: opts.frameRate, - recvAudio: opts.audioActive, - recvVideo: opts.videoActive, - typeOfVideo: opts.typeOfVideo - }; - var stream = new Stream_1.Stream(_this.session, streamOptions); - _this.addStream(stream); - }); - console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); - }; - Connection.prototype.addStream = function (stream) { - stream.connection = this; - this.stream = stream; - }; - Connection.prototype.removeStream = function (streamId) { - delete this.stream; - }; - Connection.prototype.dispose = function () { - if (!!this.stream) { - delete this.stream; - } - this.disposed = true; - }; - return Connection; -}()); -exports.Connection = Connection; - -},{"./Stream":32}],28:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState"); -var LocalRecorder = (function () { - function LocalRecorder(stream) { - this.stream = stream; - this.chunks = []; - this.count = 0; - this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; - this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; - this.state = LocalRecorderState_1.LocalRecorderState.READY; - } - LocalRecorder.prototype.record = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (typeof MediaRecorder === 'undefined') { - console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); - throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); - } - if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) { - throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); - } - console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'"); - if (typeof MediaRecorder.isTypeSupported === 'function') { - var options = void 0; - if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { - options = { mimeType: 'video/webm;codecs=vp9' }; - } - else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { - options = { mimeType: 'video/webm;codecs=h264' }; - } - else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { - options = { mimeType: 'video/webm;codecs=vp8' }; - } - console.log('Using mimeType ' + options.mimeType); - _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options); - } - else { - console.warn('isTypeSupported is not supported, using default codecs for browser'); - _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream()); - } - _this.mediaRecorder.start(10); - } - catch (err) { - reject(err); - } - _this.mediaRecorder.ondataavailable = function (e) { - _this.chunks.push(e.data); - }; - _this.mediaRecorder.onerror = function (e) { - console.error('MediaRecorder error: ', e); - }; - _this.mediaRecorder.onstart = function () { - console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - }; - _this.mediaRecorder.onpause = function () { - console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onresume = function () { - console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onwarning = function (e) { - console.log('MediaRecorder warning: ' + e); - }; - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - resolve(); - }); - }; - LocalRecorder.prototype.stop = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before')); - } - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - resolve(); - }; - _this.mediaRecorder.stop(); - } - catch (e) { - reject(e); - } - }); - }; - LocalRecorder.prototype.pause = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) { - reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before')); - } - _this.mediaRecorder.pause(); - _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED; - } - catch (error) { - reject(error); - } - }); - }; - LocalRecorder.prototype.resume = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) { - throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before')); - } - _this.mediaRecorder.resume(); - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - } - catch (error) { - reject(error); - } - }); - }; - LocalRecorder.prototype.preview = function (parentElement) { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - this.videoPreview = document.createElement('video'); - this.videoPreview.id = this.id; - this.videoPreview.autoplay = true; - if (typeof parentElement === 'string') { - this.htmlParentElementId = parentElement; - var parentElementDom = document.getElementById(parentElement); - if (parentElementDom) { - this.videoPreview = parentElementDom.appendChild(this.videoPreview); - } - } - else { - this.htmlParentElementId = parentElement.id; - this.videoPreview = parentElement.appendChild(this.videoPreview); - } - this.videoPreview.src = this.videoPreviewSrc; - return this.videoPreview; - }; - LocalRecorder.prototype.clean = function () { - var _this = this; - var f = function () { - delete _this.blob; - _this.chunks = []; - _this.count = 0; - delete _this.mediaRecorder; - _this.state = LocalRecorderState_1.LocalRecorderState.READY; - }; - if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) { - this.stop().then(function () { return f(); }).catch(function () { return f(); }); - } - else { - f(); - } - }; - LocalRecorder.prototype.download = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var a = document.createElement('a'); - a.style.display = 'none'; - document.body.appendChild(a); - var url = window.URL.createObjectURL(this.blob); - a.href = url; - a.download = this.id + '.webm'; - a.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(a); - } - }; - LocalRecorder.prototype.getBlob = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); - } - else { - return this.blob; - } - }; - LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_1 = new XMLHttpRequest(); - http_1.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_1.setRequestHeader(key, headers[key]); - } - } - http_1.onreadystatechange = function () { - if (http_1.readyState === 4) { - if (http_1.status.toString().charAt(0) === '2') { - resolve(http_1.responseText); - } - else { - reject(http_1.status); - } - } - }; - http_1.send(_this.blob); - } - }); - }; - LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_2 = new XMLHttpRequest(); - http_2.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_2.setRequestHeader(key, headers[key]); - } - } - var sendable = new FormData(); - sendable.append('file', _this.blob, _this.id + '.webm'); - http_2.onreadystatechange = function () { - if (http_2.readyState === 4) { - if (http_2.status.toString().charAt(0) === '2') { - resolve(http_2.responseText); - } - else { - reject(http_2.status); - } - } - }; - http_2.send(sendable); - } - }); - }; - LocalRecorder.prototype.onStopDefault = function () { - console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')'); - this.blob = new Blob(this.chunks, { type: 'video/webm' }); - this.chunks = []; - this.videoPreviewSrc = window.URL.createObjectURL(this.blob); - this.state = LocalRecorderState_1.LocalRecorderState.FINISHED; - }; - return LocalRecorder; -}()); -exports.LocalRecorder = LocalRecorder; - -},{"../OpenViduInternal/Enums/LocalRecorderState":35}],29:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorder_1 = require("./LocalRecorder"); -var Publisher_1 = require("./Publisher"); -var Session_1 = require("./Session"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); -var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); -var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); -var platform = require("platform"); -var OpenVidu = (function () { - function OpenVidu() { - this.secret = ''; - this.recorder = false; - this.advancedConfiguration = {}; - console.info("'OpenVidu' initialized"); - } - OpenVidu.prototype.initSession = function () { - this.session = new Session_1.Session(this); - return this.session; - }; - OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) { - var properties; - if (!!param2 && (typeof param2 !== 'function')) { - properties = param2; - properties = { - audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, - frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), - insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, - publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, - publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, - resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), - videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: true, - publishAudio: true, - publishVideo: true, - resolution: '640x480' - }; - } - var publisher = new Publisher_1.Publisher(targetElement, properties, this); - var completionHandler; - if (!!param2 && (typeof param2 === 'function')) { - completionHandler = param2; - } - else if (!!param3) { - completionHandler = param3; - } - publisher.initialize() - .then(function () { - if (completionHandler !== undefined) { - completionHandler(undefined); - } - publisher.emitEvent('accessAllowed', []); - }).catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - publisher.emitEvent('accessDenied', []); - }); - return publisher; - }; - OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - var publisher; - var callback = function (error) { - if (!!error) { - reject(error); - } - else { - resolve(publisher); - } - }; - if (!!properties) { - publisher = _this.initPublisher(targetElement, properties, callback); - } - else { - publisher = _this.initPublisher(targetElement, callback); - } - }); - }; - OpenVidu.prototype.initLocalRecorder = function (stream) { - return new LocalRecorder_1.LocalRecorder(stream); - }; - OpenVidu.prototype.checkSystemRequirements = function () { - var browser = platform.name; - var version = platform.version; - if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') && - (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') && - (browser !== 'Opera') && (browser !== 'Opera Mobile') && - (browser !== 'Safari')) { - return 0; - } - else { - return 1; - } - }; - OpenVidu.prototype.getDevices = function () { - return new Promise(function (resolve, reject) { - navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { - var devices = []; - deviceInfos.forEach(function (deviceInfo) { - if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { - devices.push({ - kind: deviceInfo.kind, - deviceId: deviceInfo.deviceId, - label: deviceInfo.label - }); - } - }); - resolve(devices); - }).catch(function (error) { - console.error('Error getting devices', error); - reject(error); - }); - }); - }; - OpenVidu.prototype.getUserMedia = function (options) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.generateMediaConstraints(options) - .then(function (constraints) { - navigator.mediaDevices.getUserMedia(constraints) - .then(function (mediaStream) { - resolve(mediaStream); - }) - .catch(function (error) { - var errorName; - var errorMessage = error.toString(); - if (!(options.videoSource === 'screen')) { - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; - } - reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - }) - .catch(function (error) { - reject(error); - }); - }); - }; - OpenVidu.prototype.enableProdMode = function () { - console.log = function () { }; - console.debug = function () { }; - console.info = function () { }; - console.warn = function () { }; - }; - OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { - this.advancedConfiguration = configuration; - }; - OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { - var _this = this; - return new Promise(function (resolve, reject) { - var audio, video; - if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) { - audio = false; - } - else if (publisherProperties.audioSource === undefined) { - audio = true; - } - else { - audio = publisherProperties.audioSource; - } - if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) { - video = false; - } - else { - video = { - height: { - ideal: 480 - }, - width: { - ideal: 640 - } - }; - } - var mediaConstraints = { - audio: audio, - video: video - }; - if (typeof mediaConstraints.audio === 'string') { - mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } }; - } - if (mediaConstraints.video) { - if (!!publisherProperties.resolution) { - var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); - var width = Number(widthAndHeight[0]); - var height = Number(widthAndHeight[1]); - mediaConstraints.video.width.ideal = width; - mediaConstraints.video.height.ideal = height; - } - if (!!publisherProperties.frameRate) { - mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate }; - } - if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') { - if (publisherProperties.videoSource === 'screen') { - if (platform.name !== 'Chrome' && platform.name !== 'Firefox') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); - console.error(error); - reject(error); - } - else { - if (!!_this.advancedConfiguration.screenShareChromeExtension) { - var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); - screenSharing.getChromeExtensionStatus(extensionId, function (status) { - if (status === 'installed-enabled') { - screenSharing.getScreenConstraints(function (error, screenConstraints) { - if (!!error && error === 'permission-denied') { - var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - console.error(error_1); - reject(error_1); - } - else { - mediaConstraints.video = screenConstraints; - resolve(mediaConstraints); - } - }); - } - if (status === 'installed-disabled') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - console.error(error); - reject(error); - } - if (status === 'not-installed') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); - console.error(error); - reject(error); - } - }); - } - else { - screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { - if (!!error) { - if (error === 'not-installed') { - var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); - console.error(error_2); - reject(error_2); - } - else if (error === 'installed-disabled') { - var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - console.error(error_3); - reject(error_3); - } - else if (error === 'permission-denied') { - var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - console.error(error_4); - reject(error_4); - } - } - else { - mediaConstraints.video = screenConstraints.video; - resolve(mediaConstraints); - } - }); - } - publisherProperties.videoSource = 'screen'; - } - } - else { - mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource }; - resolve(mediaConstraints); - } - } - else { - resolve(mediaConstraints); - } - } - else { - resolve(mediaConstraints); - } - }); - }; - OpenVidu.prototype.startWs = function (onConnectSucces) { - var config = { - heartbeat: 5000, - sendCloseMessage: false, - ws: { - uri: this.wsUri, - useSockJS: false, - onconnected: onConnectSucces, - ondisconnect: this.disconnectCallback.bind(this), - onreconnecting: this.reconnectingCallback.bind(this), - onreconnected: this.reconnectedCallback.bind(this) - }, - rpc: { - requestTimeout: 15000, - participantJoined: this.session.onParticipantJoined.bind(this.session), - participantPublished: this.session.onParticipantPublished.bind(this.session), - participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), - participantLeft: this.session.onParticipantLeft.bind(this.session), - participantEvicted: this.session.onParticipantEvicted.bind(this.session), - recordingStarted: this.session.onRecordingStarted.bind(this.session), - recordingStopped: this.session.onRecordingStopped.bind(this.session), - sendMessage: this.session.onNewMessage.bind(this.session), - iceCandidate: this.session.recvIceCandidate.bind(this.session), - mediaError: this.session.onMediaError.bind(this.session) - } - }; - this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); - }; - OpenVidu.prototype.closeWs = function () { - this.jsonRpcClient.close(); - }; - OpenVidu.prototype.sendRequest = function (method, params, callback) { - if (params && params instanceof Function) { - callback = params; - params = {}; - } - console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); - this.jsonRpcClient.send(method, params, callback); - }; - OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) { - var is = (!!mediaSource && - mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' && - mediaSource.id !== undefined && typeof mediaSource.id === 'string' && - mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' && - mediaSource.label !== undefined && typeof mediaSource.label === 'string' && - mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' && - mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string'); - return is; - }; - OpenVidu.prototype.getWsUri = function () { - return this.wsUri; - }; - OpenVidu.prototype.getSecret = function () { - return this.secret; - }; - OpenVidu.prototype.getRecorder = function () { - return this.recorder; - }; - OpenVidu.prototype.disconnectCallback = function () { - console.warn('Websocket connection lost'); - if (this.isRoomAvailable()) { - this.session.onLostConnection(); - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.reconnectingCallback = function () { - console.warn('Websocket connection lost (reconnecting)'); - if (this.isRoomAvailable()) { - this.session.onLostConnection(); - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.reconnectedCallback = function () { - console.warn('Websocket reconnected'); - }; - OpenVidu.prototype.isRoomAvailable = function () { - if (this.session !== undefined && this.session instanceof Session_1.Session) { - return true; - } - else { - console.warn('Session instance not found'); - return false; - } - }; - return OpenVidu; -}()); -exports.OpenVidu = OpenVidu; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":52,"../OpenViduInternal/ScreenSharing/Screen-Capturing":59,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":58,"./LocalRecorder":28,"./Publisher":30,"./Session":31,"platform":9}],30:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Session_1 = require("./Session"); -var Stream_1 = require("./Stream"); -var StreamManager_1 = require("./StreamManager"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var Publisher = (function (_super) { - __extends(Publisher, _super); - function Publisher(targEl, properties, openvidu) { - var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this; - _this.openvidu = openvidu; - _this.accessAllowed = false; - _this.isSubscribedToRemote = false; - _this.accessDenied = false; - _this.properties = properties; - _this.stream.ee.on('local-stream-destroyed-by-disconnect', function (reason) { - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - }); - return _this; - } - Publisher.prototype.publishAudio = function (value) { - this.stream.getWebRtcPeer().audioEnabled = value; - console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream'); - }; - Publisher.prototype.publishVideo = function (value) { - this.stream.getWebRtcPeer().videoEnabled = value; - console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream'); - }; - Publisher.prototype.subscribeToRemote = function (value) { - value = (value !== undefined) ? value : true; - this.isSubscribedToRemote = value; - this.stream.subscribeToMyRemote(value); - }; - Publisher.prototype.on = function (type, handler) { - var _this = this; - _super.prototype.on.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.on('stream-created-by-publisher', function () { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'remoteVideoPlaying') { - if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.ee.emitEvent('accessAllowed'); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.ee.emitEvent('accessDenied'); - } - } - return this; - }; - Publisher.prototype.once = function (type, handler) { - var _this = this; - _super.prototype.once.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.once('stream-created-by-publisher', function () { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'remoteVideoPlaying') { - if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.ee.emitEvent('accessAllowed'); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.ee.emitEvent('accessDenied'); - } - } - return this; - }; - Publisher.prototype.initialize = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var errorCallback = function (openViduError) { - _this.accessDenied = true; - _this.accessAllowed = false; - reject(openViduError); - }; - var successCallback = function (mediaStream) { - _this.accessAllowed = true; - _this.accessDenied = false; - if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) { - mediaStream.removeTrack(mediaStream.getAudioTracks()[0]); - mediaStream.addTrack(_this.properties.audioSource); - } - if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) { - mediaStream.removeTrack(mediaStream.getVideoTracks()[0]); - mediaStream.addTrack(_this.properties.videoSource); - } - if (!!mediaStream.getAudioTracks()[0]) { - mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; - } - if (!!mediaStream.getVideoTracks()[0]) { - mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; - } - _this.stream.setMediaStream(mediaStream); - if (!_this.stream.displayMyRemote()) { - _this.stream.updateMediaStreamInVideos(); - } - _this.stream.isLocalStreamReadyToPublish = true; - _this.stream.ee.emitEvent('stream-ready-to-publish', []); - if (!!_this.firstVideoElement) { - _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode); - } - delete _this.firstVideoElement; - resolve(); - }; - _this.openvidu.generateMediaConstraints(_this.properties) - .then(function (constraints) { - var outboundStreamOptions = { - mediaConstraints: constraints, - publisherProperties: _this.properties - }; - _this.stream.setOutboundStreamOptions(outboundStreamOptions); - var constraintsAux = {}; - var timeForDialogEvent = 1250; - if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) { - var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio); - constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1; - constraintsAux.video = constraints.video; - var startTime_1 = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (mediaStream) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) { - constraintsAux.audio = definedAudioConstraint_1; - constraintsAux.video = false; - startTime_1 = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (audioOnlyStream) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); - successCallback(mediaStream); - }) - .catch(function (error) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'notallowederror': - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'overconstrainederror': - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - } - }); - } - else { - successCallback(mediaStream); - } - }) - .catch(function (error) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - case 'notallowederror': - errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'overconstrainederror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - } - }); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'")); - } - }) - .catch(function (error) { - errorCallback(error); - }); - }); - }; - Publisher.prototype.updateSession = function (session) { - this.session = session; - this.stream.session = session; - }; - Publisher.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - Publisher.prototype.reestablishStreamPlayingEvent = function () { - if (this.ee.getListeners('streamPlaying').length > 0) { - this.addPlayEventToFirstVideo(); - } - }; - Publisher.prototype.setPermissionDialogTimer = function (waitTime) { - var _this = this; - this.permissionDialogTimeout = setTimeout(function () { - _this.ee.emitEvent('accessDialogOpened', []); - }, waitTime); - }; - Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) { - clearTimeout(this.permissionDialogTimeout); - if ((Date.now() - startTime) > waitTime) { - this.ee.emitEvent('accessDialogClosed', []); - } - }; - return Publisher; -}(StreamManager_1.StreamManager)); -exports.Publisher = Publisher; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Events/StreamEvent":44,"../OpenViduInternal/Events/VideoElementEvent":46,"./Session":31,"./Stream":32,"./StreamManager":33}],31:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Connection_1 = require("./Connection"); -var Subscriber_1 = require("./Subscriber"); -var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent"); -var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent"); -var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); -var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var platform = require("platform"); -var EventEmitter = require("wolfy87-eventemitter"); -var Session = (function () { - function Session(openvidu) { - this.streamManagers = []; - this.remoteStreamsCreated = {}; - this.remoteConnections = {}; - this.speakingEventsEnabled = false; - this.ee = new EventEmitter(); - this.openvidu = openvidu; - } - Session.prototype.connect = function (token, metadata) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.processToken(token); - if (_this.openvidu.checkSystemRequirements()) { - _this.options = { - sessionId: _this.sessionId, - participantId: token, - metadata: !!metadata ? _this.stringClientMetadata(metadata) : '' - }; - _this.connectAux(token).then(function () { - resolve(); - }).catch(function (error) { - reject(error); - }); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu')); - } - }); - }; - Session.prototype.disconnect = function () { - this.leave(false, 'disconnect'); - }; - Session.prototype.subscribe = function (stream, targetElement, param3, param4) { - var properties = {}; - if (!!param3 && typeof param3 !== 'function') { - properties = { - insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, - subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: true, - subscribeToVideo: true - }; - } - var completionHandler; - if (!!param3 && (typeof param3 === 'function')) { - completionHandler = param3; - } - else if (!!param4) { - completionHandler = param4; - } - console.info('Subscribing to ' + stream.connection.connectionId); - stream.subscribe() - .then(function () { - console.info('Subscribed correctly to ' + stream.connection.connectionId); - if (completionHandler !== undefined) { - completionHandler(undefined); - } - }) - .catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - }); - var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties); - if (!!subscriber.targetElement) { - stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode); - } - return subscriber; - }; - Session.prototype.subscribeAsync = function (stream, targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - var subscriber; - var callback = function (error) { - if (!!error) { - reject(error); - } - else { - resolve(subscriber); - } - }; - if (!!properties) { - subscriber = _this.subscribe(stream, targetElement, properties, callback); - } - else { - subscriber = _this.subscribe(stream, targetElement, callback); - } - }); - }; - Session.prototype.unsubscribe = function (subscriber) { - var connectionId = subscriber.stream.connection.connectionId; - console.info('Unsubscribing from ' + connectionId); - this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { - if (error) { - console.error('Error unsubscribing from ' + connectionId, error); - } - else { - console.info('Unsubscribed correctly from ' + connectionId); - } - subscriber.stream.disposeWebRtcPeer(); - subscriber.stream.disposeMediaStream(); - }); - subscriber.stream.streamManager.removeAllVideos(); - }; - Session.prototype.publish = function (publisher) { - var _this = this; - return new Promise(function (resolve, reject) { - publisher.session = _this; - publisher.stream.session = _this; - if (!publisher.stream.isLocalStreamPublished) { - _this.connection.addStream(publisher.stream); - publisher.stream.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - } - else { - publisher.initialize() - .then(function () { - _this.connection.addStream(publisher.stream); - publisher.reestablishStreamPlayingEvent(); - publisher.stream.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }).catch(function (error) { - reject(error); - }); - } - }); - }; - Session.prototype.unpublish = function (publisher) { - var stream = publisher.stream; - if (!stream.connection) { - console.error('The associated Connection object of this Publisher is null', stream); - return; - } - else if (stream.connection !== this.connection) { - console.error('The associated Connection object of this Publisher is not your local Connection.' + - "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); - return; - } - else { - console.info('Unpublishing local media (' + stream.connection.connectionId + ')'); - this.openvidu.sendRequest('unpublishVideo', function (error, response) { - if (error) { - console.error(error); - } - else { - console.info('Media unpublished correctly'); - } - }); - stream.disposeWebRtcPeer(); - delete stream.connection.stream; - var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish'); - publisher.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - } - }; - Session.prototype.signal = function (signal) { - var _this = this; - return new Promise(function (resolve, reject) { - var signalMessage = {}; - if (signal.to && signal.to.length > 0) { - var connectionIds_1 = []; - signal.to.forEach(function (connection) { - connectionIds_1.push(connection.connectionId); - }); - signalMessage['to'] = connectionIds_1; - } - else { - signalMessage['to'] = []; - } - signalMessage['data'] = signal.data ? signal.data : ''; - signalMessage['type'] = signal.type ? signal.type : ''; - _this.openvidu.sendRequest('sendMessage', { - message: JSON.stringify(signalMessage) - }, function (error, response) { - if (!!error) { - reject(error); - } - else { - resolve(); - } - }); - }); - }; - Session.prototype.on = function (type, handler) { - this.ee.on(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered by 'Session'", event); - } - else { - console.info("Event '" + type + "' triggered by 'Session'"); - } - handler(event); - }); - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = true; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !str.speechEvent && str.hasAudio) { - str.enableSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.once = function (type, handler) { - this.ee.once(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered by 'Session'", event); - } - else { - console.info("Event '" + type + "' triggered by 'Session'"); - } - handler(event); - }); - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = true; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !str.speechEvent && str.hasAudio) { - str.enableOnceSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.off = function (type, handler) { - if (!handler) { - this.ee.removeAllListeners(type); - } - else { - this.ee.off(type, handler); - } - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = false; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !!str.speechEvent) { - str.disableSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.onParticipantJoined = function (response) { - var _this = this; - this.getConnection(response.id, '') - .then(function (connection) { - console.warn('Connection ' + response.id + ' already exists in connections list'); - }) - .catch(function (openViduError) { - var connection = new Connection_1.Connection(_this, response); - _this.remoteConnections[response.id] = connection; - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - }; - Session.prototype.onParticipantLeft = function (msg) { - var _this = this; - this.getRemoteConnection(msg.name, 'Remote connection ' + msg.name + " unknown when 'onParticipantLeft'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (connection) { - if (!!connection.stream) { - var stream = connection.stream; - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - delete _this.remoteStreamsCreated[stream.streamId]; - } - delete _this.remoteConnections[connection.connectionId]; - _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onParticipantPublished = function (response) { - var _this = this; - var afterConnectionFound = function (connection) { - _this.remoteConnections[connection.connectionId] = connection; - if (!_this.remoteStreamsCreated[connection.stream.streamId]) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]); - } - _this.remoteStreamsCreated[connection.stream.streamId] = true; - }; - var connection; - this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (con) { - connection = con; - response.metadata = con.data; - connection.options = response; - connection.initRemoteStreams(response.streams); - afterConnectionFound(connection); - }) - .catch(function (openViduError) { - connection = new Connection_1.Connection(_this, response); - afterConnectionFound(connection); - }); - }; - Session.prototype.onParticipantUnpublished = function (msg) { - var _this = this; - this.getRemoteConnection(msg.name, "Remote connection '" + msg.name + "' unknown when 'onParticipantUnpublished'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (connection) { - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - var streamId = connection.stream.streamId; - delete _this.remoteStreamsCreated[streamId]; - connection.removeStream(streamId); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onParticipantEvicted = function (msg) { - }; - Session.prototype.onNewMessage = function (msg) { - var _this = this; - console.info('New signal: ' + JSON.stringify(msg)); - this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: " - + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId) - .then(function (connection) { - _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); - _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.recvIceCandidate = function (msg) { - var candidate = { - candidate: msg.candidate, - sdpMid: msg.sdpMid, - sdpMLineIndex: msg.sdpMLineIndex - }; - this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) - .then(function (connection) { - var stream = connection.stream; - stream.getWebRtcPeer().addIceCandidate(candidate, function (error) { - if (error) { - console.error('Error adding candidate for ' + stream.streamId - + ' stream of endpoint ' + msg.endpointName + ': ' + error); - } - }); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onSessionClosed = function (msg) { - console.info('Session closed: ' + JSON.stringify(msg)); - var s = msg.room; - if (s !== undefined) { - this.ee.emitEvent('session-closed', [{ - session: s - }]); - } - else { - console.warn('Session undefined on session closed', msg); - } - }; - Session.prototype.onLostConnection = function () { - if (!this.connection) { - console.warn('Not connected to session: if you are not debugging, this is probably a certificate error'); - var url = 'https://' + this.openvidu.getWsUri().split('wss://')[1].split('/openvidu')[0]; - if (window.confirm('If you are not debugging, this is probably a certificate error at \"' + url + '\"\n\nClick OK to navigate and accept it')) { - location.assign(url + '/accept-certificate'); - } - return; - } - console.warn('Lost connection in Session ' + this.sessionId); - if (!!this.sessionId && !this.connection.disposed) { - this.leave(true, 'networkDisconnect'); - } - }; - Session.prototype.onMediaError = function (params) { - console.error('Media error: ' + JSON.stringify(params)); - var err = params.error; - if (err) { - this.ee.emitEvent('error-media', [{ - error: err - }]); - } - else { - console.warn('Received undefined media error. Params:', params); - } - }; - Session.prototype.onRecordingStarted = function (response) { - this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]); - }; - Session.prototype.onRecordingStopped = function (response) { - this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]); - }; - Session.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - Session.prototype.leave = function (forced, reason) { - var _this = this; - forced = !!forced; - console.info('Leaving Session (forced=' + forced + ')'); - if (!!this.connection) { - if (!this.connection.disposed && !forced) { - this.openvidu.sendRequest('leaveRoom', function (error, response) { - if (error) { - console.error(error); - } - _this.openvidu.closeWs(); - }); - } - else { - this.openvidu.closeWs(); - } - if (!!this.connection.stream) { - this.connection.stream.disposeWebRtcPeer(); - if (this.connection.stream.isLocalStreamPublished) { - this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); - } - } - if (!this.connection.disposed) { - var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason); - this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); - sessionDisconnectEvent.callDefaultBehaviour(); - } - } - else { - console.warn('You were not connected to the session ' + this.sessionId); - } - }; - Session.prototype.connectAux = function (token) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.openvidu.startWs(function (error) { - if (!!error) { - reject(error); - } - else { - var joinParams = { - token: (!!token) ? token : '', - session: _this.sessionId, - metadata: !!_this.options.metadata ? _this.options.metadata : '', - secret: _this.openvidu.getSecret(), - recorder: _this.openvidu.getRecorder(), - }; - _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { - if (!!error) { - reject(error); - } - else { - _this.connection = new Connection_1.Connection(_this); - _this.connection.connectionId = response.id; - _this.connection.data = response.metadata; - var events_1 = { - connections: new Array(), - streams: new Array() - }; - var existingParticipants = response.value; - existingParticipants.forEach(function (participant) { - var connection = new Connection_1.Connection(_this, participant); - _this.remoteConnections[connection.connectionId] = connection; - events_1.connections.push(connection); - if (!!connection.stream) { - _this.remoteStreamsCreated[connection.stream.streamId] = true; - events_1.streams.push(connection.stream); - } - }); - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]); - events_1.connections.forEach(function (connection) { - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - events_1.streams.forEach(function (stream) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]); - }); - resolve(); - } - }); - } - }); - }); - }; - Session.prototype.stringClientMetadata = function (metadata) { - if (typeof metadata !== 'string') { - return JSON.stringify(metadata); - } - else { - return metadata; - } - }; - Session.prototype.getConnection = function (connectionId, errorMessage) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections[connectionId]; - if (!!connection) { - resolve(connection); - } - else { - if (_this.connection.connectionId === connectionId) { - resolve(_this.connection); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - } - }); - }; - Session.prototype.getRemoteConnection = function (connectionId, errorMessage) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections[connectionId]; - if (!!connection) { - resolve(connection); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - }); - }; - Session.prototype.processToken = function (token) { - var url = new URL(token); - this.sessionId = url.searchParams.get('sessionId'); - var secret = url.searchParams.get('secret'); - var recorder = url.searchParams.get('recorder'); - if (!!secret) { - this.openvidu.secret = secret; - } - if (!!recorder) { - this.openvidu.recorder = true; - } - this.openvidu.wsUri = 'wss://' + url.host + '/openvidu'; - }; - return Session; -}()); -exports.Session = Session; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/Events/ConnectionEvent":38,"../OpenViduInternal/Events/RecordingEvent":41,"../OpenViduInternal/Events/SessionDisconnectedEvent":42,"../OpenViduInternal/Events/SignalEvent":43,"../OpenViduInternal/Events/StreamEvent":44,"./Connection":27,"./Subscriber":34,"platform":9,"wolfy87-eventemitter":25}],32:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats"); -var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent"); -var EventEmitter = require("wolfy87-eventemitter"); -var kurentoUtils = require("../OpenViduInternal/KurentoUtils/kurento-utils-js"); -var Stream = (function () { - function Stream(session, options) { - var _this = this; - this.ee = new EventEmitter(); - this.isSubscribeToRemote = false; - this.isLocalStreamReadyToPublish = false; - this.isLocalStreamPublished = false; - this.session = session; - if (options.hasOwnProperty('id')) { - this.inboundStreamOpts = options; - this.streamId = this.inboundStreamOpts.id; - this.hasAudio = this.inboundStreamOpts.recvAudio; - this.hasVideo = this.inboundStreamOpts.recvVideo; - this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo; - this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; - } - else { - this.outboundStreamOpts = options; - if (this.isSendVideo()) { - if (this.isSendScreen()) { - this.streamId = 'SCREEN'; - this.typeOfVideo = 'SCREEN'; - } - else { - this.streamId = 'CAMERA'; - this.typeOfVideo = 'CAMERA'; - } - this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; - } - else { - this.streamId = 'MICRO'; - delete this.typeOfVideo; - } - this.hasAudio = this.isSendAudio(); - this.hasVideo = this.isSendVideo(); - } - this.ee.on('mediastream-updated', function () { - _this.streamManager.updateMediaStream(_this.mediaStream); - console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']'); - }); - } - Stream.prototype.getMediaStream = function () { - return this.mediaStream; - }; - Stream.prototype.setMediaStream = function (mediaStream) { - this.mediaStream = mediaStream; - }; - Stream.prototype.updateMediaStreamInVideos = function () { - this.ee.emitEvent('mediastream-updated'); - }; - Stream.prototype.getWebRtcPeer = function () { - return this.webRtcPeer; - }; - Stream.prototype.getRTCPeerConnection = function () { - return this.webRtcPeer.peerConnection; - }; - Stream.prototype.subscribeToMyRemote = function (value) { - this.isSubscribeToRemote = value; - }; - Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { - this.outboundStreamOpts = outboundStreamOpts; - }; - Stream.prototype.subscribe = function () { - var _this = this; - return new Promise(function (resolve, reject) { - _this.initWebRtcPeerReceive() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }); - }; - Stream.prototype.publish = function () { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.isLocalStreamReadyToPublish) { - _this.initWebRtcPeerSend() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - } - else { - _this.ee.once('stream-ready-to-publish', function () { - _this.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }); - } - }); - }; - Stream.prototype.disposeWebRtcPeer = function () { - if (this.webRtcPeer) { - this.webRtcPeer.dispose(); - } - if (this.speechEvent) { - this.speechEvent.stop(); - } - this.stopWebRtcStats(); - console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed'); - }; - Stream.prototype.disposeMediaStream = function () { - if (this.mediaStream) { - this.mediaStream.getAudioTracks().forEach(function (track) { - track.stop(); - }); - this.mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - delete this.mediaStream; - } - console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed'); - }; - Stream.prototype.displayMyRemote = function () { - return this.isSubscribeToRemote; - }; - Stream.prototype.isSendAudio = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.audioSource !== null && - this.outboundStreamOpts.publisherProperties.audioSource !== false); - }; - Stream.prototype.isSendVideo = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.videoSource !== null && - this.outboundStreamOpts.publisherProperties.videoSource !== false); - }; - Stream.prototype.isSendScreen = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.videoSource === 'screen'); - }; - Stream.prototype.setSpeechEventIfNotExists = function () { - if (!this.speechEvent) { - var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}; - harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50; - harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50; - this.speechEvent = kurentoUtils.WebRtcPeer.hark(this.mediaStream, harkOptions); - } - }; - Stream.prototype.enableSpeakingEvents = function () { - var _this = this; - this.setSpeechEventIfNotExists(); - this.speechEvent.on('speaking', function () { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - }); - this.speechEvent.on('stopped_speaking', function () { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - }); - }; - Stream.prototype.enableOnceSpeakingEvents = function () { - var _this = this; - this.setSpeechEventIfNotExists(); - this.speechEvent.on('speaking', function () { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - _this.disableSpeakingEvents(); - }); - this.speechEvent.on('stopped_speaking', function () { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - _this.disableSpeakingEvents(); - }); - }; - Stream.prototype.disableSpeakingEvents = function () { - this.speechEvent.stop(); - this.speechEvent = undefined; - }; - Stream.prototype.initWebRtcPeerSend = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var userMediaConstraints = { - audio: _this.isSendAudio(), - video: _this.isSendVideo() - }; - var options = { - videoStream: _this.mediaStream, - mediaConstraints: userMediaConstraints, - onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), - iceServers: _this.session.openvidu.advancedConfiguration.iceServers - }; - var successCallback = function (error, sdpOfferParam, wp) { - if (error) { - reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error))); - } - console.debug('Sending SDP offer to publish as ' - + _this.streamId, sdpOfferParam); - _this.session.openvidu.sendRequest('publishVideo', { - sdpOffer: sdpOfferParam, - doLoopback: _this.displayMyRemote() || false, - audioActive: _this.isSendAudio(), - videoActive: _this.isSendVideo(), - typeOfVideo: ((_this.isSendVideo()) ? (_this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''), - frameRate: !!_this.frameRate ? _this.frameRate : -1 - }, function (error, response) { - if (error) { - reject('Error on publishVideo: ' + JSON.stringify(error)); - } - else { - _this.processSdpAnswer(response.sdpAnswer) - .then(function () { - _this.isLocalStreamPublished = true; - if (_this.displayMyRemote()) { - _this.updateMediaStreamInVideos(); - } - _this.ee.emitEvent('stream-created-by-publisher'); - resolve(); - }) - .catch(function (error) { - reject(error); - }); - console.info("'Publisher' successfully published to session"); - } - }); - }; - if (_this.displayMyRemote()) { - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function (err) { - if (err) { - reject(err); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - } - else { - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options, function (error) { - if (error) { - reject(error); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - } - }); - }; - Stream.prototype.initWebRtcPeerReceive = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var offerConstraints = { - audio: _this.inboundStreamOpts.recvAudio, - video: _this.inboundStreamOpts.recvVideo - }; - console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); - var options = { - onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), - mediaConstraints: offerConstraints - }; - var successCallback = function (error, sdpOfferParam, wp) { - if (error) { - reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error))); - } - console.debug('Sending SDP offer to subscribe to ' - + _this.streamId, sdpOfferParam); - _this.session.openvidu.sendRequest('receiveVideoFrom', { - sender: _this.streamId, - sdpOffer: sdpOfferParam - }, function (error, response) { - if (error) { - reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error))); - } - else { - _this.processSdpAnswer(response.sdpAnswer).then(function () { - resolve(); - }).catch(function (error) { - reject(error); - }); - } - }); - }; - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function (error) { - if (error) { - reject(error); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - }); - }; - Stream.prototype.processSdpAnswer = function (sdpAnswer) { - var _this = this; - return new Promise(function (resolve, reject) { - var answer = new RTCSessionDescription({ - type: 'answer', - sdp: sdpAnswer, - }); - console.debug(_this.streamId + ': set peer connection with recvd SDP answer', sdpAnswer); - var streamId = _this.streamId; - var peerConnection = _this.webRtcPeer.peerConnection; - peerConnection.setRemoteDescription(answer, function () { - if (!_this.isLocal() || _this.displayMyRemote()) { - _this.mediaStream = peerConnection.getRemoteStreams()[0]; - console.debug('Peer remote stream', _this.mediaStream); - if (!!_this.mediaStream) { - _this.ee.emitEvent('mediastream-updated'); - if (!!_this.mediaStream.getAudioTracks()[0] && _this.session.speakingEventsEnabled) { - _this.enableSpeakingEvents(); - } - } - } - _this.initWebRtcStats(); - resolve(); - }, function (error) { - reject(new Error(_this.streamId + ': Error setting SDP to the peer connection: ' + JSON.stringify(error))); - }); - }); - }; - Stream.prototype.initWebRtcStats = function () { - this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); - this.webRtcStats.initWebRtcStats(); - }; - Stream.prototype.stopWebRtcStats = function () { - if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { - this.webRtcStats.stopWebRtcStats(); - } - }; - Stream.prototype.isLocal = function () { - return (!this.inboundStreamOpts && !!this.outboundStreamOpts); - }; - return Stream; -}()); -exports.Stream = Stream; - -},{"../OpenViduInternal/Events/PublisherSpeakingEvent":40,"../OpenViduInternal/KurentoUtils/kurento-utils-js":57,"../OpenViduInternal/WebRtcStats/WebRtcStats":60,"wolfy87-eventemitter":25}],33:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); -var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var EventEmitter = require("wolfy87-eventemitter"); -var StreamManager = (function () { - function StreamManager(stream, targetElement) { - var _this = this; - this.videos = []; - this.lazyLaunchVideoElementCreatedEvent = false; - this.ee = new EventEmitter(); - this.stream = stream; - this.stream.streamManager = this; - this.remote = !this.stream.isLocal(); - if (!!targetElement) { - var targEl = void 0; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targetElement); - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - if (!!targEl) { - this.firstVideoElement = { - targetElement: targEl, - video: document.createElement('video'), - id: '' - }; - this.targetElement = targEl; - this.element = targEl; - } - } - this.canPlayListener = function () { - if (_this.stream.isLocal()) { - if (!_this.stream.displayMyRemote()) { - console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); - } - else { - console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]); - } - } - else { - console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); - } - _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]); - }; - } - StreamManager.prototype.on = function (type, handler) { - this.ee.on(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered", event); - } - else { - console.info("Event '" + type + "' triggered"); - } - handler(event); - }); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = false; - } - } - if (type === 'streamPlaying' || type === 'videoPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); - this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); - } - } - return this; - }; - StreamManager.prototype.once = function (type, handler) { - this.ee.once(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered once", event); - } - else { - console.info("Event '" + type + "' triggered once"); - } - handler(event); - }); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - } - } - if (type === 'streamPlaying' || type === 'videoPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); - this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); - } - } - return this; - }; - StreamManager.prototype.off = function (type, handler) { - if (!handler) { - this.ee.removeAllListeners(type); - } - else { - this.ee.off(type, handler); - } - return this; - }; - StreamManager.prototype.addVideoElement = function (video) { - this.initializeVideoProperties(video); - for (var _i = 0, _a = this.videos; _i < _a.length; _i++) { - var v = _a[_i]; - if (v.video === video) { - return 0; - } - } - var returnNumber = 1; - this.initializeVideoProperties(video); - for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) { - var streamManager = _c[_b]; - if (streamManager.disassociateVideo(video)) { - returnNumber = -1; - break; - } - } - this.stream.session.streamManagers.forEach(function (streamManager) { - streamManager.disassociateVideo(video); - }); - this.pushNewStreamManagerVideo({ - video: video, - id: video.id - }); - console.info('New video element associated to ', this); - return returnNumber; - }; - StreamManager.prototype.createVideoElement = function (targetElement, insertMode) { - var targEl; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targEl); - if (!targEl) { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - else { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - var video = document.createElement('video'); - this.initializeVideoProperties(video); - var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; - switch (insMode) { - case VideoInsertMode_1.VideoInsertMode.AFTER: - targEl.parentNode.insertBefore(video, targEl.nextSibling); - break; - case VideoInsertMode_1.VideoInsertMode.APPEND: - targEl.appendChild(video); - break; - case VideoInsertMode_1.VideoInsertMode.BEFORE: - targEl.parentNode.insertBefore(video, targEl); - break; - case VideoInsertMode_1.VideoInsertMode.PREPEND: - targEl.insertBefore(video, targEl.childNodes[0]); - break; - case VideoInsertMode_1.VideoInsertMode.REPLACE: - targEl.parentNode.replaceChild(video, targEl); - break; - default: - insMode = VideoInsertMode_1.VideoInsertMode.APPEND; - targEl.appendChild(video); - break; - } - var v = { - targetElement: targEl, - video: video, - insertMode: insMode, - id: video.id - }; - this.pushNewStreamManagerVideo(v); - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement; - return video; - }; - StreamManager.prototype.initializeVideoProperties = function (video) { - video.srcObject = this.stream.getMediaStream(); - video.autoplay = true; - video.controls = false; - if (!video.id) { - video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId; - if (!this.id && !!this.targetElement) { - this.id = video.id; - } - } - if (!this.remote && !this.stream.displayMyRemote()) { - video.muted = true; - if (this.stream.outboundStreamOpts.publisherProperties.mirror) { - this.mirrorVideo(video); - } - } - }; - StreamManager.prototype.removeAllVideos = function () { - var _this = this; - for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) { - if (this.stream.session.streamManagers[i] === this) { - this.stream.session.streamManagers.splice(i, 1); - } - } - this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) { - streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener); - if (!!streamManagerVideo.targetElement) { - streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video); - _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]); - _this.videos.splice(videos.length - 1 - index, 1); - } - else { - streamManagerVideo.video.srcObject = null; - } - }); - }; - StreamManager.prototype.disassociateVideo = function (video) { - var disassociated = false; - for (var i = 0; i < this.videos.length; i++) { - if (this.videos[i].video === video) { - this.videos.splice(i, 1); - disassociated = true; - console.info('Video element disassociated from ', this); - break; - } - } - return disassociated; - }; - StreamManager.prototype.addPlayEventToFirstVideo = function () { - if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) { - this.videos[0].video.addEventListener('canplay', this.canPlayListener); - } - }; - StreamManager.prototype.updateMediaStream = function (mediaStream) { - this.videos.forEach(function (streamManagerVideo) { - streamManagerVideo.video.srcObject = mediaStream; - }); - }; - StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) { - this.videos.push(streamManagerVideo); - this.addPlayEventToFirstVideo(); - if (this.stream.session.streamManagers.indexOf(this) === -1) { - this.stream.session.streamManagers.push(this); - } - }; - StreamManager.prototype.mirrorVideo = function (video) { - video.style.transform = 'rotateY(180deg)'; - video.style.webkitTransform = 'rotateY(180deg)'; - }; - return StreamManager; -}()); -exports.StreamManager = StreamManager; - -},{"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/Events/StreamManagerEvent":45,"../OpenViduInternal/Events/VideoElementEvent":46,"wolfy87-eventemitter":25}],34:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var StreamManager_1 = require("./StreamManager"); -var Subscriber = (function (_super) { - __extends(Subscriber, _super); - function Subscriber(stream, targEl, properties) { - var _this = _super.call(this, stream, targEl) || this; - _this.element = _this.targetElement; - _this.stream = stream; - _this.properties = properties; - return _this; - } - Subscriber.prototype.subscribeToAudio = function (value) { - this.stream.getMediaStream().getAudioTracks().forEach(function (track) { - track.enabled = value; - }); - console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream'); - return this; - }; - Subscriber.prototype.subscribeToVideo = function (value) { - this.stream.getMediaStream().getVideoTracks().forEach(function (track) { - track.enabled = value; - }); - console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream'); - return this; - }; - return Subscriber; -}(StreamManager_1.StreamManager)); -exports.Subscriber = Subscriber; - -},{"./StreamManager":33}],35:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorderState; -(function (LocalRecorderState) { - LocalRecorderState["READY"] = "READY"; - LocalRecorderState["RECORDING"] = "RECORDING"; - LocalRecorderState["PAUSED"] = "PAUSED"; - LocalRecorderState["FINISHED"] = "FINISHED"; -})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {})); - -},{}],36:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var OpenViduErrorName; -(function (OpenViduErrorName) { - OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; - OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED"; - OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; - OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; - OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; - OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED"; - OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; - OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; - OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; - OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; - OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; - OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED"; - OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; -})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); -var OpenViduError = (function () { - function OpenViduError(name, message) { - this.name = name; - this.message = message; - } - return OpenViduError; -}()); -exports.OpenViduError = OpenViduError; - -},{}],37:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var VideoInsertMode; -(function (VideoInsertMode) { - VideoInsertMode["AFTER"] = "AFTER"; - VideoInsertMode["APPEND"] = "APPEND"; - VideoInsertMode["BEFORE"] = "BEFORE"; - VideoInsertMode["PREPEND"] = "PREPEND"; - VideoInsertMode["REPLACE"] = "REPLACE"; -})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); - -},{}],38:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var ConnectionEvent = (function (_super) { - __extends(ConnectionEvent, _super); - function ConnectionEvent(cancelable, target, type, connection, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.connection = connection; - _this.reason = reason; - return _this; - } - ConnectionEvent.prototype.callDefaultBehaviour = function () { }; - return ConnectionEvent; -}(Event_1.Event)); -exports.ConnectionEvent = ConnectionEvent; - -},{"./Event":39}],39:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Event = (function () { - function Event(cancelable, target, type) { - this.hasBeenPrevented = false; - this.cancelable = cancelable; - this.target = target; - this.type = type; - } - Event.prototype.isDefaultPrevented = function () { - return this.hasBeenPrevented; - }; - Event.prototype.preventDefault = function () { - this.callDefaultBehaviour = function () { }; - this.hasBeenPrevented = true; - }; - return Event; -}()); -exports.Event = Event; - -},{}],40:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var PublisherSpeakingEvent = (function (_super) { - __extends(PublisherSpeakingEvent, _super); - function PublisherSpeakingEvent(target, type, connection, streamId) { - var _this = _super.call(this, false, target, type) || this; - _this.type = type; - _this.connection = connection; - _this.streamId = streamId; - return _this; - } - PublisherSpeakingEvent.prototype.callDefaultBehaviour = function () { }; - return PublisherSpeakingEvent; -}(Event_1.Event)); -exports.PublisherSpeakingEvent = PublisherSpeakingEvent; - -},{"./Event":39}],41:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var RecordingEvent = (function (_super) { - __extends(RecordingEvent, _super); - function RecordingEvent(target, type, id, name) { - var _this = _super.call(this, false, target, type) || this; - _this.id = id; - if (name !== id) { - _this.name = name; - } - return _this; - } - RecordingEvent.prototype.callDefaultBehaviour = function () { }; - return RecordingEvent; -}(Event_1.Event)); -exports.RecordingEvent = RecordingEvent; - -},{"./Event":39}],42:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var SessionDisconnectedEvent = (function (_super) { - __extends(SessionDisconnectedEvent, _super); - function SessionDisconnectedEvent(target, reason) { - var _this = _super.call(this, true, target, 'sessionDisconnected') || this; - _this.reason = reason; - return _this; - } - SessionDisconnectedEvent.prototype.callDefaultBehaviour = function () { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); - var session = this.target; - for (var connectionId in session.remoteConnections) { - if (!!session.remoteConnections[connectionId].stream) { - session.remoteConnections[connectionId].stream.disposeWebRtcPeer(); - session.remoteConnections[connectionId].stream.disposeMediaStream(); - if (session.remoteConnections[connectionId].stream.streamManager) { - session.remoteConnections[connectionId].stream.streamManager.removeAllVideos(); - } - delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId]; - session.remoteConnections[connectionId].dispose(); - } - delete session.remoteConnections[connectionId]; - } - }; - return SessionDisconnectedEvent; -}(Event_1.Event)); -exports.SessionDisconnectedEvent = SessionDisconnectedEvent; - -},{"./Event":39}],43:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var SignalEvent = (function (_super) { - __extends(SignalEvent, _super); - function SignalEvent(target, type, data, from) { - var _this = _super.call(this, false, target, type) || this; - _this.type = type; - _this.data = data; - _this.from = from; - return _this; - } - SignalEvent.prototype.callDefaultBehaviour = function () { }; - return SignalEvent; -}(Event_1.Event)); -exports.SignalEvent = SignalEvent; - -},{"./Event":39}],44:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var Publisher_1 = require("../../OpenVidu/Publisher"); -var Session_1 = require("../../OpenVidu/Session"); -var StreamEvent = (function (_super) { - __extends(StreamEvent, _super); - function StreamEvent(cancelable, target, type, stream, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.stream = stream; - _this.reason = reason; - return _this; - } - StreamEvent.prototype.callDefaultBehaviour = function () { - if (this.type === 'streamDestroyed') { - if (this.target instanceof Session_1.Session) { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); - this.stream.disposeWebRtcPeer(); - } - else if (this.target instanceof Publisher_1.Publisher) { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Publisher'"); - this.stream.isLocalStreamReadyToPublish = false; - } - this.stream.disposeMediaStream(); - if (this.stream.streamManager) - this.stream.streamManager.removeAllVideos(); - delete this.stream.session.remoteStreamsCreated[this.stream.streamId]; - var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId]; - if (!!remoteConnection && !!remoteConnection.options) { - var streamOptionsServer = remoteConnection.options.streams; - for (var i = streamOptionsServer.length - 1; i >= 0; --i) { - if (streamOptionsServer[i].id === this.stream.streamId) { - streamOptionsServer.splice(i, 1); - } - } - } - } - }; - return StreamEvent; -}(Event_1.Event)); -exports.StreamEvent = StreamEvent; - -},{"../../OpenVidu/Publisher":30,"../../OpenVidu/Session":31,"./Event":39}],45:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var StreamManagerEvent = (function (_super) { - __extends(StreamManagerEvent, _super); - function StreamManagerEvent(target) { - return _super.call(this, false, target, 'streamPlaying') || this; - } - StreamManagerEvent.prototype.callDefaultBehaviour = function () { }; - return StreamManagerEvent; -}(Event_1.Event)); -exports.StreamManagerEvent = StreamManagerEvent; - -},{"./Event":39}],46:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var VideoElementEvent = (function (_super) { - __extends(VideoElementEvent, _super); - function VideoElementEvent(element, target, type) { - var _this = _super.call(this, false, target, type) || this; - _this.element = element; - return _this; - } - VideoElementEvent.prototype.callDefaultBehaviour = function () { }; - return VideoElementEvent; -}(Event_1.Event)); -exports.VideoElementEvent = VideoElementEvent; - -},{"./Event":39}],47:[function(require,module,exports){ -function Mapper() { - var sources = {}; - this.forEach = function (callback) { - for (var key in sources) { - var source = sources[key]; - for (var key2 in source) - callback(source[key2]); - } - ; - }; - this.get = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return undefined; - return ids[id]; - }; - this.remove = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return; - delete ids[id]; - for (var i in ids) { - return false; - } - delete sources[source]; - }; - this.set = function (value, id, source) { - if (value == undefined) - return this.remove(id, source); - var ids = sources[source]; - if (ids == undefined) - sources[source] = ids = {}; - ids[id] = value; - }; -} -; -Mapper.prototype.pop = function (id, source) { - var value = this.get(id, source); - if (value == undefined) - return undefined; - this.remove(id, source); - return value; -}; -module.exports = Mapper; - -},{}],48:[function(require,module,exports){ -var JsonRpcClient = require('./jsonrpcclient'); -exports.JsonRpcClient = JsonRpcClient; - -},{"./jsonrpcclient":49}],49:[function(require,module,exports){ -var RpcBuilder = require('../'); -var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); -Date.now = Date.now || function () { - return +new Date; -}; -var PING_INTERVAL = 5000; -var RECONNECTING = 'RECONNECTING'; -var CONNECTED = 'CONNECTED'; -var DISCONNECTED = 'DISCONNECTED'; -var Logger = console; -function JsonRpcClient(configuration) { - var self = this; - var wsConfig = configuration.ws; - var notReconnectIfNumLessThan = -1; - var pingNextNum = 0; - var enabledPings = true; - var pingPongStarted = false; - var pingInterval; - var status = DISCONNECTED; - var onreconnecting = wsConfig.onreconnecting; - var onreconnected = wsConfig.onreconnected; - var onconnected = wsConfig.onconnected; - var onerror = wsConfig.onerror; - configuration.rpc.pull = function (params, request) { - request.reply(null, "push"); - }; - wsConfig.onreconnecting = function () { - Logger.debug("--------- ONRECONNECTING -----------"); - if (status === RECONNECTING) { - Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it"); - return; - } - status = RECONNECTING; - if (onreconnecting) { - onreconnecting(); - } - }; - wsConfig.onreconnected = function () { - Logger.debug("--------- ONRECONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - enabledPings = true; - updateNotReconnectIfLessThan(); - usePing(); - if (onreconnected) { - onreconnected(); - } - }; - wsConfig.onconnected = function () { - Logger.debug("--------- ONCONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - enabledPings = true; - usePing(); - if (onconnected) { - onconnected(); - } - }; - wsConfig.onerror = function (error) { - Logger.debug("--------- ONERROR -----------"); - status = DISCONNECTED; - if (onerror) { - onerror(error); - } - }; - var ws = new WebSocketWithReconnection(wsConfig); - Logger.debug('Connecting websocket to URI: ' + wsConfig.uri); - var rpcBuilderOptions = { - request_timeout: configuration.rpc.requestTimeout, - ping_request_timeout: configuration.rpc.heartbeatRequestTimeout - }; - var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) { - Logger.debug('Received request: ' + JSON.stringify(request)); - try { - var func = configuration.rpc[request.method]; - if (func === undefined) { - Logger.error("Method " + request.method + " not registered in client"); - } - else { - func(request.params, request); - } - } - catch (err) { - Logger.error('Exception processing request: ' + JSON.stringify(request)); - Logger.error(err); - } - }); - this.send = function (method, params, callback) { - if (method !== 'ping') { - Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); - } - var requestTime = Date.now(); - rpc.encode(method, params, function (error, result) { - if (error) { - try { - Logger.error("ERROR:" + error.message + " in Request: method:" + - method + " params:" + JSON.stringify(params) + " request:" + - error.request); - if (error.data) { - Logger.error("ERROR DATA:" + JSON.stringify(error.data)); - } - } - catch (e) { } - error.requestTime = requestTime; - } - if (callback) { - if (result != undefined && result.value !== 'pong') { - Logger.debug('Response: ' + JSON.stringify(result)); - } - callback(error, result); - } - }); - }; - function updateNotReconnectIfLessThan() { - Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' + - notReconnectIfNumLessThan + ')'); - notReconnectIfNumLessThan = pingNextNum; - } - function sendPing() { - if (enabledPings) { - var params = null; - if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) { - params = { - interval: configuration.heartbeat || PING_INTERVAL - }; - } - pingNextNum++; - self.send('ping', params, (function (pingNum) { - return function (error, result) { - if (error) { - Logger.debug("Error in ping request #" + pingNum + " (" + - error.message + ")"); - if (pingNum > notReconnectIfNumLessThan) { - enabledPings = false; - updateNotReconnectIfLessThan(); - Logger.debug("Server did not respond to ping message #" + - pingNum + ". Reconnecting... "); - ws.reconnectWs(); - } - } - }; - })(pingNextNum)); - } - else { - Logger.debug("Trying to send ping, but ping is not enabled"); - } - } - function usePing() { - if (!pingPongStarted) { - Logger.debug("Starting ping (if configured)"); - pingPongStarted = true; - if (configuration.heartbeat != undefined) { - pingInterval = setInterval(sendPing, configuration.heartbeat); - sendPing(); - } - } - } - this.close = function () { - Logger.debug("Closing jsonRpcClient explicitly by client"); - if (pingInterval != undefined) { - Logger.debug("Clearing ping interval"); - clearInterval(pingInterval); - } - pingPongStarted = false; - enabledPings = false; - if (configuration.sendCloseMessage) { - Logger.debug("Sending close message"); - this.send('closeSession', null, function (error, result) { - if (error) { - Logger.error("Error sending close message: " + JSON.stringify(error)); - } - ws.close(); - }); - } - else { - ws.close(); - } - }; - this.forceClose = function (millis) { - ws.forceClose(millis); - }; - this.reconnect = function () { - ws.reconnectWs(); - }; -} -module.exports = JsonRpcClient; - -},{"../":52,"./transports/webSocketWithReconnection":51}],50:[function(require,module,exports){ -var WebSocketWithReconnection = require('./webSocketWithReconnection'); -exports.WebSocketWithReconnection = WebSocketWithReconnection; - -},{"./webSocketWithReconnection":51}],51:[function(require,module,exports){ -(function (global){ -"use strict"; -var BrowserWebSocket = global.WebSocket || global.MozWebSocket; -var Logger = console; -var MAX_RETRIES = 2000; -var RETRY_TIME_MS = 3000; -var CONNECTING = 0; -var OPEN = 1; -var CLOSING = 2; -var CLOSED = 3; -function WebSocketWithReconnection(config) { - var closing = false; - var registerMessageHandler; - var wsUri = config.uri; - var useSockJS = config.useSockJS; - var reconnecting = false; - var forcingDisconnection = false; - var ws; - if (useSockJS) { - ws = new SockJS(wsUri); - } - else { - ws = new WebSocket(wsUri); - } - ws.onopen = function () { - logConnected(ws, wsUri); - if (config.onconnected) { - config.onconnected(); - } - }; - ws.onerror = function (error) { - Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error); - if (config.onerror) { - config.onerror(error); - } - }; - function logConnected(ws, wsUri) { - try { - Logger.debug("WebSocket connected to " + wsUri); - } - catch (e) { - Logger.error(e); - } - } - var reconnectionOnClose = function () { - if (ws.readyState === CLOSED) { - if (closing) { - Logger.debug("Connection closed by user"); - } - else { - Logger.debug("Connection closed unexpectecly. Reconnecting..."); - reconnectToSameUri(MAX_RETRIES, 1); - } - } - else { - Logger.debug("Close callback from previous websocket. Ignoring it"); - } - }; - ws.onclose = reconnectionOnClose; - function reconnectToSameUri(maxRetries, numRetries) { - Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); - if (numRetries === 1) { - if (reconnecting) { - Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); - return; - } - else { - reconnecting = true; - } - if (config.onreconnecting) { - config.onreconnecting(); - } - } - if (forcingDisconnection) { - reconnectToNewUri(maxRetries, numRetries, wsUri); - } - else { - if (config.newWsUriOnReconnection) { - config.newWsUriOnReconnection(function (error, newWsUri) { - if (error) { - Logger.debug(error); - setTimeout(function () { - reconnectToSameUri(maxRetries, numRetries + 1); - }, RETRY_TIME_MS); - } - else { - reconnectToNewUri(maxRetries, numRetries, newWsUri); - } - }); - } - else { - reconnectToNewUri(maxRetries, numRetries, wsUri); - } - } - } - function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { - Logger.debug("Reconnection attempt #" + numRetries); - ws.close(); - wsUri = reconnectWsUri || wsUri; - var newWs; - if (useSockJS) { - newWs = new SockJS(wsUri); - } - else { - newWs = new WebSocket(wsUri); - } - newWs.onopen = function () { - Logger.debug("Reconnected after " + numRetries + " attempts..."); - logConnected(newWs, wsUri); - reconnecting = false; - registerMessageHandler(); - if (config.onreconnected()) { - config.onreconnected(); - } - newWs.onclose = reconnectionOnClose; - }; - var onErrorOrClose = function (error) { - Logger.warn("Reconnection error: ", error); - if (numRetries === maxRetries) { - if (config.ondisconnect) { - config.ondisconnect(); - } - } - else { - setTimeout(function () { - reconnectToSameUri(maxRetries, numRetries + 1); - }, RETRY_TIME_MS); - } - }; - newWs.onerror = onErrorOrClose; - ws = newWs; - } - this.close = function () { - closing = true; - ws.close(); - }; - this.forceClose = function (millis) { - Logger.debug("Testing: Force WebSocket close"); - if (millis) { - Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); - var goodWsUri = wsUri; - wsUri = "wss://21.234.12.34.4:443/"; - forcingDisconnection = true; - setTimeout(function () { - Logger.debug("Testing: Recover good wsUri " + goodWsUri); - wsUri = goodWsUri; - forcingDisconnection = false; - }, millis); - } - ws.close(); - }; - this.reconnectWs = function () { - Logger.debug("reconnectWs"); - reconnectToSameUri(MAX_RETRIES, 1, wsUri); - }; - this.send = function (message) { - ws.send(message); - }; - this.addEventListener = function (type, callback) { - registerMessageHandler = function () { - ws.addEventListener(type, callback); - }; - registerMessageHandler(); - }; -} -module.exports = WebSocketWithReconnection; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],52:[function(require,module,exports){ -var defineProperty_IE8 = false; -if (Object.defineProperty) { - try { - Object.defineProperty({}, "x", {}); - } - catch (e) { - defineProperty_IE8 = true; - } -} -if (!Function.prototype.bind) { - Function.prototype.bind = function (oThis) { - if (typeof this !== 'function') { - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { - return fToBind.apply(this instanceof fNOP && oThis - ? this - : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); - }; - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - return fBound; - }; -} -var EventEmitter = require('events').EventEmitter; -var inherits = require('inherits'); -var packers = require('./packers'); -var Mapper = require('./Mapper'); -var BASE_TIMEOUT = 5000; -function unifyResponseMethods(responseMethods) { - if (!responseMethods) - return {}; - for (var key in responseMethods) { - var value = responseMethods[key]; - if (typeof value == 'string') - responseMethods[key] = - { - response: value - }; - } - ; - return responseMethods; -} -; -function unifyTransport(transport) { - if (!transport) - return; - if (transport instanceof Function) - return { send: transport }; - if (transport.send instanceof Function) - return transport; - if (transport.postMessage instanceof Function) { - transport.send = transport.postMessage; - return transport; - } - if (transport.write instanceof Function) { - transport.send = transport.write; - return transport; - } - if (transport.onmessage !== undefined) - return; - if (transport.pause instanceof Function) - return; - throw new SyntaxError("Transport is not a function nor a valid object"); -} -; -function RpcNotification(method, params) { - if (defineProperty_IE8) { - this.method = method; - this.params = params; - } - else { - Object.defineProperty(this, 'method', { value: method, enumerable: true }); - Object.defineProperty(this, 'params', { value: params, enumerable: true }); - } -} -; -function RpcBuilder(packer, options, transport, onRequest) { - var self = this; - if (!packer) - throw new SyntaxError('Packer is not defined'); - if (!packer.pack || !packer.unpack) - throw new SyntaxError('Packer is invalid'); - var responseMethods = unifyResponseMethods(packer.responseMethods); - if (options instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = options; - transport = undefined; - options = undefined; - } - ; - if (options && options.send instanceof Function) { - if (transport && !(transport instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - onRequest = transport; - transport = options; - options = undefined; - } - ; - if (transport instanceof Function) { - if (onRequest != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = transport; - transport = undefined; - } - ; - if (transport && transport.send instanceof Function) - if (onRequest && !(onRequest instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - options = options || {}; - EventEmitter.call(this); - if (onRequest) - this.on('request', onRequest); - if (defineProperty_IE8) - this.peerID = options.peerID; - else - Object.defineProperty(this, 'peerID', { value: options.peerID }); - var max_retries = options.max_retries || 0; - function transportMessage(event) { - self.decode(event.data || event); - } - ; - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - if (transport) { - if (transport.removeEventListener) - transport.removeEventListener('message', transportMessage); - else if (transport.removeListener) - transport.removeListener('data', transportMessage); - } - ; - if (value) { - if (value.addEventListener) - value.addEventListener('message', transportMessage); - else if (value.addListener) - value.addListener('data', transportMessage); - } - ; - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - this.setTransport(transport); - var request_timeout = options.request_timeout || BASE_TIMEOUT; - var ping_request_timeout = options.ping_request_timeout || request_timeout; - var response_timeout = options.response_timeout || BASE_TIMEOUT; - var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT; - var requestID = 0; - var requests = new Mapper(); - var responses = new Mapper(); - var processedResponses = new Mapper(); - var message2Key = {}; - function storeResponse(message, id, dest) { - var response = { - message: message, - timeout: setTimeout(function () { - responses.remove(id, dest); - }, response_timeout) - }; - responses.set(response, id, dest); - } - ; - function storeProcessedResponse(ack, from) { - var timeout = setTimeout(function () { - processedResponses.remove(ack, from); - }, duplicates_timeout); - processedResponses.set(timeout, ack, from); - } - ; - function RpcRequest(method, params, id, from, transport) { - RpcNotification.call(this, method, params); - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - var response = responses.get(id, from); - if (!(transport || self.getTransport())) { - if (defineProperty_IE8) - this.duplicated = Boolean(response); - else - Object.defineProperty(this, 'duplicated', { - value: Boolean(response) - }); - } - var responseMethod = responseMethods[method]; - this.pack = packer.pack.bind(packer, this, id); - this.reply = function (error, result, transport) { - if (error instanceof Function || error && error.send instanceof Function) { - if (result != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = error; - result = null; - error = undefined; - } - else if (result instanceof Function - || result && result.send instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = result; - result = null; - } - ; - transport = unifyTransport(transport); - if (response) - clearTimeout(response.timeout); - if (from != undefined) { - if (error) - error.dest = from; - if (result) - result.dest = from; - } - ; - var message; - if (error || result != undefined) { - if (self.peerID != undefined) { - if (error) - error.from = self.peerID; - else - result.from = self.peerID; - } - if (responseMethod) { - if (responseMethod.error == undefined && error) - message = - { - error: error - }; - else { - var method = error - ? responseMethod.error - : responseMethod.response; - message = - { - method: method, - params: error || result - }; - } - } - else - message = - { - error: error, - result: result - }; - message = packer.pack(message, id); - } - else if (response) - message = response.message; - else - message = packer.pack({ result: null }, id); - storeResponse(message, id, from); - transport = transport || this.getTransport() || self.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - } - ; - inherits(RpcRequest, RpcNotification); - function cancel(message) { - var key = message2Key[message]; - if (!key) - return; - delete message2Key[message]; - var request = requests.pop(key.id, key.dest); - if (!request) - return; - clearTimeout(request.timeout); - storeProcessedResponse(key.id, key.dest); - } - ; - this.cancel = function (message) { - if (message) - return cancel(message); - for (var message in message2Key) - cancel(message); - }; - this.close = function () { - var transport = this.getTransport(); - if (transport && transport.close) - transport.close(); - this.cancel(); - processedResponses.forEach(clearTimeout); - responses.forEach(function (response) { - clearTimeout(response.timeout); - }); - }; - this.encode = function (method, params, dest, transport, callback) { - if (params instanceof Function) { - if (dest != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = params; - transport = undefined; - dest = undefined; - params = undefined; - } - else if (dest instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = dest; - transport = undefined; - dest = undefined; - } - else if (transport instanceof Function) { - if (callback != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = transport; - transport = undefined; - } - ; - if (self.peerID != undefined) { - params = params || {}; - params.from = self.peerID; - } - ; - if (dest != undefined) { - params = params || {}; - params.dest = dest; - } - ; - var message = { - method: method, - params: params - }; - if (callback) { - var id = requestID++; - var retried = 0; - message = packer.pack(message, id); - function dispatchCallback(error, result) { - self.cancel(message); - callback(error, result); - } - ; - var request = { - message: message, - callback: dispatchCallback, - responseMethods: responseMethods[method] || {} - }; - var encode_transport = unifyTransport(transport); - function sendRequest(transport) { - var rt = (method === 'ping' ? ping_request_timeout : request_timeout); - request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++)); - message2Key[message] = { id: id, dest: dest }; - requests.set(request, id, dest); - transport = transport || encode_transport || self.getTransport(); - if (transport) - return transport.send(message); - return message; - } - ; - function retry(transport) { - transport = unifyTransport(transport); - console.warn(retried + ' retry for request message:', message); - var timeout = processedResponses.pop(id, dest); - clearTimeout(timeout); - return sendRequest(transport); - } - ; - function timeout() { - if (retried < max_retries) - return retry(transport); - var error = new Error('Request has timed out'); - error.request = message; - error.retry = retry; - dispatchCallback(error); - } - ; - return sendRequest(transport); - } - ; - message = packer.pack(message); - transport = transport || this.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - this.decode = function (message, transport) { - if (!message) - throw new TypeError("Message is not defined"); - try { - message = packer.unpack(message); - } - catch (e) { - return console.debug(e, message); - } - ; - var id = message.id; - var ack = message.ack; - var method = message.method; - var params = message.params || {}; - var from = params.from; - var dest = params.dest; - if (self.peerID != undefined && from == self.peerID) - return; - if (id == undefined && ack == undefined) { - var notification = new RpcNotification(method, params); - if (self.emit('request', notification)) - return; - return notification; - } - ; - function processRequest() { - transport = unifyTransport(transport) || self.getTransport(); - if (transport) { - var response = responses.get(id, from); - if (response) - return transport.send(response.message); - } - ; - var idAck = (id != undefined) ? id : ack; - var request = new RpcRequest(method, params, idAck, from, transport); - if (self.emit('request', request)) - return; - return request; - } - ; - function processResponse(request, error, result) { - request.callback(error, result); - } - ; - function duplicatedResponse(timeout) { - console.warn("Response already processed", message); - clearTimeout(timeout); - storeProcessedResponse(ack, from); - } - ; - if (method) { - if (dest == undefined || dest == self.peerID) { - var request = requests.get(ack, from); - if (request) { - var responseMethods = request.responseMethods; - if (method == responseMethods.error) - return processResponse(request, params); - if (method == responseMethods.response) - return processResponse(request, null, params); - return processRequest(); - } - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - } - return processRequest(); - } - ; - var error = message.error; - var result = message.result; - if (error && error.dest && error.dest != self.peerID) - return; - if (result && result.dest && result.dest != self.peerID) - return; - var request = requests.get(ack, from); - if (!request) { - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - return console.warn("No callback was defined for this message", message); - } - ; - processResponse(request, error, result); - }; -} -; -inherits(RpcBuilder, EventEmitter); -RpcBuilder.RpcNotification = RpcNotification; -module.exports = RpcBuilder; -var clients = require('./clients'); -var transports = require('./clients/transports'); -RpcBuilder.clients = clients; -RpcBuilder.clients.transports = transports; -RpcBuilder.packers = packers; - -},{"./Mapper":47,"./clients":48,"./clients/transports":50,"./packers":55,"events":1,"inherits":6}],53:[function(require,module,exports){ -function pack(message, id) { - var result = { - jsonrpc: "2.0" - }; - if (message.method) { - result.method = message.method; - if (message.params) - result.params = message.params; - if (id != undefined) - result.id = id; - } - else if (id != undefined) { - if (message.error) { - if (message.result !== undefined) - throw new TypeError("Both result and error are defined"); - result.error = message.error; - } - else if (message.result !== undefined) - result.result = message.result; - else - throw new TypeError("No result or error is defined"); - result.id = id; - } - ; - return JSON.stringify(result); -} -; -function unpack(message) { - var result = message; - if (typeof message === 'string' || message instanceof String) { - result = JSON.parse(message); - } - var version = result.jsonrpc; - if (version !== '2.0') - throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); - if (result.method == undefined) { - if (result.id == undefined) - throw new TypeError("Invalid message: " + message); - var result_defined = result.result !== undefined; - var error_defined = result.error !== undefined; - if (result_defined && error_defined) - throw new TypeError("Both result and error are defined: " + message); - if (!result_defined && !error_defined) - throw new TypeError("No result or error is defined: " + message); - result.ack = result.id; - delete result.id; - } - return result; -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],54:[function(require,module,exports){ -function pack(message) { - throw new TypeError("Not yet implemented"); -} -; -function unpack(message) { - throw new TypeError("Not yet implemented"); -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],55:[function(require,module,exports){ -var JsonRPC = require('./JsonRPC'); -var XmlRPC = require('./XmlRPC'); -exports.JsonRPC = JsonRPC; -exports.XmlRPC = XmlRPC; - -},{"./JsonRPC":53,"./XmlRPC":54}],56:[function(require,module,exports){ -var freeice = require('freeice'); -var inherits = require('inherits'); -var UAParser = require('ua-parser-js'); -var uuid = require('uuid'); -var hark = require('hark'); -var EventEmitter = require('events').EventEmitter; -var recursive = require('merge').recursive.bind(undefined, true); -var sdpTranslator = require('sdp-translator'); -var logger = window.Logger || console; -var MEDIA_CONSTRAINTS = { - audio: true, - video: { - width: 640, - framerate: 15 - } -}; -var ua = (window && window.navigator) ? window.navigator.userAgent : ''; -var parser = new UAParser(ua); -var browser = parser.getBrowser(); -var usePlanB = false; -if (browser.name === 'Chrome' || browser.name === 'Chromium') { - logger.debug(browser.name + ": using SDP PlanB"); - usePlanB = true; -} -function noop(error) { - if (error) - logger.error(error); -} -function trackStop(track) { - track.stop && track.stop(); -} -function streamStop(stream) { - stream.getTracks().forEach(trackStop); -} -var dumpSDP = function (description) { - if (typeof description === 'undefined' || description === null) { - return ''; - } - return 'type: ' + description.type + '\r\n' + description.sdp; -}; -function bufferizeCandidates(pc, onerror) { - var candidatesQueue = []; - pc.addEventListener('signalingstatechange', function () { - if (this.signalingState === 'stable') { - while (candidatesQueue.length) { - var entry = candidatesQueue.shift(); - pc.addIceCandidate(entry.candidate, entry.callback, entry.callback); - } - } - }); - return function (candidate, callback) { - callback = callback || onerror; - switch (pc.signalingState) { - case 'closed': - callback(new Error('PeerConnection object is closed')); - break; - case 'stable': - if (pc.remoteDescription) { - pc.addIceCandidate(candidate, callback, callback); - } - break; - default: - candidatesQueue.push({ - candidate: candidate, - callback: callback - }); - } - }; -} -function removeFIDFromOffer(sdp) { - var n = sdp.indexOf("a=ssrc-group:FID"); - if (n > 0) { - return sdp.slice(0, n); - } - else { - return sdp; - } -} -function getSimulcastInfo(videoStream) { - var videoTracks = videoStream.getVideoTracks(); - if (!videoTracks.length) { - logger.warn('No video tracks available in the video stream'); - return ''; - } - var lines = [ - 'a=x-google-flag:conference', - 'a=ssrc-group:SIM 1 2 3', - 'a=ssrc:1 cname:localVideo', - 'a=ssrc:1 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:1 mslabel:' + videoStream.id, - 'a=ssrc:1 label:' + videoTracks[0].id, - 'a=ssrc:2 cname:localVideo', - 'a=ssrc:2 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:2 mslabel:' + videoStream.id, - 'a=ssrc:2 label:' + videoTracks[0].id, - 'a=ssrc:3 cname:localVideo', - 'a=ssrc:3 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:3 mslabel:' + videoStream.id, - 'a=ssrc:3 label:' + videoTracks[0].id - ]; - lines.push(''); - return lines.join('\n'); -} -function WebRtcPeer(mode, options, callback) { - if (!(this instanceof WebRtcPeer)) { - return new WebRtcPeer(mode, options, callback); - } - WebRtcPeer.super_.call(this); - if (options instanceof Function) { - callback = options; - options = undefined; - } - options = options || {}; - callback = (callback || noop).bind(this); - var self = this; - var localVideo = options.localVideo; - var remoteVideo = options.remoteVideo; - var videoStream = options.videoStream; - var audioStream = options.audioStream; - var mediaConstraints = options.mediaConstraints; - var connectionConstraints = options.connectionConstraints; - var pc = options.peerConnection; - var sendSource = options.sendSource || 'webcam'; - var guid = uuid.v4(); - var configuration = recursive({ - iceServers: (!!options.iceServers && options.iceServers.length > 0) ? options.iceServers : freeice() - }, options.configuration); - var onicecandidate = options.onicecandidate; - if (onicecandidate) - this.on('icecandidate', onicecandidate); - var oncandidategatheringdone = options.oncandidategatheringdone; - if (oncandidategatheringdone) { - this.on('candidategatheringdone', oncandidategatheringdone); - } - var simulcast = options.simulcast; - var multistream = options.multistream; - var interop = new sdpTranslator.Interop(); - var candidatesQueueOut = []; - var candidategatheringdone = false; - Object.defineProperties(this, { - 'peerConnection': { - get: function () { - return pc; - } - }, - 'id': { - value: options.id || guid, - writable: false - }, - 'remoteVideo': { - get: function () { - return remoteVideo; - } - }, - 'localVideo': { - get: function () { - return localVideo; - } - }, - 'currentFrame': { - get: function () { - if (!remoteVideo) - return; - if (remoteVideo.readyState < remoteVideo.HAVE_CURRENT_DATA) - throw new Error('No video stream data available'); - var canvas = document.createElement('canvas'); - canvas.width = remoteVideo.videoWidth; - canvas.height = remoteVideo.videoHeight; - canvas.getContext('2d').drawImage(remoteVideo, 0, 0); - return canvas; - } - } - }); - if (!pc) { - pc = new RTCPeerConnection(configuration); - } - pc.addEventListener('icecandidate', function (event) { - var candidate = event.candidate; - if (EventEmitter.listenerCount(self, 'icecandidate') || - EventEmitter.listenerCount(self, 'candidategatheringdone')) { - if (candidate) { - var cand; - if (multistream && usePlanB) { - cand = interop.candidateToUnifiedPlan(candidate); - } - else { - cand = candidate; - } - self.emit('icecandidate', cand); - candidategatheringdone = false; - } - else if (!candidategatheringdone) { - self.emit('candidategatheringdone'); - candidategatheringdone = true; - } - } - else if (!candidategatheringdone) { - candidatesQueueOut.push(candidate); - if (!candidate) - candidategatheringdone = true; - } - }); - pc.onaddstream = options.onaddstream; - pc.onnegotiationneeded = options.onnegotiationneeded; - this.on('newListener', function (event, listener) { - if (event === 'icecandidate' || event === 'candidategatheringdone') { - while (candidatesQueueOut.length) { - var candidate = candidatesQueueOut.shift(); - if (!candidate === (event === 'candidategatheringdone')) { - listener(candidate); - } - } - } - }); - var addIceCandidate = bufferizeCandidates(pc); - this.addIceCandidate = function (iceCandidate, callback) { - var candidate; - if (multistream && usePlanB) { - candidate = interop.candidateToPlanB(iceCandidate); - } - else { - candidate = new RTCIceCandidate(iceCandidate); - } - logger.debug('Remote ICE candidate received', iceCandidate); - callback = (callback || noop).bind(this); - addIceCandidate(candidate, callback); - }; - this.generateOffer = function (callback) { - callback = callback.bind(this); - var offerAudio = true; - var offerVideo = true; - if (mediaConstraints) { - offerAudio = (typeof mediaConstraints.audio === 'boolean') ? - mediaConstraints.audio : true; - offerVideo = (typeof mediaConstraints.video === 'boolean') ? - mediaConstraints.video : true; - } - var browserDependantConstraints = { - offerToReceiveAudio: (mode !== 'sendonly' && offerAudio), - offerToReceiveVideo: (mode !== 'sendonly' && offerVideo) - }; - var constraints = browserDependantConstraints; - logger.debug('constraints: ' + JSON.stringify(constraints)); - pc.createOffer(constraints).then(function (offer) { - logger.debug('Created SDP offer'); - offer = mangleSdpToAddSimulcast(offer); - return pc.setLocalDescription(offer); - }).then(function () { - var localDescription = pc.localDescription; - logger.debug('Local description set', localDescription.sdp); - if (multistream && usePlanB) { - localDescription = interop.toUnifiedPlan(localDescription); - logger.debug('offer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); - } - callback(null, localDescription.sdp, self.processAnswer.bind(self)); - }).catch(callback); - }; - this.getLocalSessionDescriptor = function () { - return pc.localDescription; - }; - this.getRemoteSessionDescriptor = function () { - return pc.remoteDescription; - }; - function setRemoteVideo() { - if (remoteVideo) { - remoteVideo.pause(); - var stream = pc.getRemoteStreams()[0]; - remoteVideo.srcObject = stream; - logger.debug('Remote stream:', stream); - remoteVideo.load(); - } - } - this.showLocalVideo = function () { - localVideo.srcObject = videoStream; - localVideo.muted = true; - }; - this.processAnswer = function (sdpAnswer, callback) { - callback = (callback || noop).bind(this); - var answer = new RTCSessionDescription({ - type: 'answer', - sdp: sdpAnswer - }); - if (multistream && usePlanB) { - var planBAnswer = interop.toPlanB(answer); - logger.debug('asnwer::planB', dumpSDP(planBAnswer)); - answer = planBAnswer; - } - logger.debug('SDP answer received, setting remote description'); - if (pc.signalingState === 'closed') { - return callback('PeerConnection is closed'); - } - pc.setRemoteDescription(answer, function () { - setRemoteVideo(); - callback(); - }, callback); - }; - this.processOffer = function (sdpOffer, callback) { - callback = callback.bind(this); - var offer = new RTCSessionDescription({ - type: 'offer', - sdp: sdpOffer - }); - if (multistream && usePlanB) { - var planBOffer = interop.toPlanB(offer); - logger.debug('offer::planB', dumpSDP(planBOffer)); - offer = planBOffer; - } - logger.debug('SDP offer received, setting remote description'); - if (pc.signalingState === 'closed') { - return callback('PeerConnection is closed'); - } - pc.setRemoteDescription(offer).then(function () { - return setRemoteVideo(); - }).then(function () { - return pc.createAnswer(); - }).then(function (answer) { - answer = mangleSdpToAddSimulcast(answer); - logger.debug('Created SDP answer'); - return pc.setLocalDescription(answer); - }).then(function () { - var localDescription = pc.localDescription; - if (multistream && usePlanB) { - localDescription = interop.toUnifiedPlan(localDescription); - logger.debug('answer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); - } - logger.debug('Local description set', localDescription.sdp); - callback(null, localDescription.sdp); - }).catch(callback); - }; - function mangleSdpToAddSimulcast(answer) { - if (simulcast) { - if (browser.name === 'Chrome' || browser.name === 'Chromium') { - logger.debug('Adding multicast info'); - answer = new RTCSessionDescription({ - 'type': answer.type, - 'sdp': removeFIDFromOffer(answer.sdp) + getSimulcastInfo(videoStream) - }); - } - else { - logger.warn('Simulcast is only available in Chrome browser.'); - } - } - return answer; - } - function start() { - if (pc.signalingState === 'closed') { - callback('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); - } - if (videoStream && localVideo) { - self.showLocalVideo(); - } - if (videoStream) { - pc.addStream(videoStream); - } - if (audioStream) { - pc.addStream(audioStream); - } - var browser = parser.getBrowser(); - if (mode === 'sendonly' && - (browser.name === 'Chrome' || browser.name === 'Chromium') && - browser.major === 39) { - mode = 'sendrecv'; - } - callback(); - } - if (mode !== 'recvonly' && !videoStream && !audioStream) { - function getMedia(constraints) { - if (constraints === undefined) { - constraints = MEDIA_CONSTRAINTS; - } - navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - videoStream = stream; - start(); - }).catch(callback); - } - if (sendSource === 'webcam') { - getMedia(mediaConstraints); - } - else { - getScreenConstraints(sendSource, function (error, constraints_) { - if (error) - return callback(error); - constraints = [mediaConstraints]; - constraints.unshift(constraints_); - getMedia(recursive.apply(undefined, constraints)); - }, guid); - } - } - else { - setTimeout(start, 0); - } - this.on('_dispose', function () { - if (localVideo) { - localVideo.pause(); - localVideo.srcObject = null; - localVideo.load(); - localVideo.muted = false; - } - if (remoteVideo) { - remoteVideo.pause(); - remoteVideo.srcObject = null; - remoteVideo.load(); - } - self.removeAllListeners(); - if (window.cancelChooseDesktopMedia !== undefined) { - window.cancelChooseDesktopMedia(guid); - } - }); -} -inherits(WebRtcPeer, EventEmitter); -function createEnableDescriptor(type) { - var method = 'get' + type + 'Tracks'; - return { - enumerable: true, - get: function () { - if (!this.peerConnection) - return; - var streams = this.peerConnection.getLocalStreams(); - if (!streams.length) - return; - for (var i = 0, stream; stream = streams[i]; i++) { - var tracks = stream[method](); - for (var j = 0, track; track = tracks[j]; j++) - if (!track.enabled) - return false; - } - return true; - }, - set: function (value) { - function trackSetEnable(track) { - track.enabled = value; - } - this.peerConnection.getLocalStreams().forEach(function (stream) { - stream[method]().forEach(trackSetEnable); - }); - } - }; -} -Object.defineProperties(WebRtcPeer.prototype, { - 'enabled': { - enumerable: true, - get: function () { - return this.audioEnabled && this.videoEnabled; - }, - set: function (value) { - this.audioEnabled = this.videoEnabled = value; - } - }, - 'audioEnabled': createEnableDescriptor('Audio'), - 'videoEnabled': createEnableDescriptor('Video') -}); -WebRtcPeer.prototype.getLocalStream = function (index) { - if (this.peerConnection) { - return this.peerConnection.getLocalStreams()[index || 0]; - } -}; -WebRtcPeer.prototype.getRemoteStream = function (index) { - if (this.peerConnection) { - return this.peerConnection.getRemoteStreams()[index || 0]; - } -}; -WebRtcPeer.prototype.dispose = function () { - logger.debug('Disposing WebRtcPeer'); - var pc = this.peerConnection; - try { - if (pc) { - if (pc.signalingState === 'closed') - return; - pc.getLocalStreams().forEach(streamStop); - pc.close(); - } - } - catch (err) { - logger.warn('Exception disposing webrtc peer ' + err); - } - this.emit('_dispose'); -}; -function WebRtcPeerRecvonly(options, callback) { - if (!(this instanceof WebRtcPeerRecvonly)) { - return new WebRtcPeerRecvonly(options, callback); - } - WebRtcPeerRecvonly.super_.call(this, 'recvonly', options, callback); -} -inherits(WebRtcPeerRecvonly, WebRtcPeer); -function WebRtcPeerSendonly(options, callback) { - if (!(this instanceof WebRtcPeerSendonly)) { - return new WebRtcPeerSendonly(options, callback); - } - WebRtcPeerSendonly.super_.call(this, 'sendonly', options, callback); -} -inherits(WebRtcPeerSendonly, WebRtcPeer); -function WebRtcPeerSendrecv(options, callback) { - if (!(this instanceof WebRtcPeerSendrecv)) { - return new WebRtcPeerSendrecv(options, callback); - } - WebRtcPeerSendrecv.super_.call(this, 'sendrecv', options, callback); -} -inherits(WebRtcPeerSendrecv, WebRtcPeer); -function harkUtils(stream, options) { - return hark(stream, options); -} -exports.bufferizeCandidates = bufferizeCandidates; -exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; -exports.WebRtcPeerSendonly = WebRtcPeerSendonly; -exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; -exports.hark = harkUtils; - -},{"events":1,"freeice":2,"hark":5,"inherits":6,"merge":7,"sdp-translator":15,"ua-parser-js":18,"uuid":19}],57:[function(require,module,exports){ -var WebRtcPeer = require('./WebRtcPeer'); -exports.WebRtcPeer = WebRtcPeer; - -},{"./WebRtcPeer":56}],58:[function(require,module,exports){ -window.getScreenId = function (callback) { - if (!!navigator.mozGetUserMedia) { - callback(null, 'firefox', { - video: { - mozMediaSource: 'window', - mediaSource: 'window' - } - }); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeMediaSourceId) { - if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { - callback('permission-denied'); - } - else { - callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId)); - } - window.removeEventListener('message', onIFrameCallback); - } - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); - window.removeEventListener('message', onIFrameCallback); - } - } - setTimeout(postGetSourceIdMessage, 100); -}; -function getScreenConstraints(error, sourceId) { - var screen_constraints = { - audio: false, - video: { - mandatory: { - chromeMediaSource: error ? 'screen' : 'desktop', - maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, - maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 - }, - optional: [] - } - }; - if (sourceId) { - screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; - } - return screen_constraints; -} -var iframe; -function postGetSourceIdMessage() { - if (!iframe) { - loadIFrame(postGetSourceIdMessage); - return; - } - if (!iframe.isLoaded) { - setTimeout(postGetSourceIdMessage, 100); - return; - } - iframe.contentWindow.postMessage({ - captureSourceId: true - }, '*'); -} -function loadIFrame(loadCallback) { - if (iframe) { - loadCallback(); - return; - } - iframe = document.createElement('iframe'); - iframe.onload = function () { - iframe.isLoaded = true; - loadCallback(); - }; - iframe.src = 'https://www.webrtc-experiment.com/getSourceId/'; - iframe.style.display = 'none'; - (document.body || document.documentElement).appendChild(iframe); -} -window.getChromeExtensionStatus = function (callback) { - if (!!navigator.mozGetUserMedia) { - callback('installed-enabled'); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus); - } - window.removeEventListener('message', onIFrameCallback); - } - setTimeout(postGetChromeExtensionStatusMessage, 100); -}; -function postGetChromeExtensionStatusMessage() { - if (!iframe) { - loadIFrame(postGetChromeExtensionStatusMessage); - return; - } - if (!iframe.isLoaded) { - setTimeout(postGetChromeExtensionStatusMessage, 100); - return; - } - iframe.contentWindow.postMessage({ - getChromeExtensionStatus: true - }, '*'); -} -exports.getScreenId = getScreenId; - -},{}],59:[function(require,module,exports){ -var chromeMediaSource = 'screen'; -var screenCallback; -var isFirefox = typeof window.InstallTrigger !== 'undefined'; -var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; -var isChrome = !!window.chrome && !isOpera; -window.addEventListener('message', function (event) { - if (event.origin != window.location.origin) { - return; - } - onMessageCallback(event.data); -}); -function onMessageCallback(data) { - if (data == 'PermissionDeniedError') { - chromeMediaSource = 'PermissionDeniedError'; - if (screenCallback) - return screenCallback('PermissionDeniedError'); - else - throw new Error('PermissionDeniedError'); - } - if (data == 'rtcmulticonnection-extension-loaded') { - chromeMediaSource = 'desktop'; - } - if (data.sourceId && screenCallback) { - screenCallback(sourceId = data.sourceId); - } -} -function isChromeExtensionAvailable(callback) { - if (isFirefox) - return callback(false); - if (chromeMediaSource == 'desktop') - return callback('isFirefox'); - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback('unavailable'); - } - else - callback('available'); - }, 2000); -} -function getSourceId(callback) { - if (!callback) - throw '"callback" parameter is mandatory.'; - if (sourceId) - return callback(sourceId); - screenCallback = callback; - window.postMessage('get-sourceId', '*'); -} -function getChromeExtensionStatus(extensionid, callback) { - if (isFirefox) - return callback('not-chrome'); - if (arguments.length != 2) { - callback = extensionid; - extensionid = 'ajhifddimkapgcifgcodmmfdlknahffk'; - } - var image = document.createElement('img'); - image.src = 'chrome-extension://' + extensionid + '/icon.png'; - image.onload = function () { - chromeMediaSource = 'screen'; - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback(extensionid == extensionid ? 'installed-enabled' : 'installed-disabled'); - } - else - callback('installed-enabled'); - }, 2000); - }; - image.onerror = function () { - callback('not-installed'); - }; -} -function getScreenConstraints(callback) { - sourceId = ''; - var firefoxScreenConstraints = { - mozMediaSource: 'window', - mediaSource: 'window' - }; - if (isFirefox) - return callback(null, firefoxScreenConstraints); - var screen_constraints = { - mandatory: { - chromeMediaSource: chromeMediaSource, - maxWidth: screen.width > 1920 ? screen.width : 1920, - maxHeight: screen.height > 1080 ? screen.height : 1080 - }, - optional: [] - }; - if (chromeMediaSource == 'desktop' && !sourceId) { - getSourceId(function () { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); - }); - return; - } - if (chromeMediaSource == 'desktop') { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - } - callback(null, screen_constraints); -} -exports.getScreenConstraints = getScreenConstraints; -exports.isChromeExtensionAvailable = isChromeExtensionAvailable; -exports.getChromeExtensionStatus = getChromeExtensionStatus; -exports.getSourceId = getSourceId; - -},{}],60:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var platform = require("platform"); -var WebRtcStats = (function () { - function WebRtcStats(stream) { - this.stream = stream; - this.webRtcStatsEnabled = false; - this.statsInterval = 1; - this.stats = { - inbound: { - audio: { - bytesReceived: 0, - packetsReceived: 0, - packetsLost: 0 - }, - video: { - bytesReceived: 0, - packetsReceived: 0, - packetsLost: 0, - framesDecoded: 0, - nackCount: 0 - } - }, - outbound: { - audio: { - bytesSent: 0, - packetsSent: 0, - }, - video: { - bytesSent: 0, - packetsSent: 0, - framesEncoded: 0, - nackCount: 0 - } - } - }; - } - WebRtcStats.prototype.isEnabled = function () { - return this.webRtcStatsEnabled; - }; - WebRtcStats.prototype.initWebRtcStats = function () { - var _this = this; - var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); - if (elastestInstrumentation) { - console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - this.webRtcStatsEnabled = true; - var instrumentation_1 = JSON.parse(elastestInstrumentation); - this.statsInterval = instrumentation_1.webrtc.interval; - console.warn('localStorage item: ' + JSON.stringify(instrumentation_1)); - this.webRtcStatsIntervalId = setInterval(function () { - _this.sendStatsToHttpEndpoint(instrumentation_1); - }, this.statsInterval * 1000); - return; - } - console.debug('WebRtc stats not enabled'); - }; - WebRtcStats.prototype.stopWebRtcStats = function () { - if (this.webRtcStatsEnabled) { - clearInterval(this.webRtcStatsIntervalId); - console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - } - }; - WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { - var _this = this; - var sendPost = function (json) { - var http = new XMLHttpRequest(); - var url = instrumentation.webrtc.httpEndpoint; - http.open('POST', url, true); - http.setRequestHeader('Content-type', 'application/json'); - http.onreadystatechange = function () { - if (http.readyState === 4 && http.status === 200) { - console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId); - } - }; - http.send(json); - }; - var f = function (stats) { - if (platform.name.indexOf('Firefox') !== -1) { - stats.forEach(function (stat) { - var json = {}; - if ((stat.type === 'inbound-rtp') && - (stat.nackCount !== null && - stat.isRemote === false && - stat.id.startsWith('inbound') && - stat.remoteId.startsWith('inbound'))) { - var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; - var jit = stat.jitter * 1000; - var metrics = { - bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, - jitter: jit, - packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, - packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval - }; - var units = { - bytesReceived: 'bytes', - jitter: 'ms', - packetsReceived: 'packets', - packetsLost: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; - metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; - units['framesDecoded'] = 'frames'; - units['nackCount'] = 'packets'; - _this.stats.inbound.video.framesDecoded = stat.framesDecoded; - _this.stats.inbound.video.nackCount = stat.nackCount; - } - _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; - _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; - _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - else if ((stat.type === 'outbound-rtp') && - (stat.isRemote === false && - stat.id.toLowerCase().includes('outbound'))) { - var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, - packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval - }; - var units = { - bytesSent: 'bytes', - packetsSent: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; - units['framesEncoded'] = 'frames'; - _this.stats.outbound.video.framesEncoded = stat.framesEncoded; - } - _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; - _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - }); - } - else if (platform.name.indexOf('Chrome') !== -1) { - for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { - var key = _a[_i]; - var stat = stats[key]; - if (stat.type === 'ssrc') { - var json = {}; - if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || - (stat.mediaType === 'video' && 'qpSum' in stat))) { - var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, - jitter: stat.googJitterBufferMs, - packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, - packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval - }; - var units = { - bytesReceived: 'bytes', - jitter: 'ms', - packetsReceived: 'packets', - packetsLost: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; - metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; - units['framesDecoded'] = 'frames'; - units['nackCount'] = 'packets'; - _this.stats.inbound.video.framesDecoded = stat.framesDecoded; - _this.stats.inbound.video.nackCount = stat.googNacksSent; - } - _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; - _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; - _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - else if ('bytesSent' in stat) { - var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, - packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval - }; - var units = { - bytesSent: 'bytes', - packetsSent: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; - units['framesEncoded'] = 'frames'; - _this.stats.outbound.video.framesEncoded = stat.framesEncoded; - } - _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; - _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - } - } - } - }; - this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); }); - }; - WebRtcStats.prototype.standardizeReport = function (response) { - if (platform.name.indexOf('Firefox') !== -1) { - return response; - } - var standardReport = {}; - response.result().forEach(function (report) { - var standardStats = { - id: report.id, - timestamp: report.timestamp, - type: report.type - }; - report.names().forEach(function (name) { - standardStats[name] = report.stat(name); - }); - standardReport[standardStats.id] = standardStats; - }); - return standardReport; - }; - WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) { - var _this = this; - if (platform.name.indexOf('Firefox') !== -1) { - return pc.getStats(null, function (response) { - var report = _this.standardizeReport(response); - successCb(report); - }, failureCb); - } - else if (platform.name.indexOf('Chrome') !== -1) { - return pc.getStats(function (response) { - var report = _this.standardizeReport(response); - successCb(report); - }, null, failureCb); - } - }; - return WebRtcStats; -}()); -exports.WebRtcStats = WebRtcStats; - -},{"platform":9}]},{},[26]) -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL21lcmdlL21lcmdlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi9ncmFtbWFyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL3BhcnNlci5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi93cml0ZXIuanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2FycmF5LWVxdWFscy5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNsYXRvci9saWIvaW5kZXguanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2ludGVyb3AuanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL3RyYW5zZm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91YS1wYXJzZXItanMvc3JjL3VhLXBhcnNlci5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9NYXBwZXIuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvSnNvblJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL1htbFJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcy9XZWJSdGNQZWVyLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8uanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2prQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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IjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qIVxyXG4gKiBAbmFtZSBKYXZhU2NyaXB0L05vZGVKUyBNZXJnZSB2MS4yLjBcclxuICogQGF1dGhvciB5ZWlrb3NcclxuICogQHJlcG9zaXRvcnkgaHR0cHM6Ly9naXRodWIuY29tL3llaWtvcy9qcy5tZXJnZVxyXG5cclxuICogQ29weXJpZ2h0IDIwMTQgeWVpa29zIC0gTUlUIGxpY2Vuc2VcclxuICogaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS95ZWlrb3MvanMubWVyZ2UvbWFzdGVyL0xJQ0VOU0VcclxuICovXHJcblxyXG47KGZ1bmN0aW9uKGlzTm9kZSkge1xyXG5cclxuXHQvKipcclxuXHQgKiBNZXJnZSBvbmUgb3IgbW9yZSBvYmplY3RzIFxyXG5cdCAqIEBwYXJhbSBib29sPyBjbG9uZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCwuLi4gYXJndW1lbnRzXHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0dmFyIFB1YmxpYyA9IGZ1bmN0aW9uKGNsb25lKSB7XHJcblxyXG5cdFx0cmV0dXJuIG1lcmdlKGNsb25lID09PSB0cnVlLCBmYWxzZSwgYXJndW1lbnRzKTtcclxuXHJcblx0fSwgcHVibGljTmFtZSA9ICdtZXJnZSc7XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvciBtb3JlIG9iamVjdHMgcmVjdXJzaXZlbHkgXHJcblx0ICogQHBhcmFtIGJvb2w/IGNsb25lXHJcblx0ICogQHBhcmFtIG1peGVkLC4uLiBhcmd1bWVudHNcclxuXHQgKiBAcmV0dXJuIG9iamVjdFxyXG5cdCAqL1xyXG5cclxuXHRQdWJsaWMucmVjdXJzaXZlID0gZnVuY3Rpb24oY2xvbmUpIHtcclxuXHJcblx0XHRyZXR1cm4gbWVyZ2UoY2xvbmUgPT09IHRydWUsIHRydWUsIGFyZ3VtZW50cyk7XHJcblxyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIENsb25lIHRoZSBpbnB1dCByZW1vdmluZyBhbnkgcmVmZXJlbmNlXHJcblx0ICogQHBhcmFtIG1peGVkIGlucHV0XHJcblx0ICogQHJldHVybiBtaXhlZFxyXG5cdCAqL1xyXG5cclxuXHRQdWJsaWMuY2xvbmUgPSBmdW5jdGlvbihpbnB1dCkge1xyXG5cclxuXHRcdHZhciBvdXRwdXQgPSBpbnB1dCxcclxuXHRcdFx0dHlwZSA9IHR5cGVPZihpbnB1dCksXHJcblx0XHRcdGluZGV4LCBzaXplO1xyXG5cclxuXHRcdGlmICh0eXBlID09PSAnYXJyYXknKSB7XHJcblxyXG5cdFx0XHRvdXRwdXQgPSBbXTtcclxuXHRcdFx0c2l6ZSA9IGlucHV0Lmxlbmd0aDtcclxuXHJcblx0XHRcdGZvciAoaW5kZXg9MDtpbmRleDxzaXplOysraW5kZXgpXHJcblxyXG5cdFx0XHRcdG91dHB1dFtpbmRleF0gPSBQdWJsaWMuY2xvbmUoaW5wdXRbaW5kZXhdKTtcclxuXHJcblx0XHR9IGVsc2UgaWYgKHR5cGUgPT09ICdvYmplY3QnKSB7XHJcblxyXG5cdFx0XHRvdXRwdXQgPSB7fTtcclxuXHJcblx0XHRcdGZvciAoaW5kZXggaW4gaW5wdXQpXHJcblxyXG5cdFx0XHRcdG91dHB1dFtpbmRleF0gPSBQdWJsaWMuY2xvbmUoaW5wdXRbaW5kZXhdKTtcclxuXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIG91dHB1dDtcclxuXHJcblx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogTWVyZ2UgdHdvIG9iamVjdHMgcmVjdXJzaXZlbHlcclxuXHQgKiBAcGFyYW0gbWl4ZWQgaW5wdXRcclxuXHQgKiBAcGFyYW0gbWl4ZWQgZXh0ZW5kXHJcblx0ICogQHJldHVybiBtaXhlZFxyXG5cdCAqL1xyXG5cclxuXHRmdW5jdGlvbiBtZXJnZV9yZWN1cnNpdmUoYmFzZSwgZXh0ZW5kKSB7XHJcblxyXG5cdFx0aWYgKHR5cGVPZihiYXNlKSAhPT0gJ29iamVjdCcpXHJcblxyXG5cdFx0XHRyZXR1cm4gZXh0ZW5kO1xyXG5cclxuXHRcdGZvciAodmFyIGtleSBpbiBleHRlbmQpIHtcclxuXHJcblx0XHRcdGlmICh0eXBlT2YoYmFzZVtrZXldKSA9PT0gJ29iamVjdCcgJiYgdHlwZU9mKGV4dGVuZFtrZXldKSA9PT0gJ29iamVjdCcpIHtcclxuXHJcblx0XHRcdFx0YmFzZVtrZXldID0gbWVyZ2VfcmVjdXJzaXZlKGJhc2Vba2V5XSwgZXh0ZW5kW2tleV0pO1xyXG5cclxuXHRcdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdFx0YmFzZVtrZXldID0gZXh0ZW5kW2tleV07XHJcblxyXG5cdFx0XHR9XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBiYXNlO1xyXG5cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvciBtb3JlIG9iamVjdHNcclxuXHQgKiBAcGFyYW0gYm9vbCBjbG9uZVxyXG5cdCAqIEBwYXJhbSBib29sIHJlY3Vyc2l2ZVxyXG5cdCAqIEBwYXJhbSBhcnJheSBhcmd2XHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0ZnVuY3Rpb24gbWVyZ2UoY2xvbmUsIHJlY3Vyc2l2ZSwgYXJndikge1xyXG5cclxuXHRcdHZhciByZXN1bHQgPSBhcmd2WzBdLFxyXG5cdFx0XHRzaXplID0gYXJndi5sZW5ndGg7XHJcblxyXG5cdFx0aWYgKGNsb25lIHx8IHR5cGVPZihyZXN1bHQpICE9PSAnb2JqZWN0JylcclxuXHJcblx0XHRcdHJlc3VsdCA9IHt9O1xyXG5cclxuXHRcdGZvciAodmFyIGluZGV4PTA7aW5kZXg8c2l6ZTsrK2luZGV4KSB7XHJcblxyXG5cdFx0XHR2YXIgaXRlbSA9IGFyZ3ZbaW5kZXhdLFxyXG5cclxuXHRcdFx0XHR0eXBlID0gdHlwZU9mKGl0ZW0pO1xyXG5cclxuXHRcdFx0aWYgKHR5cGUgIT09ICdvYmplY3QnKSBjb250aW51ZTtcclxuXHJcblx0XHRcdGZvciAodmFyIGtleSBpbiBpdGVtKSB7XHJcblxyXG5cdFx0XHRcdHZhciBzaXRlbSA9IGNsb25lID8gUHVibGljLmNsb25lKGl0ZW1ba2V5XSkgOiBpdGVtW2tleV07XHJcblxyXG5cdFx0XHRcdGlmIChyZWN1cnNpdmUpIHtcclxuXHJcblx0XHRcdFx0XHRyZXN1bHRba2V5XSA9IG1lcmdlX3JlY3Vyc2l2ZShyZXN1bHRba2V5XSwgc2l0ZW0pO1xyXG5cclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cclxuXHRcdFx0XHRcdHJlc3VsdFtrZXldID0gc2l0ZW07XHJcblxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdH1cclxuXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHJlc3VsdDtcclxuXHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgdHlwZSBvZiB2YXJpYWJsZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCBpbnB1dFxyXG5cdCAqIEByZXR1cm4gc3RyaW5nXHJcblx0ICpcclxuXHQgKiBAc2VlIGh0dHA6Ly9qc3BlcmYuY29tL3R5cGVvZnZhclxyXG5cdCAqL1xyXG5cclxuXHRmdW5jdGlvbiB0eXBlT2YoaW5wdXQpIHtcclxuXHJcblx0XHRyZXR1cm4gKHt9KS50b1N0cmluZy5jYWxsKGlucHV0KS5zbGljZSg4LCAtMSkudG9Mb3dlckNhc2UoKTtcclxuXHJcblx0fVxyXG5cclxuXHRpZiAoaXNOb2RlKSB7XHJcblxyXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBQdWJsaWM7XHJcblxyXG5cdH0gZWxzZSB7XHJcblxyXG5cdFx0d2luZG93W3B1YmxpY05hbWVdID0gUHVibGljO1xyXG5cclxuXHR9XHJcblxyXG59KSh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyk7IiwiLyoqXG4gICMgbm9ybWFsaWNlXG5cbiAgTm9ybWFsaXplIGFuIGljZSBzZXJ2ZXIgY29uZmlndXJhdGlvbiBvYmplY3QgKG9yIHBsYWluIG9sZCBzdHJpbmcpIGludG8gYSBmb3JtYXRcbiAgdGhhdCBpcyB1c2FibGUgaW4gYWxsIGJyb3dzZXJzIHN1cHBvcnRpbmcgV2ViUlRDLiAgUHJpbWFyaWx5IHRoaXMgbW9kdWxlIGlzIGRlc2lnbmVkXG4gIHRvIGhlbHAgd2l0aCB0aGUgdHJhbnNpdGlvbiBvZiB0aGUgYHVybGAgYXR0cmlidXRlIG9mIHRoZSBjb25maWd1cmF0aW9uIG9iamVjdCB0b1xuICB0aGUgYHVybHNgIGF0dHJpYnV0ZS5cblxuICAjIyBFeGFtcGxlIFVzYWdlXG5cbiAgPDw8IGV4YW1wbGVzL3NpbXBsZS5qc1xuXG4qKi9cblxudmFyIHByb3RvY29scyA9IFtcbiAgJ3N0dW46JyxcbiAgJ3R1cm46J1xuXTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpbnB1dCkge1xuICB2YXIgdXJsID0gKGlucHV0IHx8IHt9KS51cmwgfHwgaW5wdXQ7XG4gIHZhciBwcm90b2NvbDtcbiAgdmFyIHBhcnRzO1xuICB2YXIgb3V0cHV0ID0ge307XG5cbiAgLy8gaWYgd2UgZG9uJ3QgaGF2ZSBhIHN0cmluZyB1cmwsIHRoZW4gYWxsb3cgdGhlIGlucHV0IHRvIHBhc3N0aHJvdWdoXG4gIGlmICh0eXBlb2YgdXJsICE9ICdzdHJpbmcnICYmICghICh1cmwgaW5zdGFuY2VvZiBTdHJpbmcpKSkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIC8vIHRyaW0gdGhlIHVybCBzdHJpbmcsIGFuZCBjb252ZXJ0IHRvIGFuIGFycmF5XG4gIHVybCA9IHVybC50cmltKCk7XG5cbiAgLy8gaWYgdGhlIHByb3RvY29sIGlzIG5vdCBrbm93biwgdGhlbiBwYXNzdGhyb3VnaFxuICBwcm90b2NvbCA9IHByb3RvY29sc1twcm90b2NvbHMuaW5kZXhPZih1cmwuc2xpY2UoMCwgNSkpXTtcbiAgaWYgKCEgcHJvdG9jb2wpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyBub3cgbGV0J3MgYXR0YWNrIHRoZSByZW1haW5pbmcgdXJsIHBhcnRzXG4gIHVybCA9IHVybC5zbGljZSg1KTtcbiAgcGFydHMgPSB1cmwuc3BsaXQoJ0AnKTtcblxuICBvdXRwdXQudXNlcm5hbWUgPSBpbnB1dC51c2VybmFtZTtcbiAgb3V0cHV0LmNyZWRlbnRpYWwgPSBpbnB1dC5jcmVkZW50aWFsO1xuICAvLyBpZiB3ZSBoYXZlIGFuIGF1dGhlbnRpY2F0aW9uIHBhcnQsIHRoZW4gc2V0IHRoZSBjcmVkZW50aWFsc1xuICBpZiAocGFydHMubGVuZ3RoID4gMSkge1xuICAgIHVybCA9IHBhcnRzWzFdO1xuICAgIHBhcnRzID0gcGFydHNbMF0uc3BsaXQoJzonKTtcblxuICAgIC8vIGFkZCB0aGUgb3V0cHV0IGNyZWRlbnRpYWwgYW5kIHVzZXJuYW1lXG4gICAgb3V0cHV0LnVzZXJuYW1lID0gcGFydHNbMF07XG4gICAgb3V0cHV0LmNyZWRlbnRpYWwgPSAoaW5wdXQgfHwge30pLmNyZWRlbnRpYWwgfHwgcGFydHNbMV0gfHwgJyc7XG4gIH1cblxuICBvdXRwdXQudXJsID0gcHJvdG9jb2wgKyB1cmw7XG4gIG91dHB1dC51cmxzID0gWyBvdXRwdXQudXJsIF07XG5cbiAgcmV0dXJuIG91dHB1dDtcbn07XG4iLCIvKiFcbiAqIFBsYXRmb3JtLmpzIDxodHRwczovL210aHMuYmUvcGxhdGZvcm0+XG4gKiBDb3B5cmlnaHQgMjAxNC0yMDE4IEJlbmphbWluIFRhbiA8aHR0cHM6Ly9ibmptbnQ0bi5ub3cuc2gvPlxuICogQ29weXJpZ2h0IDIwMTEtMjAxMyBKb2huLURhdmlkIERhbHRvbiA8aHR0cDovL2FsbHlvdWNhbmxlZXQuY29tLz5cbiAqIEF2YWlsYWJsZSB1bmRlciBNSVQgbGljZW5zZSA8aHR0cHM6Ly9tdGhzLmJlL21pdD5cbiAqL1xuOyhmdW5jdGlvbigpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVybWluZSBpZiB2YWx1ZXMgYXJlIG9mIHRoZSBsYW5ndWFnZSB0eXBlIGBPYmplY3RgLiAqL1xuICB2YXIgb2JqZWN0VHlwZXMgPSB7XG4gICAgJ2Z1bmN0aW9uJzogdHJ1ZSxcbiAgICAnb2JqZWN0JzogdHJ1ZVxuICB9O1xuXG4gIC8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgcm9vdCA9IChvYmplY3RUeXBlc1t0eXBlb2Ygd2luZG93XSAmJiB3aW5kb3cpIHx8IHRoaXM7XG5cbiAgLyoqIEJhY2t1cCBwb3NzaWJsZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgb2xkUm9vdCA9IHJvb3Q7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBleHBvcnRzYC4gKi9cbiAgdmFyIGZyZWVFeHBvcnRzID0gb2JqZWN0VHlwZXNbdHlwZW9mIGV4cG9ydHNdICYmIGV4cG9ydHM7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBtb2R1bGVgLiAqL1xuICB2YXIgZnJlZU1vZHVsZSA9IG9iamVjdFR5cGVzW3R5cGVvZiBtb2R1bGVdICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzIG9yIEJyb3dzZXJpZmllZCBjb2RlIGFuZCB1c2UgaXQgYXMgYHJvb3RgLiAqL1xuICB2YXIgZnJlZUdsb2JhbCA9IGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUgJiYgdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWw7XG4gIGlmIChmcmVlR2xvYmFsICYmIChmcmVlR2xvYmFsLmdsb2JhbCA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLndpbmRvdyA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLnNlbGYgPT09IGZyZWVHbG9iYWwpKSB7XG4gICAgcm9vdCA9IGZyZWVHbG9iYWw7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBhcyB0aGUgbWF4aW11bSBsZW5ndGggb2YgYW4gYXJyYXktbGlrZSBvYmplY3QuXG4gICAqIFNlZSB0aGUgW0VTNiBzcGVjXShodHRwOi8vcGVvcGxlLm1vemlsbGEub3JnL35qb3JlbmRvcmZmL2VzNi1kcmFmdC5odG1sI3NlYy10b2xlbmd0aClcbiAgICogZm9yIG1vcmUgZGV0YWlscy5cbiAgICovXG4gIHZhciBtYXhTYWZlSW50ZWdlciA9IE1hdGgucG93KDIsIDUzKSAtIDE7XG5cbiAgLyoqIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBkZXRlY3QgT3BlcmEuICovXG4gIHZhciByZU9wZXJhID0gL1xcYk9wZXJhLztcblxuICAvKiogUG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHRoaXNCaW5kaW5nID0gdGhpcztcblxuICAvKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xuICB2YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4gIC8qKiBVc2VkIHRvIGNoZWNrIGZvciBvd24gcHJvcGVydGllcyBvZiBhbiBvYmplY3QuICovXG4gIHZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4gIC8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIHZhbHVlcy4gKi9cbiAgdmFyIHRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENhcGl0YWxpemVzIGEgc3RyaW5nIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGNhcGl0YWxpemVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gU3RyaW5nKHN0cmluZyk7XG4gICAgcmV0dXJuIHN0cmluZy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0cmluZy5zbGljZSgxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHV0aWxpdHkgZnVuY3Rpb24gdG8gY2xlYW4gdXAgdGhlIE9TIG5hbWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcyBUaGUgT1MgbmFtZSB0byBjbGVhbiB1cC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwYXR0ZXJuXSBBIGBSZWdFeHBgIHBhdHRlcm4gbWF0Y2hpbmcgdGhlIE9TIG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbGFiZWxdIEEgbGFiZWwgZm9yIHRoZSBPUy5cbiAgICovXG4gIGZ1bmN0aW9uIGNsZWFudXBPUyhvcywgcGF0dGVybiwgbGFiZWwpIHtcbiAgICAvLyBQbGF0Zm9ybSB0b2tlbnMgYXJlIGRlZmluZWQgYXQ6XG4gICAgLy8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgLy8gaHR0cDovL3dlYi5hcmNoaXZlLm9yZy93ZWIvMjAwODExMjIwNTM5NTAvaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgdmFyIGRhdGEgPSB7XG4gICAgICAnMTAuMCc6ICcxMCcsXG4gICAgICAnNi40JzogICcxMCBUZWNobmljYWwgUHJldmlldycsXG4gICAgICAnNi4zJzogICc4LjEnLFxuICAgICAgJzYuMic6ICAnOCcsXG4gICAgICAnNi4xJzogICdTZXJ2ZXIgMjAwOCBSMiAvIDcnLFxuICAgICAgJzYuMCc6ICAnU2VydmVyIDIwMDggLyBWaXN0YScsXG4gICAgICAnNS4yJzogICdTZXJ2ZXIgMjAwMyAvIFhQIDY0LWJpdCcsXG4gICAgICAnNS4xJzogICdYUCcsXG4gICAgICAnNS4wMSc6ICcyMDAwIFNQMScsXG4gICAgICAnNS4wJzogICcyMDAwJyxcbiAgICAgICc0LjAnOiAgJ05UJyxcbiAgICAgICc0LjkwJzogJ01FJ1xuICAgIH07XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgdmVyc2lvbiBmcm9tIHBsYXRmb3JtIHRva2Vucy5cbiAgICBpZiAocGF0dGVybiAmJiBsYWJlbCAmJiAvXldpbi9pLnRlc3Qob3MpICYmICEvXldpbmRvd3MgUGhvbmUgL2kudGVzdChvcykgJiZcbiAgICAgICAgKGRhdGEgPSBkYXRhWy9bXFxkLl0rJC8uZXhlYyhvcyldKSkge1xuICAgICAgb3MgPSAnV2luZG93cyAnICsgZGF0YTtcbiAgICB9XG4gICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgb3MgPSBTdHJpbmcob3MpO1xuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwpIHtcbiAgICAgIG9zID0gb3MucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgbGFiZWwpO1xuICAgIH1cblxuICAgIG9zID0gZm9ybWF0KFxuICAgICAgb3MucmVwbGFjZSgvIGNlJC9pLCAnIENFJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYmhwdy9pLCAnd2ViJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hY2ludG9zaFxcYi8sICdNYWMgT1MnKVxuICAgICAgICAucmVwbGFjZSgvX1Bvd2VyUENcXGIvaSwgJyBPUycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoT1MgWCkgW14gXFxkXSsvaSwgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hYyAoT1MgWClcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFwvKFxcZCkvLCAnICQxJylcbiAgICAgICAgLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICAucmVwbGFjZSgvKD86IEJlUEN8WyAuXSpmY1sgXFxkLl0rKSQvaSwgJycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJ4ODZcXC42NFxcYi9naSwgJ3g4Nl82NCcpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoV2luZG93cyBQaG9uZSkgT1NcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKENocm9tZSBPUyBcXHcrKSBbXFxkLl0rXFxiLywgJyQxJylcbiAgICAgICAgLnNwbGl0KCcgb24gJylbMF1cbiAgICApO1xuXG4gICAgcmV0dXJuIG9zO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGl0ZXJhdGlvbiB1dGlsaXR5IGZvciBhcnJheXMgYW5kIG9iamVjdHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIGVhY2gob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBvYmplY3QgPyBvYmplY3QubGVuZ3RoIDogMDtcblxuICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInICYmIGxlbmd0aCA+IC0xICYmIGxlbmd0aCA8PSBtYXhTYWZlSW50ZWdlcikge1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2luZGV4XSwgaW5kZXgsIG9iamVjdCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvck93bihvYmplY3QsIGNhbGxiYWNrKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJpbSBhbmQgY29uZGl0aW9uYWxseSBjYXBpdGFsaXplIHN0cmluZyB2YWx1ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBmb3JtYXQuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBmb3JtYXR0ZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gZm9ybWF0KHN0cmluZykge1xuICAgIHN0cmluZyA9IHRyaW0oc3RyaW5nKTtcbiAgICByZXR1cm4gL14oPzp3ZWJPU3xpKD86T1N8UCkpLy50ZXN0KHN0cmluZylcbiAgICAgID8gc3RyaW5nXG4gICAgICA6IGNhcGl0YWxpemUoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJdGVyYXRlcyBvdmVyIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzLCBleGVjdXRpbmcgdGhlIGBjYWxsYmFja2AgZm9yIGVhY2guXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBleGVjdXRlZCBwZXIgb3duIHByb3BlcnR5LlxuICAgKi9cbiAgZnVuY3Rpb24gZm9yT3duKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2tleV0sIGtleSwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgaW50ZXJuYWwgYFtbQ2xhc3NdXWAgb2YgYSB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBgW1tDbGFzc11dYC5cbiAgICovXG4gIGZ1bmN0aW9uIGdldENsYXNzT2YodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPT0gbnVsbFxuICAgICAgPyBjYXBpdGFsaXplKHZhbHVlKVxuICAgICAgOiB0b1N0cmluZy5jYWxsKHZhbHVlKS5zbGljZSg4LCAtMSk7XG4gIH1cblxuICAvKipcbiAgICogSG9zdCBvYmplY3RzIGNhbiByZXR1cm4gdHlwZSB2YWx1ZXMgdGhhdCBhcmUgZGlmZmVyZW50IGZyb20gdGhlaXIgYWN0dWFsXG4gICAqIGRhdGEgdHlwZS4gVGhlIG9iamVjdHMgd2UgYXJlIGNvbmNlcm5lZCB3aXRoIHVzdWFsbHkgcmV0dXJuIG5vbi1wcmltaXRpdmVcbiAgICogdHlwZXMgb2YgXCJvYmplY3RcIiwgXCJmdW5jdGlvblwiLCBvciBcInVua25vd25cIi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSBvYmplY3QgVGhlIG93bmVyIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3BlcnR5IFRoZSBwcm9wZXJ0eSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyBhIG5vbi1wcmltaXRpdmUsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGlzSG9zdFR5cGUob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgIHZhciB0eXBlID0gb2JqZWN0ICE9IG51bGwgPyB0eXBlb2Ygb2JqZWN0W3Byb3BlcnR5XSA6ICdudW1iZXInO1xuICAgIHJldHVybiAhL14oPzpib29sZWFufG51bWJlcnxzdHJpbmd8dW5kZWZpbmVkKSQvLnRlc3QodHlwZSkgJiZcbiAgICAgICh0eXBlID09ICdvYmplY3QnID8gISFvYmplY3RbcHJvcGVydHldIDogdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUHJlcGFyZXMgYSBzdHJpbmcgZm9yIHVzZSBpbiBhIGBSZWdFeHBgIGJ5IG1ha2luZyBoeXBoZW5zIGFuZCBzcGFjZXMgb3B0aW9uYWwuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBxdWFsaWZ5LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgcXVhbGlmaWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIHF1YWxpZnkoc3RyaW5nKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoLyhbIC1dKSg/ISQpL2csICckMT8nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGJhcmUtYm9uZXMgYEFycmF5I3JlZHVjZWAgbGlrZSB1dGlsaXR5IGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHsqfSBUaGUgYWNjdW11bGF0ZWQgcmVzdWx0LlxuICAgKi9cbiAgZnVuY3Rpb24gcmVkdWNlKGFycmF5LCBjYWxsYmFjaykge1xuICAgIHZhciBhY2N1bXVsYXRvciA9IG51bGw7XG4gICAgZWFjaChhcnJheSwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICBhY2N1bXVsYXRvciA9IGNhbGxiYWNrKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGFycmF5KTtcbiAgICB9KTtcbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIGZyb20gYSBzdHJpbmcuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byB0cmltLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgdHJpbW1lZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiB0cmltKHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC9eICt8ICskL2csICcnKTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IHBsYXRmb3JtIG9iamVjdC5cbiAgICpcbiAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAqIEBwYXJhbSB7T2JqZWN0fHN0cmluZ30gW3VhPW5hdmlnYXRvci51c2VyQWdlbnRdIFRoZSB1c2VyIGFnZW50IHN0cmluZyBvclxuICAgKiAgY29udGV4dCBvYmplY3QuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IEEgcGxhdGZvcm0gb2JqZWN0LlxuICAgKi9cbiAgZnVuY3Rpb24gcGFyc2UodWEpIHtcblxuICAgIC8qKiBUaGUgZW52aXJvbm1lbnQgY29udGV4dCBvYmplY3QuICovXG4gICAgdmFyIGNvbnRleHQgPSByb290O1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGEgY3VzdG9tIGNvbnRleHQgaXMgcHJvdmlkZWQuICovXG4gICAgdmFyIGlzQ3VzdG9tQ29udGV4dCA9IHVhICYmIHR5cGVvZiB1YSA9PSAnb2JqZWN0JyAmJiBnZXRDbGFzc09mKHVhKSAhPSAnU3RyaW5nJztcblxuICAgIC8vIEp1Z2dsZSBhcmd1bWVudHMuXG4gICAgaWYgKGlzQ3VzdG9tQ29udGV4dCkge1xuICAgICAgY29udGV4dCA9IHVhO1xuICAgICAgdWEgPSBudWxsO1xuICAgIH1cblxuICAgIC8qKiBCcm93c2VyIG5hdmlnYXRvciBvYmplY3QuICovXG4gICAgdmFyIG5hdiA9IGNvbnRleHQubmF2aWdhdG9yIHx8IHt9O1xuXG4gICAgLyoqIEJyb3dzZXIgdXNlciBhZ2VudCBzdHJpbmcuICovXG4gICAgdmFyIHVzZXJBZ2VudCA9IG5hdi51c2VyQWdlbnQgfHwgJyc7XG5cbiAgICB1YSB8fCAodWEgPSB1c2VyQWdlbnQpO1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGB0aGlzQmluZGluZ2AgaXMgdGhlIFtNb2R1bGVTY29wZV0uICovXG4gICAgdmFyIGlzTW9kdWxlU2NvcGUgPSBpc0N1c3RvbUNvbnRleHQgfHwgdGhpc0JpbmRpbmcgPT0gb2xkUm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGRldGVjdCBpZiBicm93c2VyIGlzIGxpa2UgQ2hyb21lLiAqL1xuICAgIHZhciBsaWtlQ2hyb21lID0gaXNDdXN0b21Db250ZXh0XG4gICAgICA/ICEhbmF2Lmxpa2VDaHJvbWVcbiAgICAgIDogL1xcYkNocm9tZVxcYi8udGVzdCh1YSkgJiYgIS9pbnRlcm5hbHxcXG4vaS50ZXN0KHRvU3RyaW5nLnRvU3RyaW5nKCkpO1xuXG4gICAgLyoqIEludGVybmFsIGBbW0NsYXNzXV1gIHZhbHVlIHNob3J0Y3V0cy4gKi9cbiAgICB2YXIgb2JqZWN0Q2xhc3MgPSAnT2JqZWN0JyxcbiAgICAgICAgYWlyUnVudGltZUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnU2NyaXB0QnJpZGdpbmdQcm94eU9iamVjdCcsXG4gICAgICAgIGVudmlyb0NsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnRW52aXJvbm1lbnQnLFxuICAgICAgICBqYXZhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIGNvbnRleHQuamF2YSkgPyAnSmF2YVBhY2thZ2UnIDogZ2V0Q2xhc3NPZihjb250ZXh0LmphdmEpLFxuICAgICAgICBwaGFudG9tQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdSdW50aW1lT2JqZWN0JztcblxuICAgIC8qKiBEZXRlY3QgSmF2YSBlbnZpcm9ubWVudHMuICovXG4gICAgdmFyIGphdmEgPSAvXFxiSmF2YS8udGVzdChqYXZhQ2xhc3MpICYmIGNvbnRleHQuamF2YTtcblxuICAgIC8qKiBEZXRlY3QgUmhpbm8uICovXG4gICAgdmFyIHJoaW5vID0gamF2YSAmJiBnZXRDbGFzc09mKGNvbnRleHQuZW52aXJvbm1lbnQpID09IGVudmlyb0NsYXNzO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBhbHBoYS4gKi9cbiAgICB2YXIgYWxwaGEgPSBqYXZhID8gJ2EnIDogJ1xcdTAzYjEnO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBiZXRhLiAqL1xuICAgIHZhciBiZXRhID0gamF2YSA/ICdiJyA6ICdcXHUwM2IyJztcblxuICAgIC8qKiBCcm93c2VyIGRvY3VtZW50IG9iamVjdC4gKi9cbiAgICB2YXIgZG9jID0gY29udGV4dC5kb2N1bWVudCB8fCB7fTtcblxuICAgIC8qKlxuICAgICAqIERldGVjdCBPcGVyYSBicm93c2VyIChQcmVzdG8tYmFzZWQpLlxuICAgICAqIGh0dHA6Ly93d3cuaG93dG9jcmVhdGUuY28udWsvb3BlcmFTdHVmZi9vcGVyYU9iamVjdC5odG1sXG4gICAgICogaHR0cDovL2Rldi5vcGVyYS5jb20vYXJ0aWNsZXMvdmlldy9vcGVyYS1taW5pLXdlYi1jb250ZW50LWF1dGhvcmluZy1ndWlkZWxpbmVzLyNvcGVyYW1pbmlcbiAgICAgKi9cbiAgICB2YXIgb3BlcmEgPSBjb250ZXh0Lm9wZXJhbWluaSB8fCBjb250ZXh0Lm9wZXJhO1xuXG4gICAgLyoqIE9wZXJhIGBbW0NsYXNzXV1gLiAqL1xuICAgIHZhciBvcGVyYUNsYXNzID0gcmVPcGVyYS50ZXN0KG9wZXJhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIG9wZXJhKSA/IG9wZXJhWydbW0NsYXNzXV0nXSA6IGdldENsYXNzT2Yob3BlcmEpKVxuICAgICAgPyBvcGVyYUNsYXNzXG4gICAgICA6IChvcGVyYSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqIFRlbXBvcmFyeSB2YXJpYWJsZSB1c2VkIG92ZXIgdGhlIHNjcmlwdCdzIGxpZmV0aW1lLiAqL1xuICAgIHZhciBkYXRhO1xuXG4gICAgLyoqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlLiAqL1xuICAgIHZhciBhcmNoID0gdWE7XG5cbiAgICAvKiogUGxhdGZvcm0gZGVzY3JpcHRpb24gYXJyYXkuICovXG4gICAgdmFyIGRlc2NyaXB0aW9uID0gW107XG5cbiAgICAvKiogUGxhdGZvcm0gYWxwaGEvYmV0YSBpbmRpY2F0b3IuICovXG4gICAgdmFyIHByZXJlbGVhc2UgPSBudWxsO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSB0aGF0IGVudmlyb25tZW50IGZlYXR1cmVzIHNob3VsZCBiZSB1c2VkIHRvIHJlc29sdmUgdGhlIHBsYXRmb3JtLiAqL1xuICAgIHZhciB1c2VGZWF0dXJlcyA9IHVhID09IHVzZXJBZ2VudDtcblxuICAgIC8qKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLiAqL1xuICAgIHZhciB2ZXJzaW9uID0gdXNlRmVhdHVyZXMgJiYgb3BlcmEgJiYgdHlwZW9mIG9wZXJhLnZlcnNpb24gPT0gJ2Z1bmN0aW9uJyAmJiBvcGVyYS52ZXJzaW9uKCk7XG5cbiAgICAvKiogQSBmbGFnIHRvIGluZGljYXRlIGlmIHRoZSBPUyBlbmRzIHdpdGggXCIvIFZlcnNpb25cIiAqL1xuICAgIHZhciBpc1NwZWNpYWxDYXNlZE9TO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBsYXlvdXQgZW5naW5lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbGF5b3V0ID0gZ2V0TGF5b3V0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0VkZ2VIVE1MJywgJ3BhdHRlcm4nOiAnRWRnZScgfSxcbiAgICAgICdUcmlkZW50JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1dlYktpdCcsICdwYXR0ZXJuJzogJ0FwcGxlV2ViS2l0JyB9LFxuICAgICAgJ2lDYWInLFxuICAgICAgJ1ByZXN0bycsXG4gICAgICAnTmV0RnJvbnQnLFxuICAgICAgJ1Rhc21hbicsXG4gICAgICAnS0hUTUwnLFxuICAgICAgJ0dlY2tvJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBicm93c2VyIG5hbWVzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBuYW1lID0gZ2V0TmFtZShbXG4gICAgICAnQWRvYmUgQUlSJyxcbiAgICAgICdBcm9yYScsXG4gICAgICAnQXZhbnQgQnJvd3NlcicsXG4gICAgICAnQnJlYWNoJyxcbiAgICAgICdDYW1pbm8nLFxuICAgICAgJ0VsZWN0cm9uJyxcbiAgICAgICdFcGlwaGFueScsXG4gICAgICAnRmVubmVjJyxcbiAgICAgICdGbG9jaycsXG4gICAgICAnR2FsZW9uJyxcbiAgICAgICdHcmVlbkJyb3dzZXInLFxuICAgICAgJ2lDYWInLFxuICAgICAgJ0ljZXdlYXNlbCcsXG4gICAgICAnSy1NZWxlb24nLFxuICAgICAgJ0tvbnF1ZXJvcicsXG4gICAgICAnTHVuYXNjYXBlJyxcbiAgICAgICdNYXh0aG9uJyxcbiAgICAgIHsgJ2xhYmVsJzogJ01pY3Jvc29mdCBFZGdlJywgJ3BhdHRlcm4nOiAnRWRnZScgfSxcbiAgICAgICdNaWRvcmknLFxuICAgICAgJ05vb2sgQnJvd3NlcicsXG4gICAgICAnUGFsZU1vb24nLFxuICAgICAgJ1BoYW50b21KUycsXG4gICAgICAnUmF2ZW4nLFxuICAgICAgJ1Jla29ucScsXG4gICAgICAnUm9ja01lbHQnLFxuICAgICAgeyAnbGFiZWwnOiAnU2Ftc3VuZyBJbnRlcm5ldCcsICdwYXR0ZXJuJzogJ1NhbXN1bmdCcm93c2VyJyB9LFxuICAgICAgJ1NlYU1vbmtleScsXG4gICAgICB7ICdsYWJlbCc6ICdTaWxrJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ1NsZWlwbmlyJyxcbiAgICAgICdTbGltQnJvd3NlcicsXG4gICAgICB7ICdsYWJlbCc6ICdTUldhcmUgSXJvbicsICdwYXR0ZXJuJzogJ0lyb24nIH0sXG4gICAgICAnU3VucmlzZScsXG4gICAgICAnU3dpZnRmb3gnLFxuICAgICAgJ1dhdGVyZm94JyxcbiAgICAgICdXZWJQb3NpdGl2ZScsXG4gICAgICAnT3BlcmEgTWluaScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYSBNaW5pJywgJ3BhdHRlcm4nOiAnT1BpT1MnIH0sXG4gICAgICAnT3BlcmEnLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEnLCAncGF0dGVybic6ICdPUFInIH0sXG4gICAgICAnQ2hyb21lJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBNb2JpbGUnLCAncGF0dGVybic6ICcoPzpDcmlPU3xDck1vKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0ZpcmVmb3gnLCAncGF0dGVybic6ICcoPzpGaXJlZm94fE1pbmVmaWVsZCknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94IGZvciBpT1MnLCAncGF0dGVybic6ICdGeGlPUycgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0lFJywgJ3BhdHRlcm4nOiAnSUVNb2JpbGUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ01TSUUnIH0sXG4gICAgICAnU2FmYXJpJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBwcm9kdWN0cyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgcHJvZHVjdCA9IGdldFByb2R1Y3QoW1xuICAgICAgeyAnbGFiZWwnOiAnQmxhY2tCZXJyeScsICdwYXR0ZXJuJzogJ0JCMTAnIH0sXG4gICAgICAnQmxhY2tCZXJyeScsXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUycsICdwYXR0ZXJuJzogJ0dULUk5MDAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMyJywgJ3BhdHRlcm4nOiAnR1QtSTkxMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzMnLCAncGF0dGVybic6ICdHVC1JOTMwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNCcsICdwYXR0ZXJuJzogJ0dULUk5NTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM1JywgJ3BhdHRlcm4nOiAnU00tRzkwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNicsICdwYXR0ZXJuJzogJ1NNLUc5MjAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYgRWRnZScsICdwYXR0ZXJuJzogJ1NNLUc5MjUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzcnLCAncGF0dGVybic6ICdTTS1HOTMwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTM1JyB9LFxuICAgICAgJ0dvb2dsZSBUVicsXG4gICAgICAnTHVtaWEnLFxuICAgICAgJ2lQYWQnLFxuICAgICAgJ2lQb2QnLFxuICAgICAgJ2lQaG9uZScsXG4gICAgICAnS2luZGxlJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0tpbmRsZSBGaXJlJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ05leHVzJyxcbiAgICAgICdOb29rJyxcbiAgICAgICdQbGF5Qm9vaycsXG4gICAgICAnUGxheVN0YXRpb24gVml0YScsXG4gICAgICAnUGxheVN0YXRpb24nLFxuICAgICAgJ1RvdWNoUGFkJyxcbiAgICAgICdUcmFuc2Zvcm1lcicsXG4gICAgICB7ICdsYWJlbCc6ICdXaWkgVScsICdwYXR0ZXJuJzogJ1dpaVUnIH0sXG4gICAgICAnV2lpJyxcbiAgICAgICdYYm94IE9uZScsXG4gICAgICB7ICdsYWJlbCc6ICdYYm94IDM2MCcsICdwYXR0ZXJuJzogJ1hib3gnIH0sXG4gICAgICAnWG9vbSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgbWFudWZhY3R1cmVycy4gKi9cbiAgICB2YXIgbWFudWZhY3R1cmVyID0gZ2V0TWFudWZhY3R1cmVyKHtcbiAgICAgICdBcHBsZSc6IHsgJ2lQYWQnOiAxLCAnaVBob25lJzogMSwgJ2lQb2QnOiAxIH0sXG4gICAgICAnQXJjaG9zJzoge30sXG4gICAgICAnQW1hem9uJzogeyAnS2luZGxlJzogMSwgJ0tpbmRsZSBGaXJlJzogMSB9LFxuICAgICAgJ0FzdXMnOiB7ICdUcmFuc2Zvcm1lcic6IDEgfSxcbiAgICAgICdCYXJuZXMgJiBOb2JsZSc6IHsgJ05vb2snOiAxIH0sXG4gICAgICAnQmxhY2tCZXJyeSc6IHsgJ1BsYXlCb29rJzogMSB9LFxuICAgICAgJ0dvb2dsZSc6IHsgJ0dvb2dsZSBUVic6IDEsICdOZXh1cyc6IDEgfSxcbiAgICAgICdIUCc6IHsgJ1RvdWNoUGFkJzogMSB9LFxuICAgICAgJ0hUQyc6IHt9LFxuICAgICAgJ0xHJzoge30sXG4gICAgICAnTWljcm9zb2Z0JzogeyAnWGJveCc6IDEsICdYYm94IE9uZSc6IDEgfSxcbiAgICAgICdNb3Rvcm9sYSc6IHsgJ1hvb20nOiAxIH0sXG4gICAgICAnTmludGVuZG8nOiB7ICdXaWkgVSc6IDEsICAnV2lpJzogMSB9LFxuICAgICAgJ05va2lhJzogeyAnTHVtaWEnOiAxIH0sXG4gICAgICAnU2Ftc3VuZyc6IHsgJ0dhbGF4eSBTJzogMSwgJ0dhbGF4eSBTMic6IDEsICdHYWxheHkgUzMnOiAxLCAnR2FsYXh5IFM0JzogMSB9LFxuICAgICAgJ1NvbnknOiB7ICdQbGF5U3RhdGlvbic6IDEsICdQbGF5U3RhdGlvbiBWaXRhJzogMSB9XG4gICAgfSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG9wZXJhdGluZyBzeXN0ZW1zIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBvcyA9IGdldE9TKFtcbiAgICAgICdXaW5kb3dzIFBob25lJyxcbiAgICAgICdBbmRyb2lkJyxcbiAgICAgICdDZW50T1MnLFxuICAgICAgeyAnbGFiZWwnOiAnQ2hyb21lIE9TJywgJ3BhdHRlcm4nOiAnQ3JPUycgfSxcbiAgICAgICdEZWJpYW4nLFxuICAgICAgJ0ZlZG9yYScsXG4gICAgICAnRnJlZUJTRCcsXG4gICAgICAnR2VudG9vJyxcbiAgICAgICdIYWlrdScsXG4gICAgICAnS3VidW50dScsXG4gICAgICAnTGludXggTWludCcsXG4gICAgICAnT3BlbkJTRCcsXG4gICAgICAnUmVkIEhhdCcsXG4gICAgICAnU3VTRScsXG4gICAgICAnVWJ1bnR1JyxcbiAgICAgICdYdWJ1bnR1JyxcbiAgICAgICdDeWd3aW4nLFxuICAgICAgJ1N5bWJpYW4gT1MnLFxuICAgICAgJ2hwd09TJyxcbiAgICAgICd3ZWJPUyAnLFxuICAgICAgJ3dlYk9TJyxcbiAgICAgICdUYWJsZXQgT1MnLFxuICAgICAgJ1RpemVuJyxcbiAgICAgICdMaW51eCcsXG4gICAgICAnTWFjIE9TIFgnLFxuICAgICAgJ01hY2ludG9zaCcsXG4gICAgICAnTWFjJyxcbiAgICAgICdXaW5kb3dzIDk4OycsXG4gICAgICAnV2luZG93cyAnXG4gICAgXSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgbGF5b3V0IGVuZ2luZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBsYXlvdXQgZW5naW5lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldExheW91dChndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCBSZWdFeHAoJ1xcXFxiJyArIChcbiAgICAgICAgICBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpXG4gICAgICAgICkgKyAnXFxcXGInLCAnaScpLmV4ZWModWEpICYmIChndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgbWFudWZhY3R1cmVyIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBvYmplY3Qgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBtYW51ZmFjdHVyZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TWFudWZhY3R1cmVyKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICAgIC8vIExvb2t1cCB0aGUgbWFudWZhY3R1cmVyIGJ5IHByb2R1Y3Qgb3Igc2NhbiB0aGUgVUEgZm9yIHRoZSBtYW51ZmFjdHVyZXIuXG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgKFxuICAgICAgICAgIHZhbHVlW3Byb2R1Y3RdIHx8XG4gICAgICAgICAgdmFsdWVbL15bYS16XSsoPzogK1thLXpdK1xcYikqL2kuZXhlYyhwcm9kdWN0KV0gfHxcbiAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHF1YWxpZnkoa2V5KSArICcoPzpcXFxcYnxcXFxcdypcXFxcZCknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICkgJiYga2V5O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGJyb3dzZXIgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBicm93c2VyIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TmFtZShndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCBSZWdFeHAoJ1xcXFxiJyArIChcbiAgICAgICAgICBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpXG4gICAgICAgICkgKyAnXFxcXGInLCAnaScpLmV4ZWModWEpICYmIChndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgT1MgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBPUyBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE9TKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnKD86L1tcXFxcZC5dK3xbIFxcXFx3Ll0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICByZXN1bHQgPSBjbGVhbnVwT1MocmVzdWx0LCBwYXR0ZXJuLCBndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBwcm9kdWN0IG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgcHJvZHVjdCBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFByb2R1Y3QoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKTtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgKHJlc3VsdCA9XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcgKlxcXFxkK1suXFxcXHdfXSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcgKlxcXFx3Ky1bXFxcXHddKicsICdpJykuZXhlYyh1YSkgfHxcbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/OjsgKig/OlthLXpdK1tfLV0pP1thLXpdK1xcXFxkK3xbXiAoKTstXSopJywgJ2knKS5leGVjKHVhKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIC8vIFNwbGl0IGJ5IGZvcndhcmQgc2xhc2ggYW5kIGFwcGVuZCBwcm9kdWN0IHZlcnNpb24gaWYgbmVlZGVkLlxuICAgICAgICAgIGlmICgocmVzdWx0ID0gU3RyaW5nKChndWVzcy5sYWJlbCAmJiAhUmVnRXhwKHBhdHRlcm4sICdpJykudGVzdChndWVzcy5sYWJlbCkpID8gZ3Vlc3MubGFiZWwgOiByZXN1bHQpLnNwbGl0KCcvJykpWzFdICYmICEvW1xcZC5dKy8udGVzdChyZXN1bHRbMF0pKSB7XG4gICAgICAgICAgICByZXN1bHRbMF0gKz0gJyAnICsgcmVzdWx0WzFdO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBDb3JyZWN0IGNoYXJhY3RlciBjYXNlIGFuZCBjbGVhbnVwIHN0cmluZy5cbiAgICAgICAgICBndWVzcyA9IGd1ZXNzLmxhYmVsIHx8IGd1ZXNzO1xuICAgICAgICAgIHJlc3VsdCA9IGZvcm1hdChyZXN1bHRbMF1cbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cChwYXR0ZXJuLCAnaScpLCBndWVzcylcbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cCgnOyAqKD86JyArIGd1ZXNzICsgJ1tfLV0pPycsICdpJyksICcgJylcbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cCgnKCcgKyBndWVzcyArICcpWy1fLl0/KFxcXFx3KScsICdpJyksICckMSAkMicpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzb2x2ZXMgdGhlIHZlcnNpb24gdXNpbmcgYW4gYXJyYXkgb2YgVUEgcGF0dGVybnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhdHRlcm5zIEFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHZlcnNpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0VmVyc2lvbihwYXR0ZXJucykge1xuICAgICAgcmV0dXJuIHJlZHVjZShwYXR0ZXJucywgZnVuY3Rpb24ocmVzdWx0LCBwYXR0ZXJuKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgKFJlZ0V4cChwYXR0ZXJuICtcbiAgICAgICAgICAnKD86LVtcXFxcZC5dKy98KD86IGZvciBbXFxcXHctXSspP1sgLy1dKShbXFxcXGQuXStbXiAoKTsvXy1dKiknLCAnaScpLmV4ZWModWEpIHx8IDApWzFdIHx8IG51bGw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgd2hlbiB0aGUgcGxhdGZvcm0gb2JqZWN0IGlzIGNvZXJjZWQgdG8gYSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbmFtZSB0b1N0cmluZ1xuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgYHBsYXRmb3JtLmRlc2NyaXB0aW9uYCBpZiBhdmFpbGFibGUsIGVsc2UgYW4gZW1wdHkgc3RyaW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvU3RyaW5nUGxhdGZvcm0oKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXNjcmlwdGlvbiB8fCAnJztcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBDb252ZXJ0IGxheW91dCB0byBhbiBhcnJheSBzbyB3ZSBjYW4gYWRkIGV4dHJhIGRldGFpbHMuXG4gICAgbGF5b3V0ICYmIChsYXlvdXQgPSBbbGF5b3V0XSk7XG5cbiAgICAvLyBEZXRlY3QgcHJvZHVjdCBuYW1lcyB0aGF0IGNvbnRhaW4gdGhlaXIgbWFudWZhY3R1cmVyJ3MgbmFtZS5cbiAgICBpZiAobWFudWZhY3R1cmVyICYmICFwcm9kdWN0KSB7XG4gICAgICBwcm9kdWN0ID0gZ2V0UHJvZHVjdChbbWFudWZhY3R1cmVyXSk7XG4gICAgfVxuICAgIC8vIENsZWFuIHVwIEdvb2dsZSBUVi5cbiAgICBpZiAoKGRhdGEgPSAvXFxiR29vZ2xlIFRWXFxiLy5leGVjKHByb2R1Y3QpKSkge1xuICAgICAgcHJvZHVjdCA9IGRhdGFbMF07XG4gICAgfVxuICAgIC8vIERldGVjdCBzaW11bGF0b3JzLlxuICAgIGlmICgvXFxiU2ltdWxhdG9yXFxiL2kudGVzdCh1YSkpIHtcbiAgICAgIHByb2R1Y3QgPSAocHJvZHVjdCA/IHByb2R1Y3QgKyAnICcgOiAnJykgKyAnU2ltdWxhdG9yJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIE1pbmkgOCsgcnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZSBvbiBpT1MuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhIE1pbmknICYmIC9cXGJPUGlPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ3J1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIE1vYmlsZSAxMS5cbiAgICBpZiAobmFtZSA9PSAnSUUnICYmIC9cXGJsaWtlIGlQaG9uZSBPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRhdGEgPSBwYXJzZSh1YS5yZXBsYWNlKC9saWtlIGlQaG9uZSBPUy8sICcnKSk7XG4gICAgICBtYW51ZmFjdHVyZXIgPSBkYXRhLm1hbnVmYWN0dXJlcjtcbiAgICAgIHByb2R1Y3QgPSBkYXRhLnByb2R1Y3Q7XG4gICAgfVxuICAgIC8vIERldGVjdCBpT1MuXG4gICAgZWxzZSBpZiAoL15pUC8udGVzdChwcm9kdWN0KSkge1xuICAgICAgbmFtZSB8fCAobmFtZSA9ICdTYWZhcmknKTtcbiAgICAgIG9zID0gJ2lPUycgKyAoKGRhdGEgPSAvIE9TIChbXFxkX10rKS9pLmV4ZWModWEpKVxuICAgICAgICA/ICcgJyArIGRhdGFbMV0ucmVwbGFjZSgvXy9nLCAnLicpXG4gICAgICAgIDogJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgS3VidW50dS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdLb25xdWVyb3InICYmICEvYnVudHUvaS50ZXN0KG9zKSkge1xuICAgICAgb3MgPSAnS3VidW50dSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBBbmRyb2lkIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKChtYW51ZmFjdHVyZXIgJiYgbWFudWZhY3R1cmVyICE9ICdHb29nbGUnICYmXG4gICAgICAgICgoL0Nocm9tZS8udGVzdChuYW1lKSAmJiAhL1xcYk1vYmlsZSBTYWZhcmlcXGIvaS50ZXN0KHVhKSkgfHwgL1xcYlZpdGFcXGIvLnRlc3QocHJvZHVjdCkpKSB8fFxuICAgICAgICAoL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpICYmIC9eQ2hyb21lLy50ZXN0KG5hbWUpICYmIC9cXGJWZXJzaW9uXFwvL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lID0gJ0FuZHJvaWQgQnJvd3Nlcic7XG4gICAgICBvcyA9IC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogJ0FuZHJvaWQnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgU2lsayBkZXNrdG9wL2FjY2VsZXJhdGVkIG1vZGVzLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1NpbGsnKSB7XG4gICAgICBpZiAoIS9cXGJNb2JpL2kudGVzdCh1YSkpIHtcbiAgICAgICAgb3MgPSAnQW5kcm9pZCc7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgfVxuICAgICAgaWYgKC9BY2NlbGVyYXRlZCAqPSAqdHJ1ZS9pLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2FjY2VsZXJhdGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBQYWxlTW9vbiBpZGVudGlmeWluZyBhcyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1BhbGVNb29uJyAmJiAoZGF0YSA9IC9cXGJGaXJlZm94XFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzIEZpcmVmb3ggJyArIGRhdGFbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBPUyBhbmQgcHJvZHVjdHMgcnVubmluZyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIChkYXRhID0gL1xcYihNb2JpbGV8VGFibGV0fFRWKVxcYi9pLmV4ZWModWEpKSkge1xuICAgICAgb3MgfHwgKG9zID0gJ0ZpcmVmb3ggT1MnKTtcbiAgICAgIHByb2R1Y3QgfHwgKHByb2R1Y3QgPSBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGZhbHNlIHBvc2l0aXZlcyBmb3IgRmlyZWZveC9TYWZhcmkuXG4gICAgZWxzZSBpZiAoIW5hbWUgfHwgKGRhdGEgPSAhL1xcYk1pbmVmaWVsZFxcYi9pLnRlc3QodWEpICYmIC9cXGIoPzpGaXJlZm94fFNhZmFyaSlcXGIvLmV4ZWMobmFtZSkpKSB7XG4gICAgICAvLyBFc2NhcGUgdGhlIGAvYCBmb3IgRmlyZWZveCAxLlxuICAgICAgaWYgKG5hbWUgJiYgIXByb2R1Y3QgJiYgL1tcXC8sXXxeW14oXSs/XFwpLy50ZXN0KHVhLnNsaWNlKHVhLmluZGV4T2YoZGF0YSArICcvJykgKyA4KSkpIHtcbiAgICAgICAgLy8gQ2xlYXIgbmFtZSBvZiBmYWxzZSBwb3NpdGl2ZXMuXG4gICAgICAgIG5hbWUgPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gUmVhc3NpZ24gYSBnZW5lcmljIG5hbWUuXG4gICAgICBpZiAoKGRhdGEgPSBwcm9kdWN0IHx8IG1hbnVmYWN0dXJlciB8fCBvcykgJiZcbiAgICAgICAgICAocHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgL1xcYig/OkFuZHJvaWR8U3ltYmlhbiBPU3xUYWJsZXQgT1N8d2ViT1MpXFxiLy50ZXN0KG9zKSkpIHtcbiAgICAgICAgbmFtZSA9IC9bYS16XSsoPzogSGF0KT8vaS5leGVjKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogZGF0YSkgKyAnIEJyb3dzZXInO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgQ2hyb21lIHZlcnNpb24gdG8gZGVzY3JpcHRpb24gZm9yIEVsZWN0cm9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0VsZWN0cm9uJyAmJiAoZGF0YSA9ICgvXFxiQ2hyb21lXFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyBkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IG5vbi1PcGVyYSAoUHJlc3RvLWJhc2VkKSB2ZXJzaW9ucyAob3JkZXIgaXMgaW1wb3J0YW50KS5cbiAgICBpZiAoIXZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSBnZXRWZXJzaW9uKFtcbiAgICAgICAgJyg/OkNsb3VkOXxDcmlPU3xDck1vfEVkZ2V8RnhpT1N8SUVNb2JpbGV8SXJvbnxPcGVyYSA/TWluaXxPUGlPU3xPUFJ8UmF2ZW58U2Ftc3VuZ0Jyb3dzZXJ8U2lsayg/IS9bXFxcXGQuXSskKSknLFxuICAgICAgICAnVmVyc2lvbicsXG4gICAgICAgIHF1YWxpZnkobmFtZSksXG4gICAgICAgICcoPzpGaXJlZm94fE1pbmVmaWVsZHxOZXRGcm9udCknXG4gICAgICBdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHN0dWJib3JuIGxheW91dCBlbmdpbmVzLlxuICAgIGlmICgoZGF0YSA9XG4gICAgICAgICAgbGF5b3V0ID09ICdpQ2FiJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID4gMyAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgIC9cXGJPcGVyYVxcYi8udGVzdChuYW1lKSAmJiAoL1xcYk9QUlxcYi8udGVzdCh1YSkgPyAnQmxpbmsnIDogJ1ByZXN0bycpIHx8XG4gICAgICAgICAgL1xcYig/Ok1pZG9yaXxOb29rfFNhZmFyaSlcXGIvaS50ZXN0KHVhKSAmJiAhL14oPzpUcmlkZW50fEVkZ2VIVE1MKSQvLnRlc3QobGF5b3V0KSAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgICFsYXlvdXQgJiYgL1xcYk1TSUVcXGIvaS50ZXN0KHVhKSAmJiAob3MgPT0gJ01hYyBPUycgPyAnVGFzbWFuJyA6ICdUcmlkZW50JykgfHxcbiAgICAgICAgICBsYXlvdXQgPT0gJ1dlYktpdCcgJiYgL1xcYlBsYXlTdGF0aW9uXFxiKD8hIFZpdGFcXGIpL2kudGVzdChuYW1lKSAmJiAnTmV0RnJvbnQnXG4gICAgICAgICkpIHtcbiAgICAgIGxheW91dCA9IFtkYXRhXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgUGhvbmUgNyBkZXNrdG9wIG1vZGUuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAoZGF0YSA9ICgvOyAqKD86WEJMV1B8WnVuZVdQKShcXGQrKS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lICcgKyAoL1xcKyQvLnRlc3QoZGF0YSkgPyBkYXRhIDogZGF0YSArICcueCcpO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDgueCBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAoL1xcYldQRGVza3RvcFxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBuYW1lID0gJ0lFIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lIDgueCc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIHZlcnNpb24gfHwgKHZlcnNpb24gPSAoL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkgfHwgMClbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgMTEgaWRlbnRpZnlpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAobmFtZSAhPSAnSUUnICYmIGxheW91dCA9PSAnVHJpZGVudCcgJiYgKGRhdGEgPSAvXFxicnY6KFtcXGQuXSspLy5leGVjKHVhKSkpIHtcbiAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzICcgKyBuYW1lICsgKHZlcnNpb24gPyAnICcgKyB2ZXJzaW9uIDogJycpKTtcbiAgICAgIH1cbiAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgdmVyc2lvbiA9IGRhdGFbMV07XG4gICAgfVxuICAgIC8vIExldmVyYWdlIGVudmlyb25tZW50IGZlYXR1cmVzLlxuICAgIGlmICh1c2VGZWF0dXJlcykge1xuICAgICAgLy8gRGV0ZWN0IHNlcnZlci1zaWRlIGVudmlyb25tZW50cy5cbiAgICAgIC8vIFJoaW5vIGhhcyBhIGdsb2JhbCBmdW5jdGlvbiB3aGlsZSBvdGhlcnMgaGF2ZSBhIGdsb2JhbCBvYmplY3QuXG4gICAgICBpZiAoaXNIb3N0VHlwZShjb250ZXh0LCAnZ2xvYmFsJykpIHtcbiAgICAgICAgaWYgKGphdmEpIHtcbiAgICAgICAgICBkYXRhID0gamF2YS5sYW5nLlN5c3RlbTtcbiAgICAgICAgICBhcmNoID0gZGF0YS5nZXRQcm9wZXJ0eSgnb3MuYXJjaCcpO1xuICAgICAgICAgIG9zID0gb3MgfHwgZGF0YS5nZXRQcm9wZXJ0eSgnb3MubmFtZScpICsgJyAnICsgZGF0YS5nZXRQcm9wZXJ0eSgnb3MudmVyc2lvbicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyaGlubykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2ZXJzaW9uID0gY29udGV4dC5yZXF1aXJlKCdyaW5nby9lbmdpbmUnKS52ZXJzaW9uLmpvaW4oJy4nKTtcbiAgICAgICAgICAgIG5hbWUgPSAnUmluZ29KUyc7XG4gICAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgICBpZiAoKGRhdGEgPSBjb250ZXh0LnN5c3RlbSkgJiYgZGF0YS5nbG9iYWwuc3lzdGVtID09IGNvbnRleHQuc3lzdGVtKSB7XG4gICAgICAgICAgICAgIG5hbWUgPSAnTmFyd2hhbCc7XG4gICAgICAgICAgICAgIG9zIHx8IChvcyA9IGRhdGFbMF0ub3MgfHwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdSaGlubyc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKFxuICAgICAgICAgIHR5cGVvZiBjb250ZXh0LnByb2Nlc3MgPT0gJ29iamVjdCcgJiYgIWNvbnRleHQucHJvY2Vzcy5icm93c2VyICYmXG4gICAgICAgICAgKGRhdGEgPSBjb250ZXh0LnByb2Nlc3MpXG4gICAgICAgICkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucyA9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLmVsZWN0cm9uID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ05vZGUgJyArIGRhdGEudmVyc2lvbnMubm9kZSk7XG4gICAgICAgICAgICAgIG5hbWUgPSAnRWxlY3Ryb24nO1xuICAgICAgICAgICAgICB2ZXJzaW9uID0gZGF0YS52ZXJzaW9ucy5lbGVjdHJvbjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMubncgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnQ2hyb21pdW0gJyArIHZlcnNpb24sICdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ05XLmpzJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMubnc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdOb2RlLmpzJztcbiAgICAgICAgICAgIGFyY2ggPSBkYXRhLmFyY2g7XG4gICAgICAgICAgICBvcyA9IGRhdGEucGxhdGZvcm07XG4gICAgICAgICAgICB2ZXJzaW9uID0gL1tcXGQuXSsvLmV4ZWMoZGF0YS52ZXJzaW9uKTtcbiAgICAgICAgICAgIHZlcnNpb24gPSB2ZXJzaW9uID8gdmVyc2lvblswXSA6IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgQWRvYmUgQUlSLlxuICAgICAgZWxzZSBpZiAoZ2V0Q2xhc3NPZigoZGF0YSA9IGNvbnRleHQucnVudGltZSkpID09IGFpclJ1bnRpbWVDbGFzcykge1xuICAgICAgICBuYW1lID0gJ0Fkb2JlIEFJUic7XG4gICAgICAgIG9zID0gZGF0YS5mbGFzaC5zeXN0ZW0uQ2FwYWJpbGl0aWVzLm9zO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IFBoYW50b21KUy5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnBoYW50b20pKSA9PSBwaGFudG9tQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdQaGFudG9tSlMnO1xuICAgICAgICB2ZXJzaW9uID0gKGRhdGEgPSBkYXRhLnZlcnNpb24gfHwgbnVsbCkgJiYgKGRhdGEubWFqb3IgKyAnLicgKyBkYXRhLm1pbm9yICsgJy4nICsgZGF0YS5wYXRjaCk7XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSUUgY29tcGF0aWJpbGl0eSBtb2Rlcy5cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBkb2MuZG9jdW1lbnRNb2RlID09ICdudW1iZXInICYmIChkYXRhID0gL1xcYlRyaWRlbnRcXC8oXFxkKykvaS5leGVjKHVhKSkpIHtcbiAgICAgICAgLy8gV2UncmUgaW4gY29tcGF0aWJpbGl0eSBtb2RlIHdoZW4gdGhlIFRyaWRlbnQgdmVyc2lvbiArIDQgZG9lc24ndFxuICAgICAgICAvLyBlcXVhbCB0aGUgZG9jdW1lbnQgbW9kZS5cbiAgICAgICAgdmVyc2lvbiA9IFt2ZXJzaW9uLCBkb2MuZG9jdW1lbnRNb2RlXTtcbiAgICAgICAgaWYgKChkYXRhID0gK2RhdGFbMV0gKyA0KSAhPSB2ZXJzaW9uWzFdKSB7XG4gICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnSUUgJyArIHZlcnNpb25bMV0gKyAnIG1vZGUnKTtcbiAgICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICcnKTtcbiAgICAgICAgICB2ZXJzaW9uWzFdID0gZGF0YTtcbiAgICAgICAgfVxuICAgICAgICB2ZXJzaW9uID0gbmFtZSA9PSAnSUUnID8gU3RyaW5nKHZlcnNpb25bMV0udG9GaXhlZCgxKSkgOiB2ZXJzaW9uWzBdO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIDExIG1hc2tpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAvXig/OkNocm9tZXxGaXJlZm94KVxcYi8udGVzdChuYW1lKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdtYXNraW5nIGFzICcgKyBuYW1lICsgJyAnICsgdmVyc2lvbik7XG4gICAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgICB2ZXJzaW9uID0gJzExLjAnO1xuICAgICAgICBsYXlvdXQgPSBbJ1RyaWRlbnQnXTtcbiAgICAgICAgb3MgPSAnV2luZG93cyc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zICYmIGZvcm1hdChvcyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBwcmVyZWxlYXNlIHBoYXNlcy5cbiAgICBpZiAodmVyc2lvbiAmJiAoZGF0YSA9XG4gICAgICAgICAgLyg/OlthYl18ZHB8cHJlfFthYl1cXGQrcHJlKSg/OlxcZCtcXCs/KT8kL2kuZXhlYyh2ZXJzaW9uKSB8fFxuICAgICAgICAgIC8oPzphbHBoYXxiZXRhKSg/OiA/XFxkKT8vaS5leGVjKHVhICsgJzsnICsgKHVzZUZlYXR1cmVzICYmIG5hdi5hcHBNaW5vclZlcnNpb24pKSB8fFxuICAgICAgICAgIC9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAnYSdcbiAgICAgICAgKSkge1xuICAgICAgcHJlcmVsZWFzZSA9IC9iL2kudGVzdChkYXRhKSA/ICdiZXRhJyA6ICdhbHBoYSc7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKFJlZ0V4cChkYXRhICsgJ1xcXFwrPyQnKSwgJycpICtcbiAgICAgICAgKHByZXJlbGVhc2UgPT0gJ2JldGEnID8gYmV0YSA6IGFscGhhKSArICgvXFxkK1xcKz8vLmV4ZWMoZGF0YSkgfHwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBNb2JpbGUuXG4gICAgaWYgKG5hbWUgPT0gJ0Zlbm5lYycgfHwgbmFtZSA9PSAnRmlyZWZveCcgJiYgL1xcYig/OkFuZHJvaWR8RmlyZWZveCBPUylcXGIvLnRlc3Qob3MpKSB7XG4gICAgICBuYW1lID0gJ0ZpcmVmb3ggTW9iaWxlJztcbiAgICB9XG4gICAgLy8gT2JzY3VyZSBNYXh0aG9uJ3MgdW5yZWxpYWJsZSB2ZXJzaW9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ01heHRob24nICYmIHZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSB2ZXJzaW9uLnJlcGxhY2UoL1xcLltcXGQuXSsvLCAnLngnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFhib3ggMzYwIGFuZCBYYm94IE9uZS5cbiAgICBlbHNlIGlmICgvXFxiWGJveFxcYi9pLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcpIHtcbiAgICAgICAgb3MgPSBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHByb2R1Y3QgPT0gJ1hib3ggMzYwJyAmJiAvXFxiSUVNb2JpbGVcXGIvLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ21vYmlsZSBtb2RlJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFkZCBtb2JpbGUgcG9zdGZpeC5cbiAgICBlbHNlIGlmICgoL14oPzpDaHJvbWV8SUV8T3BlcmEpJC8udGVzdChuYW1lKSB8fCBuYW1lICYmICFwcm9kdWN0ICYmICEvQnJvd3NlcnxNb2JpLy50ZXN0KG5hbWUpKSAmJlxuICAgICAgICAob3MgPT0gJ1dpbmRvd3MgQ0UnIHx8IC9Nb2JpL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lICs9ICcgTW9iaWxlJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIHBsYXRmb3JtIHByZXZpZXcuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnSUUnICYmIHVzZUZlYXR1cmVzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoY29udGV4dC5leHRlcm5hbCA9PT0gbnVsbCkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ3BsYXRmb3JtIHByZXZpZXcnKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2VtYmVkZGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBCbGFja0JlcnJ5IE9TIHZlcnNpb24uXG4gICAgLy8gaHR0cDovL2RvY3MuYmxhY2tiZXJyeS5jb20vZW4vZGV2ZWxvcGVycy9kZWxpdmVyYWJsZXMvMTgxNjkvSFRUUF9oZWFkZXJzX3NlbnRfYnlfQkJfQnJvd3Nlcl8xMjM0OTExXzExLmpzcFxuICAgIGVsc2UgaWYgKCgvXFxiQmxhY2tCZXJyeVxcYi8udGVzdChwcm9kdWN0KSB8fCAvXFxiQkIxMFxcYi8udGVzdCh1YSkpICYmIChkYXRhID1cbiAgICAgICAgICAoUmVnRXhwKHByb2R1Y3QucmVwbGFjZSgvICsvZywgJyAqJykgKyAnLyhbLlxcXFxkXSspJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fFxuICAgICAgICAgIHZlcnNpb25cbiAgICAgICAgKSkge1xuICAgICAgZGF0YSA9IFtkYXRhLCAvQkIxMC8udGVzdCh1YSldO1xuICAgICAgb3MgPSAoZGF0YVsxXSA/IChwcm9kdWN0ID0gbnVsbCwgbWFudWZhY3R1cmVyID0gJ0JsYWNrQmVycnknKSA6ICdEZXZpY2UgU29mdHdhcmUnKSArICcgJyArIGRhdGFbMF07XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGlkZW50aWZ5aW5nL21hc2tpbmcgaXRzZWxmIGFzIGFub3RoZXIgYnJvd3Nlci5cbiAgICAvLyBodHRwOi8vd3d3Lm9wZXJhLmNvbS9zdXBwb3J0L2tiL3ZpZXcvODQzL1xuICAgIGVsc2UgaWYgKHRoaXMgIT0gZm9yT3duICYmIHByb2R1Y3QgIT0gJ1dpaScgJiYgKFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiBvcGVyYSkgfHxcbiAgICAgICAgICAoL09wZXJhLy50ZXN0KG5hbWUpICYmIC9cXGIoPzpNU0lFfEZpcmVmb3gpXFxiL2kudGVzdCh1YSkpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGJPUyBYICg/OlxcZCtcXC4pezIsfS8udGVzdChvcykpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0lFJyAmJiAoXG4gICAgICAgICAgICAob3MgJiYgIS9eV2luLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gNS41KSB8fFxuICAgICAgICAgICAgL1xcYldpbmRvd3MgWFBcXGIvLnRlc3Qob3MpICYmIHZlcnNpb24gPiA4IHx8XG4gICAgICAgICAgICB2ZXJzaW9uID09IDggJiYgIS9cXGJUcmlkZW50XFxiLy50ZXN0KHVhKVxuICAgICAgICAgICkpXG4gICAgICAgICkgJiYgIXJlT3BlcmEudGVzdCgoZGF0YSA9IHBhcnNlLmNhbGwoZm9yT3duLCB1YS5yZXBsYWNlKHJlT3BlcmEsICcnKSArICc7JykpKSAmJiBkYXRhLm5hbWUpIHtcbiAgICAgIC8vIFdoZW4gXCJpZGVudGlmeWluZ1wiLCB0aGUgVUEgY29udGFpbnMgYm90aCBPcGVyYSBhbmQgdGhlIG90aGVyIGJyb3dzZXIncyBuYW1lLlxuICAgICAgZGF0YSA9ICdpbmcgYXMgJyArIGRhdGEubmFtZSArICgoZGF0YSA9IGRhdGEudmVyc2lvbikgPyAnICcgKyBkYXRhIDogJycpO1xuICAgICAgaWYgKHJlT3BlcmEudGVzdChuYW1lKSkge1xuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpICYmIG9zID09ICdNYWMgT1MnKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGRhdGEgPSAnaWRlbnRpZnknICsgZGF0YTtcbiAgICAgIH1cbiAgICAgIC8vIFdoZW4gXCJtYXNraW5nXCIsIHRoZSBVQSBjb250YWlucyBvbmx5IHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGVsc2Uge1xuICAgICAgICBkYXRhID0gJ21hc2snICsgZGF0YTtcbiAgICAgICAgaWYgKG9wZXJhQ2xhc3MpIHtcbiAgICAgICAgICBuYW1lID0gZm9ybWF0KG9wZXJhQ2xhc3MucmVwbGFjZSgvKFthLXpdKShbQS1aXSkvZywgJyQxICQyJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5hbWUgPSAnT3BlcmEnO1xuICAgICAgICB9XG4gICAgICAgIGlmICgvXFxiSUVcXGIvLnRlc3QoZGF0YSkpIHtcbiAgICAgICAgICBvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF1c2VGZWF0dXJlcykge1xuICAgICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsYXlvdXQgPSBbJ1ByZXN0byddO1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdlYktpdCBOaWdodGx5IGFuZCBhcHByb3hpbWF0ZSBDaHJvbWUvU2FmYXJpIHZlcnNpb25zLlxuICAgIGlmICgoZGF0YSA9ICgvXFxiQXBwbGVXZWJLaXRcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAvLyBDb3JyZWN0IGJ1aWxkIG51bWJlciBmb3IgbnVtZXJpYyBjb21wYXJpc29uLlxuICAgICAgLy8gKGUuZy4gXCI1MzIuNVwiIGJlY29tZXMgXCI1MzIuMDVcIilcbiAgICAgIGRhdGEgPSBbcGFyc2VGbG9hdChkYXRhLnJlcGxhY2UoL1xcLihcXGQpJC8sICcuMCQxJykpLCBkYXRhXTtcbiAgICAgIC8vIE5pZ2h0bHkgYnVpbGRzIGFyZSBwb3N0Zml4ZWQgd2l0aCBhIFwiK1wiLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgZGF0YVsxXS5zbGljZSgtMSkgPT0gJysnKSB7XG4gICAgICAgIG5hbWUgPSAnV2ViS2l0IE5pZ2h0bHknO1xuICAgICAgICBwcmVyZWxlYXNlID0gJ2FscGhhJztcbiAgICAgICAgdmVyc2lvbiA9IGRhdGFbMV0uc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuICAgICAgLy8gQ2xlYXIgaW5jb3JyZWN0IGJyb3dzZXIgdmVyc2lvbnMuXG4gICAgICBlbHNlIGlmICh2ZXJzaW9uID09IGRhdGFbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uID09IChkYXRhWzJdID0gKC9cXGJTYWZhcmlcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHRoZSBmdWxsIENocm9tZSB2ZXJzaW9uIHdoZW4gYXZhaWxhYmxlLlxuICAgICAgZGF0YVsxXSA9ICgvXFxiQ2hyb21lXFwvKFtcXGQuXSspL2kuZXhlYyh1YSkgfHwgMClbMV07XG4gICAgICAvLyBEZXRlY3QgQmxpbmsgbGF5b3V0IGVuZ2luZS5cbiAgICAgIGlmIChkYXRhWzBdID09IDUzNy4zNiAmJiBkYXRhWzJdID09IDUzNy4zNiAmJiBwYXJzZUZsb2F0KGRhdGFbMV0pID49IDI4ICYmIGxheW91dCA9PSAnV2ViS2l0Jykge1xuICAgICAgICBsYXlvdXQgPSBbJ0JsaW5rJ107XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSmF2YVNjcmlwdENvcmUuXG4gICAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY3Njg0NzQvaG93LWNhbi1pLWRldGVjdC13aGljaC1qYXZhc2NyaXB0LWVuZ2luZS12OC1vci1qc2MtaXMtdXNlZC1hdC1ydW50aW1lLWluLWFuZHJvaVxuICAgICAgaWYgKCF1c2VGZWF0dXJlcyB8fCAoIWxpa2VDaHJvbWUgJiYgIWRhdGFbMV0pKSB7XG4gICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJ2xpa2UgU2FmYXJpJyk7XG4gICAgICAgIGRhdGEgPSAoZGF0YSA9IGRhdGFbMF0sIGRhdGEgPCA0MDAgPyAxIDogZGF0YSA8IDUwMCA/IDIgOiBkYXRhIDwgNTI2ID8gMyA6IGRhdGEgPCA1MzMgPyA0IDogZGF0YSA8IDUzNCA/ICc0KycgOiBkYXRhIDwgNTM1ID8gNSA6IGRhdGEgPCA1MzcgPyA2IDogZGF0YSA8IDUzOCA/IDcgOiBkYXRhIDwgNjAxID8gOCA6ICc4Jyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIENocm9tZScpO1xuICAgICAgICBkYXRhID0gZGF0YVsxXSB8fCAoZGF0YSA9IGRhdGFbMF0sIGRhdGEgPCA1MzAgPyAxIDogZGF0YSA8IDUzMiA/IDIgOiBkYXRhIDwgNTMyLjA1ID8gMyA6IGRhdGEgPCA1MzMgPyA0IDogZGF0YSA8IDUzNC4wMyA/IDUgOiBkYXRhIDwgNTM0LjA3ID8gNiA6IGRhdGEgPCA1MzQuMTAgPyA3IDogZGF0YSA8IDUzNC4xMyA/IDggOiBkYXRhIDwgNTM0LjE2ID8gOSA6IGRhdGEgPCA1MzQuMjQgPyAxMCA6IGRhdGEgPCA1MzQuMzAgPyAxMSA6IGRhdGEgPCA1MzUuMDEgPyAxMiA6IGRhdGEgPCA1MzUuMDIgPyAnMTMrJyA6IGRhdGEgPCA1MzUuMDcgPyAxNSA6IGRhdGEgPCA1MzUuMTEgPyAxNiA6IGRhdGEgPCA1MzUuMTkgPyAxNyA6IGRhdGEgPCA1MzYuMDUgPyAxOCA6IGRhdGEgPCA1MzYuMTAgPyAxOSA6IGRhdGEgPCA1MzcuMDEgPyAyMCA6IGRhdGEgPCA1MzcuMTEgPyAnMjErJyA6IGRhdGEgPCA1MzcuMTMgPyAyMyA6IGRhdGEgPCA1MzcuMTggPyAyNCA6IGRhdGEgPCA1MzcuMjQgPyAyNSA6IGRhdGEgPCA1MzcuMzYgPyAyNiA6IGxheW91dCAhPSAnQmxpbmsnID8gJzI3JyA6ICcyOCcpO1xuICAgICAgfVxuICAgICAgLy8gQWRkIHRoZSBwb3N0Zml4IG9mIFwiLnhcIiBvciBcIitcIiBmb3IgYXBwcm94aW1hdGUgdmVyc2lvbnMuXG4gICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSArPSAnICcgKyAoZGF0YSArPSB0eXBlb2YgZGF0YSA9PSAnbnVtYmVyJyA/ICcueCcgOiAvWy4rXS8udGVzdChkYXRhKSA/ICcnIDogJysnKSk7XG4gICAgICAvLyBPYnNjdXJlIHZlcnNpb24gZm9yIHNvbWUgU2FmYXJpIDEtMiByZWxlYXNlcy5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmICghdmVyc2lvbiB8fCBwYXJzZUludCh2ZXJzaW9uKSA+IDQ1KSkge1xuICAgICAgICB2ZXJzaW9uID0gZGF0YTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGRlc2t0b3AgbW9kZXMuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhJyAmJiAgKGRhdGEgPSAvXFxiemJvdnx6dmF2JC8uZXhlYyhvcykpKSB7XG4gICAgICBuYW1lICs9ICcgJztcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgaWYgKGRhdGEgPT0gJ3p2YXYnKSB7XG4gICAgICAgIG5hbWUgKz0gJ01pbmknO1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5hbWUgKz0gJ01vYmlsZSc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhICsgJyQnKSwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQ2hyb21lIGRlc2t0b3AgbW9kZS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTYWZhcmknICYmIC9cXGJDaHJvbWVcXGIvLmV4ZWMobGF5b3V0ICYmIGxheW91dFsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgbmFtZSA9ICdDaHJvbWUgTW9iaWxlJztcbiAgICAgIHZlcnNpb24gPSBudWxsO1xuXG4gICAgICBpZiAoL1xcYk9TIFhcXGIvLnRlc3Qob3MpKSB7XG4gICAgICAgIG1hbnVmYWN0dXJlciA9ICdBcHBsZSc7XG4gICAgICAgIG9zID0gJ2lPUyA0LjMrJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gU3RyaXAgaW5jb3JyZWN0IE9TIHZlcnNpb25zLlxuICAgIGlmICh2ZXJzaW9uICYmIHZlcnNpb24uaW5kZXhPZigoZGF0YSA9IC9bXFxkLl0rJC8uZXhlYyhvcykpKSA9PSAwICYmXG4gICAgICAgIHVhLmluZGV4T2YoJy8nICsgZGF0YSArICctJykgPiAtMSkge1xuICAgICAgb3MgPSB0cmltKG9zLnJlcGxhY2UoZGF0YSwgJycpKTtcbiAgICB9XG4gICAgLy8gQWRkIGxheW91dCBlbmdpbmUuXG4gICAgaWYgKGxheW91dCAmJiAhL1xcYig/OkF2YW50fE5vb2spXFxiLy50ZXN0KG5hbWUpICYmIChcbiAgICAgICAgL0Jyb3dzZXJ8THVuYXNjYXBlfE1heHRob24vLnRlc3QobmFtZSkgfHxcbiAgICAgICAgbmFtZSAhPSAnU2FmYXJpJyAmJiAvXmlPUy8udGVzdChvcykgJiYgL1xcYlNhZmFyaVxcYi8udGVzdChsYXlvdXRbMV0pIHx8XG4gICAgICAgIC9eKD86QWRvYmV8QXJvcmF8QnJlYWNofE1pZG9yaXxPcGVyYXxQaGFudG9tfFJla29ucXxSb2NrfFNhbXN1bmcgSW50ZXJuZXR8U2xlaXBuaXJ8V2ViKS8udGVzdChuYW1lKSAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICAvLyBEb24ndCBhZGQgbGF5b3V0IGRldGFpbHMgdG8gZGVzY3JpcHRpb24gaWYgdGhleSBhcmUgZmFsc2V5LlxuICAgICAgKGRhdGEgPSBsYXlvdXRbbGF5b3V0Lmxlbmd0aCAtIDFdKSAmJiBkZXNjcmlwdGlvbi5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICAvLyBDb21iaW5lIGNvbnRleHR1YWwgaW5mb3JtYXRpb24uXG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgZGVzY3JpcHRpb24gPSBbJygnICsgZGVzY3JpcHRpb24uam9pbignOyAnKSArICcpJ107XG4gICAgfVxuICAgIC8vIEFwcGVuZCBtYW51ZmFjdHVyZXIgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiBwcm9kdWN0ICYmIHByb2R1Y3QuaW5kZXhPZihtYW51ZmFjdHVyZXIpIDwgMCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnb24gJyArIG1hbnVmYWN0dXJlcik7XG4gICAgfVxuICAgIC8vIEFwcGVuZCBwcm9kdWN0IHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChwcm9kdWN0KSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCgvXm9uIC8udGVzdChkZXNjcmlwdGlvbltkZXNjcmlwdGlvbi5sZW5ndGggLSAxXSkgPyAnJyA6ICdvbiAnKSArIHByb2R1Y3QpO1xuICAgIH1cbiAgICAvLyBQYXJzZSB0aGUgT1MgaW50byBhbiBvYmplY3QuXG4gICAgaWYgKG9zKSB7XG4gICAgICBkYXRhID0gLyAoW1xcZC4rXSspJC8uZXhlYyhvcyk7XG4gICAgICBpc1NwZWNpYWxDYXNlZE9TID0gZGF0YSAmJiBvcy5jaGFyQXQob3MubGVuZ3RoIC0gZGF0YVswXS5sZW5ndGggLSAxKSA9PSAnLyc7XG4gICAgICBvcyA9IHtcbiAgICAgICAgJ2FyY2hpdGVjdHVyZSc6IDMyLFxuICAgICAgICAnZmFtaWx5JzogKGRhdGEgJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gb3MucmVwbGFjZShkYXRhWzBdLCAnJykgOiBvcyxcbiAgICAgICAgJ3ZlcnNpb24nOiBkYXRhID8gZGF0YVsxXSA6IG51bGwsXG4gICAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciB2ZXJzaW9uID0gdGhpcy52ZXJzaW9uO1xuICAgICAgICAgIHJldHVybiB0aGlzLmZhbWlseSArICgodmVyc2lvbiAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyAnICcgKyB2ZXJzaW9uIDogJycpICsgKHRoaXMuYXJjaGl0ZWN0dXJlID09IDY0ID8gJyA2NC1iaXQnIDogJycpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBBZGQgYnJvd3Nlci9PUyBhcmNoaXRlY3R1cmUuXG4gICAgaWYgKChkYXRhID0gL1xcYig/OkFNRHxJQXxXaW58V09XfHg4Nl98eCk2NFxcYi9pLmV4ZWMoYXJjaCkpICYmICEvXFxiaTY4NlxcYi9pLnRlc3QoYXJjaCkpIHtcbiAgICAgIGlmIChvcykge1xuICAgICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICAgICAgb3MuZmFtaWx5ID0gb3MuZmFtaWx5LnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhKSwgJycpO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICAgIG5hbWUgJiYgKC9cXGJXT1c2NFxcYi9pLnRlc3QodWEpIHx8XG4gICAgICAgICAgKHVzZUZlYXR1cmVzICYmIC9cXHcoPzo4NnwzMikkLy50ZXN0KG5hdi5jcHVDbGFzcyB8fCBuYXYucGxhdGZvcm0pICYmICEvXFxiV2luNjQ7IHg2NFxcYi9pLnRlc3QodWEpKSlcbiAgICAgICkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCczMi1iaXQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQ2hyb21lIDM5IGFuZCBhYm92ZSBvbiBPUyBYIGlzIGFsd2F5cyA2NC1iaXQuXG4gICAgZWxzZSBpZiAoXG4gICAgICAgIG9zICYmIC9eT1MgWC8udGVzdChvcy5mYW1pbHkpICYmXG4gICAgICAgIG5hbWUgPT0gJ0Nocm9tZScgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+PSAzOVxuICAgICkge1xuICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgfVxuXG4gICAgdWEgfHwgKHVhID0gbnVsbCk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gb2JqZWN0LlxuICAgICAqXG4gICAgICogQG5hbWUgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICB2YXIgcGxhdGZvcm0gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBkZXNjcmlwdGlvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyJ3MgbGF5b3V0IGVuZ2luZS5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBsYXlvdXQgZW5naW5lcyBpbmNsdWRlOlxuICAgICAqIFwiQmxpbmtcIiwgXCJFZGdlSFRNTFwiLCBcIkdlY2tvXCIsIFwiVHJpZGVudFwiIGFuZCBcIldlYktpdFwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmxheW91dCA9IGxheW91dCAmJiBsYXlvdXRbMF07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCdzIG1hbnVmYWN0dXJlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIG1hbnVmYWN0dXJlcnMgaW5jbHVkZTpcbiAgICAgKiBcIkFwcGxlXCIsIFwiQXJjaG9zXCIsIFwiQW1hem9uXCIsIFwiQXN1c1wiLCBcIkJhcm5lcyAmIE5vYmxlXCIsIFwiQmxhY2tCZXJyeVwiLFxuICAgICAqIFwiR29vZ2xlXCIsIFwiSFBcIiwgXCJIVENcIiwgXCJMR1wiLCBcIk1pY3Jvc29mdFwiLCBcIk1vdG9yb2xhXCIsIFwiTmludGVuZG9cIixcbiAgICAgKiBcIk5va2lhXCIsIFwiU2Ftc3VuZ1wiIGFuZCBcIlNvbnlcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5tYW51ZmFjdHVyZXIgPSBtYW51ZmFjdHVyZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3Nlci9lbnZpcm9ubWVudC5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBicm93c2VyIG5hbWVzIGluY2x1ZGU6XG4gICAgICogXCJDaHJvbWVcIiwgXCJFbGVjdHJvblwiLCBcIkZpcmVmb3hcIiwgXCJGaXJlZm94IGZvciBpT1NcIiwgXCJJRVwiLFxuICAgICAqIFwiTWljcm9zb2Z0IEVkZ2VcIiwgXCJQaGFudG9tSlNcIiwgXCJTYWZhcmlcIiwgXCJTZWFNb25rZXlcIiwgXCJTaWxrXCIsXG4gICAgICogXCJPcGVyYSBNaW5pXCIgYW5kIFwiT3BlcmFcIlxuICAgICAqXG4gICAgICogTW9iaWxlIHZlcnNpb25zIG9mIHNvbWUgYnJvd3NlcnMgaGF2ZSBcIk1vYmlsZVwiIGFwcGVuZGVkIHRvIHRoZWlyIG5hbWU6XG4gICAgICogZWcuIFwiQ2hyb21lIE1vYmlsZVwiLCBcIkZpcmVmb3ggTW9iaWxlXCIsIFwiSUUgTW9iaWxlXCIgYW5kIFwiT3BlcmEgTW9iaWxlXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubmFtZSA9IG5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYWxwaGEvYmV0YSByZWxlYXNlIGluZGljYXRvci5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJlcmVsZWFzZSA9IHByZXJlbGVhc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCBob3N0aW5nIHRoZSBicm93c2VyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIHByb2R1Y3RzIGluY2x1ZGU6XG4gICAgICpcbiAgICAgKiBcIkJsYWNrQmVycnlcIiwgXCJHYWxheHkgUzRcIiwgXCJMdW1pYVwiLCBcImlQYWRcIiwgXCJpUG9kXCIsIFwiaVBob25lXCIsIFwiS2luZGxlXCIsXG4gICAgICogXCJLaW5kbGUgRmlyZVwiLCBcIk5leHVzXCIsIFwiTm9va1wiLCBcIlBsYXlCb29rXCIsIFwiVG91Y2hQYWRcIiBhbmQgXCJUcmFuc2Zvcm1lclwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByb2R1Y3QgPSBwcm9kdWN0O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIncyB1c2VyIGFnZW50IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udWEgPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyL2Vudmlyb25tZW50IHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnZlcnNpb24gPSBuYW1lICYmIHZlcnNpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgb3BlcmF0aW5nIHN5c3RlbS5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm9zID0gb3MgfHwge1xuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlIHRoZSBPUyBpcyBidWlsdCBmb3IuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBudW1iZXJ8bnVsbFxuICAgICAgICovXG4gICAgICAnYXJjaGl0ZWN0dXJlJzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgZmFtaWx5IG9mIHRoZSBPUy5cbiAgICAgICAqXG4gICAgICAgKiBDb21tb24gdmFsdWVzIGluY2x1ZGU6XG4gICAgICAgKiBcIldpbmRvd3NcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IFIyIC8gN1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggLyBWaXN0YVwiLFxuICAgICAgICogXCJXaW5kb3dzIFhQXCIsIFwiT1MgWFwiLCBcIlVidW50dVwiLCBcIkRlYmlhblwiLCBcIkZlZG9yYVwiLCBcIlJlZCBIYXRcIiwgXCJTdVNFXCIsXG4gICAgICAgKiBcIkFuZHJvaWRcIiwgXCJpT1NcIiBhbmQgXCJXaW5kb3dzIFBob25lXCJcbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICAgKi9cbiAgICAgICdmYW1pbHknOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSB2ZXJzaW9uIG9mIHRoZSBPUy5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICAgKi9cbiAgICAgICd2ZXJzaW9uJzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBSZXR1cm5zIHRoZSBPUyBzdHJpbmcuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgT1Mgc3RyaW5nLlxuICAgICAgICovXG4gICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHsgcmV0dXJuICdudWxsJzsgfVxuICAgIH07XG5cbiAgICBwbGF0Zm9ybS5wYXJzZSA9IHBhcnNlO1xuICAgIHBsYXRmb3JtLnRvU3RyaW5nID0gdG9TdHJpbmdQbGF0Zm9ybTtcblxuICAgIGlmIChwbGF0Zm9ybS52ZXJzaW9uKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KHZlcnNpb24pO1xuICAgIH1cbiAgICBpZiAocGxhdGZvcm0ubmFtZSkge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdChuYW1lKTtcbiAgICB9XG4gICAgaWYgKG9zICYmIG5hbWUgJiYgIShvcyA9PSBTdHJpbmcob3MpLnNwbGl0KCcgJylbMF0gJiYgKG9zID09IG5hbWUuc3BsaXQoJyAnKVswXSB8fCBwcm9kdWN0KSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2gocHJvZHVjdCA/ICcoJyArIG9zICsgJyknIDogJ29uICcgKyBvcyk7XG4gICAgfVxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gZGVzY3JpcHRpb24uam9pbignICcpO1xuICAgIH1cbiAgICByZXR1cm4gcGxhdGZvcm07XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvLyBFeHBvcnQgcGxhdGZvcm0uXG4gIHZhciBwbGF0Zm9ybSA9IHBhcnNlKCk7XG5cbiAgLy8gU29tZSBBTUQgYnVpbGQgb3B0aW1pemVycywgbGlrZSByLmpzLCBjaGVjayBmb3IgY29uZGl0aW9uIHBhdHRlcm5zIGxpa2UgdGhlIGZvbGxvd2luZzpcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PSAnb2JqZWN0JyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gRXhwb3NlIHBsYXRmb3JtIG9uIHRoZSBnbG9iYWwgb2JqZWN0IHRvIHByZXZlbnQgZXJyb3JzIHdoZW4gcGxhdGZvcm0gaXNcbiAgICAvLyBsb2FkZWQgYnkgYSBzY3JpcHQgdGFnIGluIHRoZSBwcmVzZW5jZSBvZiBhbiBBTUQgbG9hZGVyLlxuICAgIC8vIFNlZSBodHRwOi8vcmVxdWlyZWpzLm9yZy9kb2NzL2Vycm9ycy5odG1sI21pc21hdGNoIGZvciBtb3JlIGRldGFpbHMuXG4gICAgcm9vdC5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuXG4gICAgLy8gRGVmaW5lIGFzIGFuIGFub255bW91cyBtb2R1bGUgc28gcGxhdGZvcm0gY2FuIGJlIGFsaWFzZWQgdGhyb3VnaCBwYXRoIG1hcHBpbmcuXG4gICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHBsYXRmb3JtO1xuICAgIH0pO1xuICB9XG4gIC8vIENoZWNrIGZvciBgZXhwb3J0c2AgYWZ0ZXIgYGRlZmluZWAgaW4gY2FzZSBhIGJ1aWxkIG9wdGltaXplciBhZGRzIGFuIGBleHBvcnRzYCBvYmplY3QuXG4gIGVsc2UgaWYgKGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUpIHtcbiAgICAvLyBFeHBvcnQgZm9yIENvbW1vbkpTIHN1cHBvcnQuXG4gICAgZm9yT3duKHBsYXRmb3JtLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICBmcmVlRXhwb3J0c1trZXldID0gdmFsdWU7XG4gICAgfSk7XG4gIH1cbiAgZWxzZSB7XG4gICAgLy8gRXhwb3J0IHRvIHRoZSBnbG9iYWwgb2JqZWN0LlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcbiAgfVxufS5jYWxsKHRoaXMpKTtcbiIsInZhciBncmFtbWFyID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIHY6IFt7XG4gICAgICBuYW1lOiAndmVyc2lvbicsXG4gICAgICByZWc6IC9eKFxcZCopJC9cbiAgfV0sXG4gIG86IFt7IC8vbz0tIDIwNTE4IDAgSU4gSVA0IDIwMy4wLjExMy4xXG4gICAgLy8gTkI6IHNlc3Npb25JZCB3aWxsIGJlIGEgU3RyaW5nIGluIG1vc3QgY2FzZXMgYmVjYXVzZSBpdCBpcyBodWdlXG4gICAgbmFtZTogJ29yaWdpbicsXG4gICAgcmVnOiAvXihcXFMqKSAoXFxkKikgKFxcZCopIChcXFMqKSBJUChcXGQpIChcXFMqKS8sXG4gICAgbmFtZXM6IFsndXNlcm5hbWUnLCAnc2Vzc2lvbklkJywgJ3Nlc3Npb25WZXJzaW9uJywgJ25ldFR5cGUnLCAnaXBWZXInLCAnYWRkcmVzcyddLFxuICAgIGZvcm1hdDogXCIlcyAlcyAlZCAlcyBJUCVkICVzXCJcbiAgfV0sXG4gIC8vIGRlZmF1bHQgcGFyc2luZyBvZiB0aGVzZSBvbmx5ICh0aG91Z2ggc29tZSBvZiB0aGVzZSBmZWVsIG91dGRhdGVkKVxuICBzOiBbeyBuYW1lOiAnbmFtZScgfV0sXG4gIGk6IFt7IG5hbWU6ICdkZXNjcmlwdGlvbicgfV0sXG4gIHU6IFt7IG5hbWU6ICd1cmknIH1dLFxuICBlOiBbeyBuYW1lOiAnZW1haWwnIH1dLFxuICBwOiBbeyBuYW1lOiAncGhvbmUnIH1dLFxuICB6OiBbeyBuYW1lOiAndGltZXpvbmVzJyB9XSwgLy8gVE9ETzogdGhpcyBvbmUgY2FuIGFjdHVhbGx5IGJlIHBhcnNlZCBwcm9wZXJseS4uXG4gIHI6IFt7IG5hbWU6ICdyZXBlYXRzJyB9XSwgICAvLyBUT0RPOiB0aGlzIG9uZSBjYW4gYWxzbyBiZSBwYXJzZWQgcHJvcGVybHlcbiAgLy9rOiBbe31dLCAvLyBvdXRkYXRlZCB0aGluZyBpZ25vcmVkXG4gIHQ6IFt7IC8vdD0wIDBcbiAgICBuYW1lOiAndGltaW5nJyxcbiAgICByZWc6IC9eKFxcZCopIChcXGQqKS8sXG4gICAgbmFtZXM6IFsnc3RhcnQnLCAnc3RvcCddLFxuICAgIGZvcm1hdDogXCIlZCAlZFwiXG4gIH1dLFxuICBjOiBbeyAvL2M9SU4gSVA0IDEwLjQ3LjE5Ny4yNlxuICAgICAgbmFtZTogJ2Nvbm5lY3Rpb24nLFxuICAgICAgcmVnOiAvXklOIElQKFxcZCkgKFxcUyopLyxcbiAgICAgIG5hbWVzOiBbJ3ZlcnNpb24nLCAnaXAnXSxcbiAgICAgIGZvcm1hdDogXCJJTiBJUCVkICVzXCJcbiAgfV0sXG4gIGI6IFt7IC8vYj1BUzo0MDAwXG4gICAgICBwdXNoOiAnYmFuZHdpZHRoJyxcbiAgICAgIHJlZzogL14oVElBU3xBU3xDVHxSUnxSUyk6KFxcZCopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbGltaXQnXSxcbiAgICAgIGZvcm1hdDogXCIlczolc1wiXG4gIH1dLFxuICBtOiBbeyAvL209dmlkZW8gNTE3NDQgUlRQL0FWUCAxMjYgOTcgOTggMzQgMzFcbiAgICAgIC8vIE5COiBzcGVjaWFsIC0gcHVzaGVzIHRvIHNlc3Npb25cbiAgICAgIC8vIFRPRE86IHJ0cC9mbXRwIHNob3VsZCBiZSBmaWx0ZXJlZCBieSB0aGUgcGF5bG9hZHMgZm91bmQgaGVyZT9cbiAgICAgIHJlZzogL14oXFx3KikgKFxcZCopIChbXFx3XFwvXSopKD86ICguKikpPy8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ3BvcnQnLCAncHJvdG9jb2wnLCAncGF5bG9hZHMnXSxcbiAgICAgIGZvcm1hdDogXCIlcyAlZCAlcyAlc1wiXG4gIH1dLFxuICBhOiBbXG4gICAgeyAvL2E9cnRwbWFwOjExMCBvcHVzLzQ4MDAwLzJcbiAgICAgIHB1c2g6ICdydHAnLFxuICAgICAgcmVnOiAvXnJ0cG1hcDooXFxkKikgKFtcXHdcXC1dKikoPzpcXHMqXFwvKFxcZCopKD86XFxzKlxcLyhcXFMqKSk/KT8vLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb2RlYycsICdyYXRlJywgJ2VuY29kaW5nJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5lbmNvZGluZykgP1xuICAgICAgICAgIFwicnRwbWFwOiVkICVzLyVzLyVzXCI6XG4gICAgICAgICAgby5yYXRlID9cbiAgICAgICAgICBcInJ0cG1hcDolZCAlcy8lc1wiOlxuICAgICAgICAgIFwicnRwbWFwOiVkICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Zm10cDoxMDggcHJvZmlsZS1sZXZlbC1pZD0yNDtvYmplY3Q9MjM7Yml0cmF0ZT02NDAwMFxuICAgICAgLy9hPWZtdHA6MTExIG1pbnB0aW1lPTEwOyB1c2VpbmJhbmRmZWM9MVxuICAgICAgcHVzaDogJ2ZtdHAnLFxuICAgICAgcmVnOiAvXmZtdHA6KFxcZCopIChbXFxTfCBdKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb25maWcnXSxcbiAgICAgIGZvcm1hdDogXCJmbXRwOiVkICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWNvbnRyb2w6c3RyZWFtaWQ9MFxuICAgICAgICBuYW1lOiAnY29udHJvbCcsXG4gICAgICAgIHJlZzogL15jb250cm9sOiguKikvLFxuICAgICAgICBmb3JtYXQ6IFwiY29udHJvbDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwOjY1MTc5IElOIElQNCAxOTMuODQuNzcuMTk0XG4gICAgICBuYW1lOiAncnRjcCcsXG4gICAgICByZWc6IC9ecnRjcDooXFxkKikoPzogKFxcUyopIElQKFxcZCkgKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsncG9ydCcsICduZXRUeXBlJywgJ2lwVmVyJywgJ2FkZHJlc3MnXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmFkZHJlc3MgIT0gbnVsbCkgP1xuICAgICAgICAgIFwicnRjcDolZCAlcyBJUCVkICVzXCI6XG4gICAgICAgICAgXCJydGNwOiVkXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IHRyci1pbnQgMTAwXG4gICAgICBwdXNoOiAncnRjcEZiVHJySW50JyxcbiAgICAgIHJlZzogL15ydGNwLWZiOihcXCp8XFxkKikgdHJyLWludCAoXFxkKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICd2YWx1ZSddLFxuICAgICAgZm9ybWF0OiBcInJ0Y3AtZmI6JWQgdHJyLWludCAlZFwiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IG5hY2sgcnBzaVxuICAgICAgcHVzaDogJ3J0Y3BGYicsXG4gICAgICByZWc6IC9ecnRjcC1mYjooXFwqfFxcZCopIChbXFx3LV9dKikoPzogKFtcXHctX10qKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAndHlwZScsICdzdWJ0eXBlJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zdWJ0eXBlICE9IG51bGwpID9cbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXNcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPWV4dG1hcDoyIHVybjppZXRmOnBhcmFtczpydHAtaGRyZXh0OnRvZmZzZXRcbiAgICAgIC8vYT1leHRtYXA6MS9yZWN2b25seSBVUkktZ3BzLXN0cmluZ1xuICAgICAgcHVzaDogJ2V4dCcsXG4gICAgICByZWc6IC9eZXh0bWFwOihbXFx3X1xcL10qKSAoXFxTKikoPzogKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsndmFsdWUnLCAndXJpJywgJ2NvbmZpZyddLCAvLyB2YWx1ZSBtYXkgaW5jbHVkZSBcIi9kaXJlY3Rpb25cIiBzdWZmaXhcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmNvbmZpZyAhPSBudWxsKSA/XG4gICAgICAgICAgXCJleHRtYXA6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcImV4dG1hcDolcyAlc1wiO1xuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAgLy9hPWNyeXB0bzoxIEFFU19DTV8xMjhfSE1BQ19TSEExXzgwIGlubGluZTpQUzF1UUNWZWVDRkNhblZtY2prcFB5d2pOV2hjWUQwbVhYdHhhVkJSfDJeMjB8MTozMlxuICAgICAgcHVzaDogJ2NyeXB0bycsXG4gICAgICByZWc6IC9eY3J5cHRvOihcXGQqKSAoW1xcd19dKikgKFxcUyopKD86IChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2lkJywgJ3N1aXRlJywgJ2NvbmZpZycsICdzZXNzaW9uQ29uZmlnJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zZXNzaW9uQ29uZmlnICE9IG51bGwpID9cbiAgICAgICAgICBcImNyeXB0bzolZCAlcyAlcyAlc1wiOlxuICAgICAgICAgIFwiY3J5cHRvOiVkICVzICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1zZXR1cDphY3RwYXNzXG4gICAgICBuYW1lOiAnc2V0dXAnLFxuICAgICAgcmVnOiAvXnNldHVwOihcXHcqKS8sXG4gICAgICBmb3JtYXQ6IFwic2V0dXA6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9bWlkOjFcbiAgICAgIG5hbWU6ICdtaWQnLFxuICAgICAgcmVnOiAvXm1pZDooW15cXHNdKikvLFxuICAgICAgZm9ybWF0OiBcIm1pZDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkOjBjOGIwNjRkLWQ4MDctNDNiNC1iNDM0LWY5MmE4ODlkODU4NyA5ODE3ODY4NS1kNDA5LTQ2ZTAtOGUxNi03ZWYwZGIwZGI2NGFcbiAgICAgIG5hbWU6ICdtc2lkJyxcbiAgICAgIHJlZzogL15tc2lkOiguKikvLFxuICAgICAgZm9ybWF0OiBcIm1zaWQ6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9cHRpbWU6MjBcbiAgICAgIG5hbWU6ICdwdGltZScsXG4gICAgICByZWc6IC9ecHRpbWU6KFxcZCopLyxcbiAgICAgIGZvcm1hdDogXCJwdGltZTolZFwiXG4gICAgfSxcbiAgICB7IC8vYT1tYXhwdGltZTo2MFxuICAgICAgbmFtZTogJ21heHB0aW1lJyxcbiAgICAgIHJlZzogL15tYXhwdGltZTooXFxkKikvLFxuICAgICAgZm9ybWF0OiBcIm1heHB0aW1lOiVkXCJcbiAgICB9LFxuICAgIHsgLy9hPXNlbmRyZWN2XG4gICAgICBuYW1lOiAnZGlyZWN0aW9uJyxcbiAgICAgIHJlZzogL14oc2VuZHJlY3Z8cmVjdm9ubHl8c2VuZG9ubHl8aW5hY3RpdmUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLWxpdGVcbiAgICAgIG5hbWU6ICdpY2VsaXRlJyxcbiAgICAgIHJlZzogL14oaWNlLWxpdGUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLXVmcmFnOkY3Z0lcbiAgICAgIG5hbWU6ICdpY2VVZnJhZycsXG4gICAgICByZWc6IC9eaWNlLXVmcmFnOihcXFMqKS8sXG4gICAgICBmb3JtYXQ6IFwiaWNlLXVmcmFnOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1wd2Q6eDljbWwvWXppY2hWMitYbGhpTXU4Z1xuICAgICAgbmFtZTogJ2ljZVB3ZCcsXG4gICAgICByZWc6IC9eaWNlLXB3ZDooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1wd2Q6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9ZmluZ2VycHJpbnQ6U0hBLTEgMDA6MTE6MjI6MzM6NDQ6NTU6NjY6Nzc6ODg6OTk6QUE6QkI6Q0M6REQ6RUU6RkY6MDA6MTE6MjI6MzNcbiAgICAgIG5hbWU6ICdmaW5nZXJwcmludCcsXG4gICAgICByZWc6IC9eZmluZ2VycHJpbnQ6KFxcUyopIChcXFMqKS8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ2hhc2gnXSxcbiAgICAgIGZvcm1hdDogXCJmaW5nZXJwcmludDolcyAlc1wiXG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Y2FuZGlkYXRlOjAgMSBVRFAgMjExMzY2NzMyNyAyMDMuMC4xMTMuMSA1NDQwMCB0eXAgaG9zdFxuICAgICAgLy9hPWNhbmRpZGF0ZToxMTYyODc1MDgxIDEgdWRwIDIxMTM5MzcxNTEgMTkyLjE2OC4zNC43NSA2MDAxNyB0eXAgaG9zdCBnZW5lcmF0aW9uIDBcbiAgICAgIC8vYT1jYW5kaWRhdGU6MzI4OTkxMjk1NyAyIHVkcCAxODQ1NTAxNjk1IDE5My44NC43Ny4xOTQgNjAwMTcgdHlwIHNyZmx4IHJhZGRyIDE5Mi4xNjguMzQuNzUgcnBvcnQgNjAwMTcgZ2VuZXJhdGlvbiAwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjIyOTgxNTYyMCAxIHRjcCAxNTE4MjgwNDQ3IDE5Mi4xNjguMTUwLjE5IDYwMDE3IHR5cCBob3N0IHRjcHR5cGUgYWN0aXZlIGdlbmVyYXRpb24gMFxuICAgICAgLy9hPWNhbmRpZGF0ZTozMjg5OTEyOTU3IDIgdGNwIDE4NDU1MDE2OTUgMTkzLjg0Ljc3LjE5NCA2MDAxNyB0eXAgc3JmbHggcmFkZHIgMTkyLjE2OC4zNC43NSBycG9ydCA2MDAxNyB0Y3B0eXBlIHBhc3NpdmUgZ2VuZXJhdGlvbiAwXG4gICAgICBwdXNoOidjYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL15jYW5kaWRhdGU6KFxcUyopIChcXGQqKSAoXFxTKikgKFxcZCopIChcXFMqKSAoXFxkKikgdHlwIChcXFMqKSg/OiByYWRkciAoXFxTKikgcnBvcnQgKFxcZCopKT8oPzogdGNwdHlwZSAoXFxTKikpPyg/OiBnZW5lcmF0aW9uIChcXGQqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2ZvdW5kYXRpb24nLCAnY29tcG9uZW50JywgJ3RyYW5zcG9ydCcsICdwcmlvcml0eScsICdpcCcsICdwb3J0JywgJ3R5cGUnLCAncmFkZHInLCAncnBvcnQnLCAndGNwdHlwZScsICdnZW5lcmF0aW9uJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHZhciBzdHIgPSBcImNhbmRpZGF0ZTolcyAlZCAlcyAlZCAlcyAlZCB0eXAgJXNcIjtcblxuICAgICAgICBzdHIgKz0gKG8ucmFkZHIgIT0gbnVsbCkgPyBcIiByYWRkciAlcyBycG9ydCAlZFwiIDogXCIldiV2XCI7XG5cbiAgICAgICAgLy8gTkI6IGNhbmRpZGF0ZSBoYXMgdGhyZWUgb3B0aW9uYWwgY2h1bmtzLCBzbyAldm9pZCBtaWRkbGVzIG9uZSBpZiBpdCdzIG1pc3NpbmdcbiAgICAgICAgc3RyICs9IChvLnRjcHR5cGUgIT0gbnVsbCkgPyBcIiB0Y3B0eXBlICVzXCIgOiBcIiV2XCI7XG5cbiAgICAgICAgaWYgKG8uZ2VuZXJhdGlvbiAhPSBudWxsKSB7XG4gICAgICAgICAgc3RyICs9IFwiIGdlbmVyYXRpb24gJWRcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9ZW5kLW9mLWNhbmRpZGF0ZXMgKGtlZXAgYWZ0ZXIgdGhlIGNhbmRpZGF0ZXMgbGluZSBmb3IgcmVhZGFiaWxpdHkpXG4gICAgICBuYW1lOiAnZW5kT2ZDYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL14oZW5kLW9mLWNhbmRpZGF0ZXMpL1xuICAgIH0sXG4gICAgeyAvL2E9cmVtb3RlLWNhbmRpZGF0ZXM6MSAyMDMuMC4xMTMuMSA1NDQwMCAyIDIwMy4wLjExMy4xIDU0NDAxIC4uLlxuICAgICAgbmFtZTogJ3JlbW90ZUNhbmRpZGF0ZXMnLFxuICAgICAgcmVnOiAvXnJlbW90ZS1jYW5kaWRhdGVzOiguKikvLFxuICAgICAgZm9ybWF0OiBcInJlbW90ZS1jYW5kaWRhdGVzOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1vcHRpb25zOmdvb2dsZS1pY2VcbiAgICAgIG5hbWU6ICdpY2VPcHRpb25zJyxcbiAgICAgIHJlZzogL15pY2Utb3B0aW9uczooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1vcHRpb25zOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXNzcmM6MjU2NjEwNzU2OSBjbmFtZTp0OVlVOE0xVXhURjhZMUExXG4gICAgICBwdXNoOiBcInNzcmNzXCIsXG4gICAgICByZWc6IC9ec3NyYzooXFxkKikgKFtcXHdfXSopOiguKikvLFxuICAgICAgbmFtZXM6IFsnaWQnLCAnYXR0cmlidXRlJywgJ3ZhbHVlJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYzolZCAlczolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1zc3JjLWdyb3VwOkZFQyAxIDJcbiAgICAgIHB1c2g6IFwic3NyY0dyb3Vwc1wiLFxuICAgICAgcmVnOiAvXnNzcmMtZ3JvdXA6KFxcdyopICguKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWNzJywgJ3NzcmNzJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYy1ncm91cDolcyAlc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkLXNlbWFudGljOiBXTVMgSnZsYW01WDNTWDFPUDZwbjIweldvZ3ZhS0p6NUhqZjlPbmxWXG4gICAgICBuYW1lOiBcIm1zaWRTZW1hbnRpY1wiLFxuICAgICAgcmVnOiAvXm1zaWQtc2VtYW50aWM6XFxzPyhcXHcqKSAoXFxTKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWMnLCAndG9rZW4nXSxcbiAgICAgIGZvcm1hdDogXCJtc2lkLXNlbWFudGljOiAlcyAlc1wiIC8vIHNwYWNlIGFmdGVyIFwiOlwiIGlzIG5vdCBhY2NpZGVudGFsXG4gICAgfSxcbiAgICB7IC8vYT1ncm91cDpCVU5ETEUgYXVkaW8gdmlkZW9cbiAgICAgIHB1c2g6ICdncm91cHMnLFxuICAgICAgcmVnOiAvXmdyb3VwOihcXHcqKSAoLiopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbWlkcyddLFxuICAgICAgZm9ybWF0OiBcImdyb3VwOiVzICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtbXV4XG4gICAgICBuYW1lOiAncnRjcE11eCcsXG4gICAgICByZWc6IC9eKHJ0Y3AtbXV4KS9cbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtcnNpemVcbiAgICAgIG5hbWU6ICdydGNwUnNpemUnLFxuICAgICAgcmVnOiAvXihydGNwLXJzaXplKS9cbiAgICB9LFxuICAgIHsgLy8gYW55IGE9IHRoYXQgd2UgZG9uJ3QgdW5kZXJzdGFuZCBpcyBrZXB0cyB2ZXJiYXRpbSBvbiBtZWRpYS5pbnZhbGlkXG4gICAgICBwdXNoOiAnaW52YWxpZCcsXG4gICAgICBuYW1lczogW1widmFsdWVcIl1cbiAgICB9XG4gIF1cbn07XG5cbi8vIHNldCBzZW5zaWJsZSBkZWZhdWx0cyB0byBhdm9pZCBwb2xsdXRpbmcgdGhlIGdyYW1tYXIgd2l0aCBib3JpbmcgZGV0YWlsc1xuT2JqZWN0LmtleXMoZ3JhbW1hcikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gIHZhciBvYmpzID0gZ3JhbW1hcltrZXldO1xuICBvYmpzLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgIGlmICghb2JqLnJlZykge1xuICAgICAgb2JqLnJlZyA9IC8oLiopLztcbiAgICB9XG4gICAgaWYgKCFvYmouZm9ybWF0KSB7XG4gICAgICBvYmouZm9ybWF0ID0gXCIlc1wiO1xuICAgIH1cbiAgfSk7XG59KTtcbiIsInZhciBwYXJzZXIgPSByZXF1aXJlKCcuL3BhcnNlcicpO1xudmFyIHdyaXRlciA9IHJlcXVpcmUoJy4vd3JpdGVyJyk7XG5cbmV4cG9ydHMud3JpdGUgPSB3cml0ZXI7XG5leHBvcnRzLnBhcnNlID0gcGFyc2VyLnBhcnNlO1xuZXhwb3J0cy5wYXJzZUZtdHBDb25maWcgPSBwYXJzZXIucGFyc2VGbXRwQ29uZmlnO1xuZXhwb3J0cy5wYXJzZVBheWxvYWRzID0gcGFyc2VyLnBhcnNlUGF5bG9hZHM7XG5leHBvcnRzLnBhcnNlUmVtb3RlQ2FuZGlkYXRlcyA9IHBhcnNlci5wYXJzZVJlbW90ZUNhbmRpZGF0ZXM7XG4iLCJ2YXIgdG9JbnRJZkludCA9IGZ1bmN0aW9uICh2KSB7XG4gIHJldHVybiBTdHJpbmcoTnVtYmVyKHYpKSA9PT0gdiA/IE51bWJlcih2KSA6IHY7XG59O1xuXG52YXIgYXR0YWNoUHJvcGVydGllcyA9IGZ1bmN0aW9uIChtYXRjaCwgbG9jYXRpb24sIG5hbWVzLCByYXdOYW1lKSB7XG4gIGlmIChyYXdOYW1lICYmICFuYW1lcykge1xuICAgIGxvY2F0aW9uW3Jhd05hbWVdID0gdG9JbnRJZkludChtYXRjaFsxXSk7XG4gIH1cbiAgZWxzZSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgaWYgKG1hdGNoW2krMV0gIT0gbnVsbCkge1xuICAgICAgICBsb2NhdGlvbltuYW1lc1tpXV0gPSB0b0ludElmSW50KG1hdGNoW2krMV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxudmFyIHBhcnNlUmVnID0gZnVuY3Rpb24gKG9iaiwgbG9jYXRpb24sIGNvbnRlbnQpIHtcbiAgdmFyIG5lZWRzQmxhbmsgPSBvYmoubmFtZSAmJiBvYmoubmFtZXM7XG4gIGlmIChvYmoucHVzaCAmJiAhbG9jYXRpb25bb2JqLnB1c2hdKSB7XG4gICAgbG9jYXRpb25bb2JqLnB1c2hdID0gW107XG4gIH1cbiAgZWxzZSBpZiAobmVlZHNCbGFuayAmJiAhbG9jYXRpb25bb2JqLm5hbWVdKSB7XG4gICAgbG9jYXRpb25bb2JqLm5hbWVdID0ge307XG4gIH1cbiAgdmFyIGtleUxvY2F0aW9uID0gb2JqLnB1c2ggP1xuICAgIHt9IDogIC8vIGJsYW5rIG9iamVjdCB0aGF0IHdpbGwgYmUgcHVzaGVkXG4gICAgbmVlZHNCbGFuayA/IGxvY2F0aW9uW29iai5uYW1lXSA6IGxvY2F0aW9uOyAvLyBvdGhlcndpc2UsIG5hbWVkIGxvY2F0aW9uIG9yIHJvb3RcblxuICBhdHRhY2hQcm9wZXJ0aWVzKGNvbnRlbnQubWF0Y2gob2JqLnJlZyksIGtleUxvY2F0aW9uLCBvYmoubmFtZXMsIG9iai5uYW1lKTtcblxuICBpZiAob2JqLnB1c2gpIHtcbiAgICBsb2NhdGlvbltvYmoucHVzaF0ucHVzaChrZXlMb2NhdGlvbik7XG4gIH1cbn07XG5cbnZhciBncmFtbWFyID0gcmVxdWlyZSgnLi9ncmFtbWFyJyk7XG52YXIgdmFsaWRMaW5lID0gUmVnRXhwLnByb3RvdHlwZS50ZXN0LmJpbmQoL14oW2Etel0pPSguKikvKTtcblxuZXhwb3J0cy5wYXJzZSA9IGZ1bmN0aW9uIChzZHApIHtcbiAgdmFyIHNlc3Npb24gPSB7fVxuICAgICwgbWVkaWEgPSBbXVxuICAgICwgbG9jYXRpb24gPSBzZXNzaW9uOyAvLyBwb2ludHMgYXQgd2hlcmUgcHJvcGVydGllcyBnbyB1bmRlciAob25lIG9mIHRoZSBhYm92ZSlcblxuICAvLyBwYXJzZSBsaW5lcyB3ZSB1bmRlcnN0YW5kXG4gIHNkcC5zcGxpdCgvKFxcclxcbnxcXHJ8XFxuKS8pLmZpbHRlcih2YWxpZExpbmUpLmZvckVhY2goZnVuY3Rpb24gKGwpIHtcbiAgICB2YXIgdHlwZSA9IGxbMF07XG4gICAgdmFyIGNvbnRlbnQgPSBsLnNsaWNlKDIpO1xuICAgIGlmICh0eXBlID09PSAnbScpIHtcbiAgICAgIG1lZGlhLnB1c2goe3J0cDogW10sIGZtdHA6IFtdfSk7XG4gICAgICBsb2NhdGlvbiA9IG1lZGlhW21lZGlhLmxlbmd0aC0xXTsgLy8gcG9pbnQgYXQgbGF0ZXN0IG1lZGlhIGxpbmVcbiAgICB9XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IChncmFtbWFyW3R5cGVdIHx8IFtdKS5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgdmFyIG9iaiA9IGdyYW1tYXJbdHlwZV1bal07XG4gICAgICBpZiAob2JqLnJlZy50ZXN0KGNvbnRlbnQpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVJlZyhvYmosIGxvY2F0aW9uLCBjb250ZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHNlc3Npb24ubWVkaWEgPSBtZWRpYTsgLy8gbGluayBpdCB1cFxuICByZXR1cm4gc2Vzc2lvbjtcbn07XG5cbnZhciBmbXRwUmVkdWNlciA9IGZ1bmN0aW9uIChhY2MsIGV4cHIpIHtcbiAgdmFyIHMgPSBleHByLnNwbGl0KCc9Jyk7XG4gIGlmIChzLmxlbmd0aCA9PT0gMikge1xuICAgIGFjY1tzWzBdXSA9IHRvSW50SWZJbnQoc1sxXSk7XG4gIH1cbiAgcmV0dXJuIGFjYztcbn07XG5cbmV4cG9ydHMucGFyc2VGbXRwQ29uZmlnID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KC9cXDtcXHM/LykucmVkdWNlKGZtdHBSZWR1Y2VyLCB7fSk7XG59O1xuXG5leHBvcnRzLnBhcnNlUGF5bG9hZHMgPSBmdW5jdGlvbiAoc3RyKSB7XG4gIHJldHVybiBzdHIuc3BsaXQoJyAnKS5tYXAoTnVtYmVyKTtcbn07XG5cbmV4cG9ydHMucGFyc2VSZW1vdGVDYW5kaWRhdGVzID0gZnVuY3Rpb24gKHN0cikge1xuICB2YXIgY2FuZGlkYXRlcyA9IFtdO1xuICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoJyAnKS5tYXAodG9JbnRJZkludCk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpICs9IDMpIHtcbiAgICBjYW5kaWRhdGVzLnB1c2goe1xuICAgICAgY29tcG9uZW50OiBwYXJ0c1tpXSxcbiAgICAgIGlwOiBwYXJ0c1tpICsgMV0sXG4gICAgICBwb3J0OiBwYXJ0c1tpICsgMl1cbiAgICB9KTtcbiAgfVxuICByZXR1cm4gY2FuZGlkYXRlcztcbn07XG4iLCJ2YXIgZ3JhbW1hciA9IHJlcXVpcmUoJy4vZ3JhbW1hcicpO1xuXG4vLyBjdXN0b21pemVkIHV0aWwuZm9ybWF0IC0gZGlzY2FyZHMgZXhjZXNzIGFyZ3VtZW50cyBhbmQgY2FuIHZvaWQgbWlkZGxlIG9uZXNcbnZhciBmb3JtYXRSZWdFeHAgPSAvJVtzZHYlXS9nO1xudmFyIGZvcm1hdCA9IGZ1bmN0aW9uIChmb3JtYXRTdHIpIHtcbiAgdmFyIGkgPSAxO1xuICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgdmFyIGxlbiA9IGFyZ3MubGVuZ3RoO1xuICByZXR1cm4gZm9ybWF0U3RyLnJlcGxhY2UoZm9ybWF0UmVnRXhwLCBmdW5jdGlvbiAoeCkge1xuICAgIGlmIChpID49IGxlbikge1xuICAgICAgcmV0dXJuIHg7IC8vIG1pc3NpbmcgYXJndW1lbnRcbiAgICB9XG4gICAgdmFyIGFyZyA9IGFyZ3NbaV07XG4gICAgaSArPSAxO1xuICAgIHN3aXRjaCAoeCkge1xuICAgICAgY2FzZSAnJSUnOlxuICAgICAgICByZXR1cm4gJyUnO1xuICAgICAgY2FzZSAnJXMnOlxuICAgICAgICByZXR1cm4gU3RyaW5nKGFyZyk7XG4gICAgICBjYXNlICclZCc6XG4gICAgICAgIHJldHVybiBOdW1iZXIoYXJnKTtcbiAgICAgIGNhc2UgJyV2JzpcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfSk7XG4gIC8vIE5COiB3ZSBkaXNjYXJkIGV4Y2VzcyBhcmd1bWVudHMgLSB0aGV5IGFyZSB0eXBpY2FsbHkgdW5kZWZpbmVkIGZyb20gbWFrZUxpbmVcbn07XG5cbnZhciBtYWtlTGluZSA9IGZ1bmN0aW9uICh0eXBlLCBvYmosIGxvY2F0aW9uKSB7XG4gIHZhciBzdHIgPSBvYmouZm9ybWF0IGluc3RhbmNlb2YgRnVuY3Rpb24gP1xuICAgIChvYmouZm9ybWF0KG9iai5wdXNoID8gbG9jYXRpb24gOiBsb2NhdGlvbltvYmoubmFtZV0pKSA6XG4gICAgb2JqLmZvcm1hdDtcblxuICB2YXIgYXJncyA9IFt0eXBlICsgJz0nICsgc3RyXTtcbiAgaWYgKG9iai5uYW1lcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqLm5hbWVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICB2YXIgbiA9IG9iai5uYW1lc1tpXTtcbiAgICAgIGlmIChvYmoubmFtZSkge1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVdW25dKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgeyAvLyBmb3IgbUxpbmUgYW5kIHB1c2ggYXR0cmlidXRlc1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVzW2ldXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIGFyZ3MucHVzaChsb2NhdGlvbltvYmoubmFtZV0pO1xuICB9XG4gIHJldHVybiBmb3JtYXQuYXBwbHkobnVsbCwgYXJncyk7XG59O1xuXG4vLyBSRkMgc3BlY2lmaWVkIG9yZGVyXG4vLyBUT0RPOiBleHRlbmQgdGhpcyB3aXRoIGFsbCB0aGUgcmVzdFxudmFyIGRlZmF1bHRPdXRlck9yZGVyID0gW1xuICAndicsICdvJywgJ3MnLCAnaScsXG4gICd1JywgJ2UnLCAncCcsICdjJyxcbiAgJ2InLCAndCcsICdyJywgJ3onLCAnYSdcbl07XG52YXIgZGVmYXVsdElubmVyT3JkZXIgPSBbJ2knLCAnYycsICdiJywgJ2EnXTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzZXNzaW9uLCBvcHRzKSB7XG4gIG9wdHMgPSBvcHRzIHx8IHt9O1xuICAvLyBlbnN1cmUgY2VydGFpbiBwcm9wZXJ0aWVzIGV4aXN0XG4gIGlmIChzZXNzaW9uLnZlcnNpb24gPT0gbnVsbCkge1xuICAgIHNlc3Npb24udmVyc2lvbiA9IDA7IC8vIFwidj0wXCIgbXVzdCBiZSB0aGVyZSAob25seSBkZWZpbmVkIHZlcnNpb24gYXRtKVxuICB9XG4gIGlmIChzZXNzaW9uLm5hbWUgPT0gbnVsbCkge1xuICAgIHNlc3Npb24ubmFtZSA9IFwiIFwiOyAvLyBcInM9IFwiIG11c3QgYmUgdGhlcmUgaWYgbm8gbWVhbmluZ2Z1bCBuYW1lIHNldFxuICB9XG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBpZiAobUxpbmUucGF5bG9hZHMgPT0gbnVsbCkge1xuICAgICAgbUxpbmUucGF5bG9hZHMgPSBcIlwiO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIG91dGVyT3JkZXIgPSBvcHRzLm91dGVyT3JkZXIgfHwgZGVmYXVsdE91dGVyT3JkZXI7XG4gIHZhciBpbm5lck9yZGVyID0gb3B0cy5pbm5lck9yZGVyIHx8IGRlZmF1bHRJbm5lck9yZGVyO1xuICB2YXIgc2RwID0gW107XG5cbiAgLy8gbG9vcCB0aHJvdWdoIG91dGVyT3JkZXIgZm9yIG1hdGNoaW5nIHByb3BlcnRpZXMgb24gc2Vzc2lvblxuICBvdXRlck9yZGVyLmZvckVhY2goZnVuY3Rpb24gKHR5cGUpIHtcbiAgICBncmFtbWFyW3R5cGVdLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgICAgaWYgKG9iai5uYW1lIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoubmFtZV0gIT0gbnVsbCkge1xuICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIHNlc3Npb24pKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoucHVzaF0gIT0gbnVsbCkge1xuICAgICAgICBzZXNzaW9uW29iai5wdXNoXS5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIHNkcC5wdXNoKG1ha2VMaW5lKHR5cGUsIG9iaiwgZWwpKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIHRoZW4gZm9yIGVhY2ggbWVkaWEgbGluZSwgZm9sbG93IHRoZSBpbm5lck9yZGVyXG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBzZHAucHVzaChtYWtlTGluZSgnbScsIGdyYW1tYXIubVswXSwgbUxpbmUpKTtcblxuICAgIGlubmVyT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAodHlwZSkge1xuICAgICAgZ3JhbW1hclt0eXBlXS5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgaWYgKG9iai5uYW1lIGluIG1MaW5lICYmIG1MaW5lW29iai5uYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBtTGluZSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIG1MaW5lICYmIG1MaW5lW29iai5wdXNoXSAhPSBudWxsKSB7XG4gICAgICAgICAgbUxpbmVbb2JqLnB1c2hdLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIGVsKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gc2RwLmpvaW4oJ1xcclxcbicpICsgJ1xcclxcbic7XG59O1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGFycmF5RXF1YWxzKGFycmF5KSB7XG4gICAgLy8gaWYgdGhlIG90aGVyIGFycmF5IGlzIGEgZmFsc3kgdmFsdWUsIHJldHVyblxuICAgIGlmICghYXJyYXkpXG4gICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgIC8vIGNvbXBhcmUgbGVuZ3RocyAtIGNhbiBzYXZlIGEgbG90IG9mIHRpbWVcbiAgICBpZiAodGhpcy5sZW5ndGggIT0gYXJyYXkubGVuZ3RoKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgbmVzdGVkIGFycmF5c1xuICAgICAgICBpZiAodGhpc1tpXSBpbnN0YW5jZW9mIEFycmF5ICYmIGFycmF5W2ldIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIHJlY3Vyc2UgaW50byB0aGUgbmVzdGVkIGFycmF5c1xuICAgICAgICAgICAgaWYgKCFhcnJheUVxdWFscy5hcHBseSh0aGlzW2ldLCBbYXJyYXlbaV1dKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpc1tpXSAhPSBhcnJheVtpXSkge1xuICAgICAgICAgICAgLy8gV2FybmluZyAtIHR3byBkaWZmZXJlbnQgb2JqZWN0IGluc3RhbmNlcyB3aWxsIG5ldmVyIGJlIGVxdWFsOlxuICAgICAgICAgICAgLy8ge3g6MjB9ICE9IHt4OjIwfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufTtcblxuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnRzLkludGVyb3AgPSByZXF1aXJlKCcuL2ludGVyb3AnKTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyogZ2xvYmFsIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbiAqL1xuLyogZ2xvYmFsIFJUQ0ljZUNhbmRpZGF0ZSAqL1xuLyoganNoaW50IC1XMDk3ICovXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIHRyYW5zZm9ybSA9IHJlcXVpcmUoJy4vdHJhbnNmb3JtJyk7XG52YXIgYXJyYXlFcXVhbHMgPSByZXF1aXJlKCcuL2FycmF5LWVxdWFscycpO1xuXG5mdW5jdGlvbiBJbnRlcm9wKCkge1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtYXAgaG9sZHMgdGhlIG1vc3QgcmVjZW50IFVuaWZpZWQgUGxhbiBvZmZlci9hbnN3ZXIgU0RQIHRoYXQgd2FzXG4gICAgICogY29udmVydGVkIHRvIFBsYW4gQiwgd2l0aCB0aGUgU0RQIHR5cGUgKCdvZmZlcicgb3IgJ2Fuc3dlcicpIGFzIGtleXMgYW5kXG4gICAgICogdGhlIFNEUCBzdHJpbmcgYXMgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHR5cGUge3t9fVxuICAgICAqL1xuICAgIHRoaXMuY2FjaGUgPSB7XG4gICAgICAgIG1sQjJVTWFwIDoge30sXG4gICAgICAgIG1sVTJCTWFwIDoge31cbiAgICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEludGVyb3A7XG5cbi8qKlxuICogQ2hhbmdlcyB0aGUgY2FuZGlkYXRlIGFyZ3MgdG8gbWF0Y2ggd2l0aCB0aGUgcmVsYXRlZCBVbmlmaWVkIFBsYW5cbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuY2FuZGlkYXRlVG9VbmlmaWVkUGxhbiA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHZhciBjYW5kID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuXG4gICAgY2FuZC5zZHBNTGluZUluZGV4ID0gdGhpcy5jYWNoZS5tbEIyVU1hcFtjYW5kLnNkcE1MaW5lSW5kZXhdO1xuICAgIC8qIFRPRE86IGNoYW5nZSBzZHBNaWQgdG8gKGF1ZGlvfHZpZGVvKS1TU1JDICovXG5cbiAgICByZXR1cm4gY2FuZDtcbn07XG5cbi8qKlxuICogQ2hhbmdlcyB0aGUgY2FuZGlkYXRlIGFyZ3MgdG8gbWF0Y2ggd2l0aCB0aGUgcmVsYXRlZCBQbGFuIEJcbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuY2FuZGlkYXRlVG9QbGFuQiA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHZhciBjYW5kID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuXG4gICAgaWYgKGNhbmQuc2RwTWlkLmluZGV4T2YoJ2F1ZGlvJykgPT09IDApIHtcbiAgICAgIGNhbmQuc2RwTWlkID0gJ2F1ZGlvJztcbiAgICB9IGVsc2UgaWYgKGNhbmQuc2RwTWlkLmluZGV4T2YoJ3ZpZGVvJykgPT09IDApIHtcbiAgICAgIGNhbmQuc2RwTWlkID0gJ3ZpZGVvJztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5kaWRhdGUgd2l0aCAnICsgY2FuZC5zZHBNaWQgKyAnIG5vdCBhbGxvd2VkJyk7XG4gICAgfVxuXG4gICAgY2FuZC5zZHBNTGluZUluZGV4ID0gdGhpcy5jYWNoZS5tbFUyQk1hcFtjYW5kLnNkcE1MaW5lSW5kZXhdO1xuXG4gICAgcmV0dXJuIGNhbmQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBtLWxpbmUgd2l0aCB0aGUgZ2l2ZW4gbWVkaWEgdHlwZSBhbmQgd2l0aCBhXG4gKiBkaXJlY3Rpb24gd2hpY2ggYWxsb3dzIHNlbmRpbmcsIGluIHRoZSBsYXN0IFVuaWZpZWQgUGxhbiBkZXNjcmlwdGlvbiB3aXRoXG4gKiB0eXBlIFwiYW5zd2VyXCIgY29udmVydGVkIHRvIFBsYW4gQi4gUmV0dXJucyB7bnVsbH0gaWYgdGhlcmUgaXMgbm8gc2F2ZWRcbiAqIGFuc3dlciwgb3IgaWYgbm9uZSBvZiBpdHMgbS1saW5lcyB3aXRoIHRoZSBnaXZlbiB0eXBlIGFsbG93IHNlbmRpbmcuXG4gKiBAcGFyYW0gdHlwZSB0aGUgbWVkaWEgdHlwZSAoXCJhdWRpb1wiIG9yIFwidmlkZW9cIikuXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyID0gZnVuY3Rpb24odHlwZSkge1xuICAgIGlmICghdGhpcy5jYWNoZS5hbnN3ZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UodGhpcy5jYWNoZS5hbnN3ZXIpO1xuICAgIGlmIChzZXNzaW9uICYmIHNlc3Npb24ubWVkaWEgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSl7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vzc2lvbi5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHNlc3Npb24ubWVkaWFbaV0udHlwZSA9PSB0eXBlICYmXG4gICAgICAgICAgICAgICAgKCFzZXNzaW9uLm1lZGlhW2ldLmRpcmVjdGlvbiAvKiBkZWZhdWx0IHRvIHNlbmRyZWN2ICovIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn07XG5cbi8qKlxuICogVGhpcyBtZXRob2QgdHJhbnNmb3JtcyBhIFVuaWZpZWQgUGxhbiBTRFAgdG8gYW4gZXF1aXZhbGVudCBQbGFuIEIgU0RQLiBBXG4gKiBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIHRyYW5zZm9ybXMgdGhlIFNEUCB0byBQbGFuIEIgYmVmb3JlIHBhc3NpbmcgaXQgdG8gdGhlXG4gKiBhcHBsaWNhdGlvbi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvUGxhbkIgPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBPYmplY3RpZnkgdGhlIFNEUCBmb3IgZWFzaWVyIG1hbmlwdWxhdGlvbi5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFVuaWZpZWQgUGxhbiBTRFAuIFBsYW4gQlxuICAgIC8vIFNEUCBoYXMgYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA8PSAzICYmIHNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBVbmlmaWVkIFBsYW4uJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vI2VuZHJlZ2lvblxuXG4gICAgLy8gSEFDSyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMTEzNDQzXG4gICAgdmFyIHNkcCA9IGRlc2Muc2RwO1xuICAgIHZhciByZXdyaXRlID0gZmFsc2U7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB1TGluZSA9IHNlc3Npb24ubWVkaWFbaV07XG4gICAgICAgIHVMaW5lLnJ0cC5mb3JFYWNoKGZ1bmN0aW9uKHJ0cCkge1xuICAgICAgICAgICAgaWYgKHJ0cC5jb2RlYyA9PT0gJ05VTEwnKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHJld3JpdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBvZmZlciA9IHRyYW5zZm9ybS5wYXJzZShzZWxmLmNhY2hlLm9mZmVyKTtcbiAgICAgICAgICAgICAgICBydHAuY29kZWMgPSBvZmZlci5tZWRpYVtpXS5ydHBbMF0uY29kZWM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAocmV3cml0ZSkge1xuICAgICAgICBzZHAgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG4gICAgfVxuXG4gICAgLy8gVW5pZmllZCBQbGFuIFNEUCBpcyBvdXIgXCJwcmVjaW91c1wiLiBDYWNoZSBpdCBmb3IgbGF0ZXIgdXNlIGluIHRoZSBQbGFuIEJcbiAgICAvLyAtPiBVbmlmaWVkIFBsYW4gdHJhbnNmb3JtYXRpb24uXG4gICAgdGhpcy5jYWNoZVtkZXNjLnR5cGVdID0gc2RwO1xuXG4gICAgLy8jcmVnaW9uIENvbnZlcnQgZnJvbSBVbmlmaWVkIFBsYW4gdG8gUGxhbiBCLlxuXG4gICAgLy8gV2UgcmVidWlsZCB0aGUgc2Vzc2lvbi5tZWRpYSBhcnJheS5cbiAgICB2YXIgbWVkaWEgPSBzZXNzaW9uLm1lZGlhO1xuICAgIHNlc3Npb24ubWVkaWEgPSBbXTtcblxuICAgIC8vIEFzc29jaWF0aXZlIGFycmF5IHRoYXQgbWFwcyBjaGFubmVsIHR5cGVzIHRvIGNoYW5uZWwgb2JqZWN0cyBmb3IgZmFzdFxuICAgIC8vIGFjY2VzcyB0byBjaGFubmVsIG9iamVjdHMgYnkgdGhlaXIgdHlwZSwgZS5nLiB0eXBlMmJsWydhdWRpbyddLT5jaGFubmVsXG4gICAgLy8gb2JqLlxuICAgIHZhciB0eXBlMmJsID0ge307XG5cbiAgICAvLyBVc2VkIHRvIGJ1aWxkIHRoZSBncm91cDpCVU5ETEUgdmFsdWUgYWZ0ZXIgdGhlIGNoYW5uZWxzIGNvbnN0cnVjdGlvblxuICAgIC8vIGxvb3AuXG4gICAgdmFyIHR5cGVzID0gW107XG5cbiAgICBtZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKHVMaW5lKSB7XG4gICAgICAgIC8vIHJ0Y3AtbXV4IGlzIHJlcXVpcmVkIGluIHRoZSBQbGFuIEIgU0RQLlxuICAgICAgICBpZiAoKHR5cGVvZiB1TGluZS5ydGNwTXV4ICE9PSAnc3RyaW5nJyB8fFxuICAgICAgICAgICAgdUxpbmUucnRjcE11eCAhPT0gJ3J0Y3AtbXV4JykgJiZcbiAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29udmVydCB0byBQbGFuIEIgYmVjYXVzZSBtLWxpbmVzICcgK1xuICAgICAgICAgICAgICAgICd3aXRob3V0IHRoZSBydGNwLW11eCBhdHRyaWJ1dGUgd2VyZSBmb3VuZC4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHdlIGRvbid0IGhhdmUgYSBjaGFubmVsIGZvciB0aGlzIHVMaW5lLnR5cGUgT1IgdGhlIHNlbGVjdGVkIGlzXG4gICAgICAgIC8vIGluYWN0aXZlLCB0aGVuIHNlbGVjdCB0aGlzIHVMaW5lIGFzIHRoZSBjaGFubmVsIGJhc2lzLlxuICAgICAgICBpZiAodHlwZW9mIHR5cGUyYmxbdUxpbmUudHlwZV0gPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLmRpcmVjdGlvbiA9PT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXSA9IHVMaW5lO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVMaW5lLnByb3RvY29sICE9IHR5cGUyYmxbdUxpbmUudHlwZV0ucHJvdG9jb2wpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHRvIFBsYW4gQiBiZWNhdXNlIG0tbGluZXMgJyArXG4gICAgICAgICAgICAgICdoYXZlIGRpZmZlcmVudCBwcm90b2NvbHMgYW5kIHRoaXMgbGlicmFyeSBkb2VzIG5vdCBoYXZlICcgK1xuICAgICAgICAgICAgICAnc3VwcG9ydCBmb3IgdGhhdCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVMaW5lLnBheWxvYWRzICE9IHR5cGUyYmxbdUxpbmUudHlwZV0ucGF5bG9hZHMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHRvIFBsYW4gQiBiZWNhdXNlIG0tbGluZXMgJyArXG4gICAgICAgICAgICAgICdoYXZlIGRpZmZlcmVudCBwYXlsb2FkcyBhbmQgdGhpcyBsaWJyYXJ5IGRvZXMgbm90IGhhdmUgJyArXG4gICAgICAgICAgICAgICdzdXBwb3J0IGZvciB0aGF0Jyk7XG4gICAgICAgIH1cblxuICAgIH0pO1xuXG4gICAgLy8gSW1wbG9kZSB0aGUgVW5pZmllZCBQbGFuIG0tbGluZXMvdHJhY2tzIGludG8gUGxhbiBCIGNoYW5uZWxzLlxuICAgIG1lZGlhLmZvckVhY2goZnVuY3Rpb24odUxpbmUpIHtcbiAgICAgICAgaWYgKHVMaW5lLnR5cGUgPT09ICdhcHBsaWNhdGlvbicpIHtcbiAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG4gICAgICAgICAgICB0eXBlcy5wdXNoKHVMaW5lLm1pZCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgc291cmNlcyB0byB0aGUgY2hhbm5lbCBhbmQgaGFuZGxlIGE9bXNpZC5cbiAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5zb3VyY2VzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgT2JqZWN0LmtleXModUxpbmUuc291cmNlcykuZm9yRWFjaChmdW5jdGlvbihzc3JjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXMgIT09ICdvYmplY3QnKVxuICAgICAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXMgPSB7fTtcblxuICAgICAgICAgICAgICAgIC8vIEFzc2lnbiB0aGUgc291cmNlcyB0byB0aGUgY2hhbm5lbC5cbiAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXNbc3NyY10gPVxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5tc2lkICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbiBQbGFuIEIgdGhlIG1zaWQgaXMgYW4gU1NSQyBhdHRyaWJ1dGUuIEFsc28sIHdlIGRvbid0XG4gICAgICAgICAgICAgICAgICAgIC8vIGNhcmUgYWJvdXQgdGhlIG9ic29sZXRlIGxhYmVsIGFuZCBtc2xhYmVsIGF0dHJpYnV0ZXMuXG4gICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGUgdGhhdCBpdCBpcyBub3QgZ3VhcmFudGVlZCB0aGF0IHRoZSB1TGluZSB3aWxsXG4gICAgICAgICAgICAgICAgICAgIC8vIGhhdmUgYW4gbXNpZC4gcmVjdm9ubHkgY2hhbm5lbHMgaW4gcGFydGljdWxhciBkb24ndCBoYXZlXG4gICAgICAgICAgICAgICAgICAgIC8vIG9uZS5cbiAgICAgICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzW3NzcmNdLm1zaWQgPVxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubXNpZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gTk9URSBzc3JjcyBpbiBzc3JjIGdyb3VwcyB3aWxsIHNoYXJlIG1zaWRzLCBhc1xuICAgICAgICAgICAgICAgIC8vIGRyYWZ0LXViZXJ0aS1ydGN3ZWItcGxhbi0wMCBtYW5kYXRlcy5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHNzcmMgZ3JvdXBzIHRvIHRoZSBjaGFubmVsLlxuICAgICAgICBpZiAodHlwZW9mIHVMaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheSh1TGluZS5zc3JjR3JvdXBzKSkge1xuXG4gICAgICAgICAgICAvLyBDcmVhdGUgdGhlIHNzcmNHcm91cHMgYXJyYXksIGlmIGl0J3Mgbm90IGRlZmluZWQuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcyA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgIUFycmF5LmlzQXJyYXkodHlwZTJibFt1TGluZS50eXBlXS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcyA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMgPVxuICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3Vwcy5jb25jYXQoXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNzcmNHcm91cHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUyYmxbdUxpbmUudHlwZV0gPT09IHVMaW5lKSB7XG4gICAgICAgICAgICAvLyBQbGFuIEIgbWlkcyBhcmUgaW4gWydhdWRpbycsICd2aWRlbycsICdkYXRhJ11cbiAgICAgICAgICAgIHVMaW5lLm1pZCA9IHVMaW5lLnR5cGU7XG5cbiAgICAgICAgICAgIC8vIFBsYW4gQiBkb2Vzbid0IHN1cHBvcnQvbmVlZCB0aGUgYnVuZGxlLW9ubHkgYXR0cmlidXRlLlxuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLmJ1bmRsZU9ubHk7XG5cbiAgICAgICAgICAgIC8vIEluIFBsYW4gQiB0aGUgbXNpZCBpcyBhbiBTU1JDIGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuXG5cdCAgICBpZiAodUxpbmUudHlwZSA9PSBtZWRpYVswXS50eXBlKSB7XG5cdCAgICAgIHR5cGVzLnVuc2hpZnQodUxpbmUudHlwZSk7XG5cdCAgICAgIC8vIEFkZCB0aGUgY2hhbm5lbCB0byB0aGUgbmV3IG1lZGlhIGFycmF5LlxuXHQgICAgICBzZXNzaW9uLm1lZGlhLnVuc2hpZnQodUxpbmUpO1xuXHQgICAgfSBlbHNlIHtcblx0ICAgICAgdHlwZXMucHVzaCh1TGluZS50eXBlKTtcblx0ICAgICAgLy8gQWRkIHRoZSBjaGFubmVsIHRvIHRoZSBuZXcgbWVkaWEgYXJyYXkuXG5cdCAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG5cdCAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAvLyBXZSByZWdlbmVyYXRlIHRoZSBCVU5ETEUgZ3JvdXAgd2l0aCB0aGUgbmV3IG1pZHMuXG4gICAgICBzZXNzaW9uLmdyb3Vwcy5zb21lKGZ1bmN0aW9uKGdyb3VwKSB7XG5cdCAgaWYgKGdyb3VwLnR5cGUgPT09ICdCVU5ETEUnKSB7XG5cdCAgICAgIGdyb3VwLm1pZHMgPSB0eXBlcy5qb2luKCcgJyk7XG5cdCAgICAgIHJldHVybiB0cnVlO1xuXHQgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIG1zaWQgc2VtYW50aWNcbiAgICBzZXNzaW9uLm1zaWRTZW1hbnRpYyA9IHtcbiAgICAgICAgc2VtYW50aWM6ICdXTVMnLFxuICAgICAgICB0b2tlbjogJyonXG4gICAgfTtcblxuICAgIHZhciByZXNTdHIgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG5cbiAgICByZXR1cm4gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgIHR5cGU6IGRlc2MudHlwZSxcbiAgICAgICAgc2RwOiByZXNTdHJcbiAgICB9KTtcblxuICAgIC8vI2VuZHJlZ2lvblxufTtcblxuLyogZm9sbG93IHJ1bGVzIGRlZmluZWQgaW4gUkZDNDE0NSAqL1xuZnVuY3Rpb24gYWRkU2V0dXBBdHRyKHVMaW5lKSB7XG4gICAgaWYgKHR5cGVvZiB1TGluZS5zZXR1cCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh1TGluZS5zZXR1cCA9PT0gXCJhY3RpdmVcIikge1xuICAgICAgICAgICAgdUxpbmUuc2V0dXAgPSBcInBhc3NpdmVcIjtcbiAgICB9IGVsc2UgaWYgKHVMaW5lLnNldHVwID09PSBcInBhc3NpdmVcIikge1xuICAgICAgICB1TGluZS5zZXR1cCA9IFwiYWN0aXZlXCI7XG4gICAgfVxufVxuXG4vKipcbiAqIFRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYSBQbGFuIEIgU0RQIHRvIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIFNEUC4gQVxuICogUGVlckNvbm5lY3Rpb24gd3JhcHBlciB0cmFuc2Zvcm1zIHRoZSBTRFAgdG8gVW5pZmllZCBQbGFuIGJlZm9yZSBwYXNzaW5nIGl0XG4gKiB0byBGRi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvVW5pZmllZFBsYW4gPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFBsYW4gQiBTRFAuIFBsYW4gQiBTRFAgaGFzXG4gICAgLy8gYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA+IDMgfHwgIXNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBQbGFuIEIuJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vIE1ha2Ugc3VyZSB0aGlzIFBsYW4gQiBTRFAgY2FuIGJlIGNvbnZlcnRlZCB0byBhIFVuaWZpZWQgUGxhbiBTRFAuXG4gICAgdmFyIG1pZHMgPSBbXTtcbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24obSkge1xuICAgICAgICBtaWRzLnB1c2gobS5taWQpO1xuICAgIH0pO1xuXG4gICAgdmFyIGhhc0J1bmRsZSA9IGZhbHNlO1xuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG4gICAgICAgIGhhc0J1bmRsZSA9IHNlc3Npb24uZ3JvdXBzLmV2ZXJ5KGZ1bmN0aW9uKGcpIHtcbiAgICAgICAgICAgIHJldHVybiBnLnR5cGUgIT09ICdCVU5ETEUnIHx8XG4gICAgICAgICAgICAgICAgYXJyYXlFcXVhbHMuYXBwbHkoZy5taWRzLnNvcnQoKSwgW21pZHMuc29ydCgpXSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICghaGFzQnVuZGxlKSB7XG4gICAgICAgIHZhciBtdXN0QmVCdW5kbGUgPSBmYWxzZTtcblxuICAgICAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgaWYgKG0uZGlyZWN0aW9uICE9PSAnaW5hY3RpdmUnKSB7XG4gICAgICAgICAgICAgICAgbXVzdEJlQnVuZGxlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKG11c3RCZUJ1bmRsZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNvbnZlcnQgdG8gVW5pZmllZCBQbGFuIGJlY2F1c2UgbS1saW5lcyB0aGF0XCIgK1xuICAgICAgICAgICAgICBcIiBhcmUgbm90IGJ1bmRsZWQgd2VyZSBmb3VuZC5cIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyNlbmRyZWdpb25cblxuXG4gICAgLy8jcmVnaW9uIENvbnZlcnQgZnJvbSBQbGFuIEIgdG8gVW5pZmllZCBQbGFuLlxuXG4gICAgLy8gVW5mb3J0dW5hdGVseSwgYSBQbGFuIEIgb2ZmZXIvYW5zd2VyIGRvZXNuJ3QgaGF2ZSBlbm91Z2ggaW5mb3JtYXRpb24gdG9cbiAgICAvLyByZWJ1aWxkIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIG9mZmVyL2Fuc3dlci5cbiAgICAvL1xuICAgIC8vIEZvciBleGFtcGxlLCBpZiB0aGlzIGlzIGEgbG9jYWwgYW5zd2VyIChpbiBVbmlmaWVkIFBsYW4gc3R5bGUpIHRoYXQgd2VcbiAgICAvLyBjb252ZXJ0IHRvIFBsYW4gQiBwcmlvciB0byBoYW5kaW5nIGl0IG92ZXIgdG8gdGhlIGFwcGxpY2F0aW9uICh0aGVcbiAgICAvLyBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIGNhbGxlZCB1cywgZm9yIGluc3RhbmNlLCBhZnRlciBhIHN1Y2Nlc3NmdWxcbiAgICAvLyBjcmVhdGVBbnN3ZXIpLCB3ZSB3YW50IHRvIHJlbWVtYmVyIHRoZSBtLWxpbmUgYXQgd2hpY2ggd2UndmUgc2VlbiB0aGVcbiAgICAvLyAobG9jYWwpIFNTUkMuIFRoYXQncyBiZWNhdXNlIHdoZW4gdGhlIGFwcGxpY2F0aW9uIHdhbnRzIHRvIGRvIGNhbGwgdGhlXG4gICAgLy8gU0xEIG1ldGhvZCwgZm9yY2luZyB1cyB0byBkbyB0aGUgaW52ZXJzZSB0cmFuc2Zvcm1hdGlvbiAoZnJvbSBQbGFuIEIgdG9cbiAgICAvLyBVbmlmaWVkIFBsYW4pLCB3ZSBuZWVkIHRvIGtub3cgdG8gd2hpY2ggbS1saW5lIHRvIGFzc2lnbiB0aGUgKGxvY2FsKVxuICAgIC8vIFNTUkMuIFdlIGFsc28gbmVlZCB0byBrbm93IGFsbCB0aGUgb3RoZXIgbS1saW5lcyB0aGF0IHRoZSBvcmlnaW5hbFxuICAgIC8vIGFuc3dlciBoYWQgYW5kIGluY2x1ZGUgdGhlbSBpbiB0aGUgdHJhbnNmb3JtZWQgYW5zd2VyIGFzIHdlbGwuXG4gICAgLy9cbiAgICAvLyBBbm90aGVyIGV4YW1wbGUgaXMgaWYgdGhpcyBpcyBhIHJlbW90ZSBvZmZlciB0aGF0IHdlIGNvbnZlcnQgdG8gUGxhbiBCXG4gICAgLy8gcHJpb3IgdG8gZ2l2aW5nIGl0IHRvIHRoZSBhcHBsaWNhdGlvbiwgd2Ugd2FudCB0byByZW1lbWJlciB0aGUgbWlkIGF0XG4gICAgLy8gd2hpY2ggd2UndmUgc2VlbiB0aGUgKHJlbW90ZSkgU1NSQy5cbiAgICAvL1xuICAgIC8vIEluIHRoZSBpdGVyYXRpb24gdGhhdCBmb2xsb3dzLCB3ZSB1c2UgdGhlIGNhY2hlZCBVbmlmaWVkIFBsYW4gKGlmIGl0XG4gICAgLy8gZXhpc3RzKSB0byBhc3NpZ24gbWlkcyB0byBzc3Jjcy5cblxuICAgIHZhciB0eXBlO1xuICAgIGlmIChkZXNjLnR5cGUgPT09ICdhbnN3ZXInKSB7XG4gICAgICAgIHR5cGUgPSAnb2ZmZXInO1xuICAgIH0gZWxzZSBpZiAoZGVzYy50eXBlID09PSAnb2ZmZXInKSB7XG4gICAgICAgIHR5cGUgPSAnYW5zd2VyJztcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUeXBlICdcIiArIGRlc2MudHlwZSArIFwiJyBub3Qgc3VwcG9ydGVkLlwiKTtcbiAgICB9XG5cbiAgICB2YXIgY2FjaGVkO1xuICAgIGlmICh0eXBlb2YgdGhpcy5jYWNoZVt0eXBlXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY2FjaGVkID0gdHJhbnNmb3JtLnBhcnNlKHRoaXMuY2FjaGVbdHlwZV0pO1xuICAgIH1cblxuICAgIHZhciByZWN2b25seVNzcmNzID0ge1xuICAgICAgICBhdWRpbzoge30sXG4gICAgICAgIHZpZGVvOiB7fVxuICAgIH07XG5cbiAgICAvLyBBIGhlbHBlciBtYXAgdGhhdCBzZW5kcyBtaWRzIHRvIG0tbGluZSBvYmplY3RzLiBXZSB1c2UgaXQgbGF0ZXIgdG9cbiAgICAvLyByZWJ1aWxkIHRoZSBVbmlmaWVkIFBsYW4gc3R5bGUgc2Vzc2lvbi5tZWRpYSBhcnJheS5cbiAgICB2YXIgbWlkMnVsID0ge307XG4gICAgdmFyIGJJZHggPSAwO1xuICAgIHZhciB1SWR4ID0gMDtcblxuICAgIHZhciBzb3VyY2VzMnVsID0ge307XG5cbiAgICB2YXIgY2FuZGlkYXRlcztcbiAgICB2YXIgaWNlVWZyYWc7XG4gICAgdmFyIGljZVB3ZDtcbiAgICB2YXIgZmluZ2VycHJpbnQ7XG4gICAgdmFyIHBheWxvYWRzID0ge307XG4gICAgdmFyIHJ0Y3BGYiA9IHt9O1xuICAgIHZhciBydHAgPSB7fTtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbihiTGluZSkge1xuICAgICAgICBpZiAoKHR5cGVvZiBiTGluZS5ydGNwTXV4ICE9PSAnc3RyaW5nJyB8fFxuICAgICAgICAgICAgYkxpbmUucnRjcE11eCAhPT0gJ3J0Y3AtbXV4JykgJiZcbiAgICAgICAgICAgIGJMaW5lLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNvbnZlcnQgdG8gVW5pZmllZCBQbGFuIGJlY2F1c2UgbS1saW5lcyBcIiArXG4gICAgICAgICAgICAgICAgXCJ3aXRob3V0IHRoZSBydGNwLW11eCBhdHRyaWJ1dGUgd2VyZSBmb3VuZC5cIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYkxpbmUudHlwZSA9PT0gJ2FwcGxpY2F0aW9uJykge1xuICAgICAgICAgICAgbWlkMnVsW2JMaW5lLm1pZF0gPSBiTGluZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdpdGggcnRjcC1tdXggYW5kIGJ1bmRsZSBhbGwgdGhlIGNoYW5uZWxzIHNob3VsZCBoYXZlIHRoZSBzYW1lIElDRVxuICAgICAgICAvLyBzdHVmZi5cbiAgICAgICAgdmFyIHNvdXJjZXMgPSBiTGluZS5zb3VyY2VzO1xuICAgICAgICB2YXIgc3NyY0dyb3VwcyA9IGJMaW5lLnNzcmNHcm91cHM7XG4gICAgICAgIHZhciBwb3J0ID0gYkxpbmUucG9ydDtcblxuICAgICAgICAvKiBDaHJvbWUgYWRkcyBkaWZmZXJlbnQgY2FuZGlkYXRlcyBldmVuIHVzaW5nIGJ1bmRsZSwgc28gd2UgY29uY2F0IHRoZSBjYW5kaWRhdGVzIGxpc3QgKi9cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5jYW5kaWRhdGVzICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNhbmRpZGF0ZXMgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBjYW5kaWRhdGVzID0gY2FuZGlkYXRlcy5jb25jYXQoYkxpbmUuY2FuZGlkYXRlcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbmRpZGF0ZXMgPSBiTGluZS5jYW5kaWRhdGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCh0eXBlb2YgaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpICYmICh0eXBlb2YgYkxpbmUuaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpICYmIChpY2VVZnJhZyAhPSBiTGluZS5pY2VVZnJhZykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgQlVORExFIHN1cHBvcnRlZCwgaWNlVWZyYWcgbXVzdCBiZSB0aGUgc2FtZSBmb3IgYWxsIG0tbGluZXMuXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TGFzdCBpY2VVZnJhZzogXCIgKyBpY2VVZnJhZyArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGljZVVmcmFnOiBcIiArIGJMaW5lLmljZVVmcmFnXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5pY2VVZnJhZyAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGljZVVmcmFnID0gYkxpbmUuaWNlVWZyYWc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHR5cGVvZiBpY2VQd2QgIT0gJ3VuZGVmaW5lZCcpICYmICh0eXBlb2YgYkxpbmUuaWNlUHdkICE9ICd1bmRlZmluZWQnKSAmJiAoaWNlUHdkICE9IGJMaW5lLmljZVB3ZCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgQlVORExFIHN1cHBvcnRlZCwgaWNlUHdkIG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgaWNlUHdkOiBcIiArIGljZVB3ZCArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGljZVB3ZDogXCIgKyBiTGluZS5pY2VQd2RcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGJMaW5lLmljZVB3ZCAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGljZVB3ZCA9IGJMaW5lLmljZVB3ZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgodHlwZW9mIGZpbmdlcnByaW50ICE9ICd1bmRlZmluZWQnKSAmJiAodHlwZW9mIGJMaW5lLmZpbmdlcnByaW50ICE9ICd1bmRlZmluZWQnKSAmJlxuICAgICAgICAgICAgKGZpbmdlcnByaW50LnR5cGUgIT0gYkxpbmUuZmluZ2VycHJpbnQudHlwZSB8fCBmaW5nZXJwcmludC5oYXNoICE9IGJMaW5lLmZpbmdlcnByaW50Lmhhc2gpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IEJVTkRMRSBzdXBwb3J0ZWQsIGZpbmdlcnByaW50IG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgZmluZ2VycHJpbnQ6IFwiICsgSlNPTi5zdHJpbmdpZnkoZmluZ2VycHJpbnQpICsgXCJcXG5cIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcXHROZXcgZmluZ2VycHJpbnQ6IFwiICsgSlNPTi5zdHJpbmdpZnkoYkxpbmUuZmluZ2VycHJpbnQpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5maW5nZXJwcmludCAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGZpbmdlcnByaW50ID0gYkxpbmUuZmluZ2VycHJpbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBwYXlsb2Fkc1tiTGluZS50eXBlXSA9IGJMaW5lLnBheWxvYWRzO1xuICAgICAgICBydGNwRmJbYkxpbmUudHlwZV0gPSBiTGluZS5ydGNwRmI7XG4gICAgICAgIHJ0cFtiTGluZS50eXBlXSA9IGJMaW5lLnJ0cDtcblxuICAgICAgICAvLyBpbnZlcnRlZCBzc3JjIGdyb3VwIG1hcFxuICAgICAgICB2YXIgc3NyYzJncm91cCA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICAgIHNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgLy8gWFhYIFRoaXMgbWlnaHQgYnJha2UgaWYgYW4gU1NSQyBpcyBpbiBtb3JlIHRoYW4gb25lIGdyb3VwXG4gICAgICAgICAgICAgICAgLy8gZm9yIHNvbWUgcmVhc29uLlxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyY0dyb3VwLnNzcmNzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmNHcm91cC5zc3JjcykpIHtcbiAgICAgICAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzLmZvckVhY2goZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyYzJncm91cFtzc3JjXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzc3JjMmdyb3VwW3NzcmNdID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNzcmMyZ3JvdXBbc3NyY10ucHVzaChzc3JjR3JvdXApO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHNzcmMgdG8gbS1saW5lIGluZGV4LlxuICAgICAgICB2YXIgc3NyYzJtbCA9IHt9O1xuXG4gICAgICAgIGlmICh0eXBlb2Ygc291cmNlcyA9PT0gJ29iamVjdCcpIHtcblxuICAgICAgICAgICAgLy8gV2UnbGwgdXNlIHRoZSBcImJMaW5lXCIgb2JqZWN0IGFzIGEgcHJvdG90eXBlIGZvciBlYWNoIG5ldyBcIm1MaW5lXCJcbiAgICAgICAgICAgIC8vIHRoYXQgd2UgY3JlYXRlLCBidXQgZmlyc3Qgd2UgbmVlZCB0byBjbGVhbiBpdCB1cCBhIGJpdC5cbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5zb3VyY2VzO1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLnNzcmNHcm91cHM7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuY2FuZGlkYXRlcztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5pY2VVZnJhZztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5pY2VQd2Q7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuZmluZ2VycHJpbnQ7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUucG9ydDtcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5taWQ7XG5cbiAgICAgICAgICAgIC8vIEV4cGxvZGUgdGhlIFBsYW4gQiBjaGFubmVsIHNvdXJjZXMgd2l0aCBvbmUgbS1saW5lIHBlciBzb3VyY2UuXG4gICAgICAgICAgICBPYmplY3Qua2V5cyhzb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uKHNzcmMpIHtcblxuICAgICAgICAgICAgICAgIC8vIFRoZSAodW5pZmllZCkgbS1saW5lIGZvciB0aGlzIFNTUkMuIFdlIGVpdGhlciBjcmVhdGUgaXQgZnJvbVxuICAgICAgICAgICAgICAgIC8vIHNjcmF0Y2ggb3IsIGlmIGl0J3MgYSBncm91cGVkIFNTUkMsIHdlIHJlLXVzZSBhIHJlbGF0ZWRcbiAgICAgICAgICAgICAgICAvLyBtbGluZS4gSW4gb3RoZXIgd29yZHMsIGlmIHRoZSBzb3VyY2UgaXMgZ3JvdXBlZCB3aXRoIGFub3RoZXJcbiAgICAgICAgICAgICAgICAvLyBzb3VyY2UsIHB1dCB0aGUgdHdvIHRvZ2V0aGVyIGluIHRoZSBzYW1lIG0tbGluZS5cbiAgICAgICAgICAgICAgICB2YXIgdUxpbmU7XG5cbiAgICAgICAgICAgICAgICAvLyBXZSBhc3N1bWUgaGVyZSB0aGF0IHdlIGFyZSB0aGUgYW5zd2VyZXIgaW4gdGhlIE8vQSwgc28gYW55XG4gICAgICAgICAgICAgICAgLy8gb2ZmZXJzIHdoaWNoIHdlIHRyYW5zbGF0ZSBjb21lIGZyb20gdGhlIHJlbW90ZSBzaWRlLCB3aGlsZVxuICAgICAgICAgICAgICAgIC8vIGFuc3dlcnMgYXJlIGxvY2FsLiBTbyB0aGUgY2hlY2sgYmVsb3cgaXMgdG8gbWFrZSB0aGF0IHdlXG4gICAgICAgICAgICAgICAgLy8gaGFuZGxlIHJlY2VpdmUtb25seSBTU1JDcyBpbiBhIHNwZWNpYWwgd2F5IG9ubHkgaWYgdGhleSBjb21lXG4gICAgICAgICAgICAgICAgLy8gZnJvbSB0aGUgcmVtb3RlIHNpZGUuXG4gICAgICAgICAgICAgICAgaWYgKGRlc2MudHlwZT09PSdvZmZlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2Ugd2FudCB0byBkZXRlY3QgU1NSQ3Mgd2hpY2ggYXJlIHVzZWQgYnkgYSByZW1vdGUgcGVlclxuICAgICAgICAgICAgICAgICAgICAvLyBpbiBhbiBtLWxpbmUgd2l0aCBkaXJlY3Rpb249cmVjdm9ubHkgKGkuZS4gdGhleSBhcmVcbiAgICAgICAgICAgICAgICAgICAgLy8gYmVpbmcgdXNlZCBmb3IgUlRDUCBvbmx5KS5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBpbmZvcm1hdGlvbiB3b3VsZCBoYXZlIGdvdHRlbiBsb3N0IGlmIHRoZSByZW1vdGVcbiAgICAgICAgICAgICAgICAgICAgLy8gcGVlciB1c2VkIFVuaWZpZWQgUGxhbiBhbmQgdGhlaXIgbG9jYWwgZGVzY3JpcHRpb24gd2FzXG4gICAgICAgICAgICAgICAgICAgIC8vIHRyYW5zbGF0ZWQgdG8gUGxhbiBCLiBTbyB3ZSB1c2UgdGhlIGxhY2sgb2YgYW4gTVNJRFxuICAgICAgICAgICAgICAgICAgICAvLyBhdHRyaWJ1dGUgdG8gZGVkdWNlIGEgXCJyZWNlaXZlIG9ubHlcIiBTU1JDLlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNvdXJjZXNbc3NyY10ubXNpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjdm9ubHlTc3Jjc1tiTGluZS50eXBlXVtzc3JjXSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWNlaXZlLW9ubHkgU1NSQ3MgbXVzdCBub3QgY3JlYXRlIG5ldyBtLWxpbmVzLiBXZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2lsbCBhc3NpZ24gdGhlbSB0byBhbiBleGlzdGluZyBtLWxpbmUgbGF0ZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNzcmMyZ3JvdXBbc3NyY10gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoc3NyYzJncm91cFtzc3JjXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3NyYzJncm91cFtzc3JjXS5zb21lKGZ1bmN0aW9uIChzc3JjR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNzcmNHcm91cC5zc3JjcyAqaXMqIGFuIEFycmF5LCBubyBuZWVkIHRvIGNoZWNrXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhZ2FpbiBoZXJlLlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNzcmNHcm91cC5zc3Jjcy5zb21lKGZ1bmN0aW9uIChyZWxhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjMm1sW3JlbGF0ZWRdID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZSA9IHNzcmMybWxbcmVsYXRlZF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVMaW5lID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbS1saW5lIGFscmVhZHkgZXhpc3RzLiBKdXN0IGFkZCB0aGUgc291cmNlLlxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID0gc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIFwiYkxpbmVcIiBhcyBhIHByb3RvdHlwZSBmb3IgdGhlIFwidUxpbmVcIi5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUgPSBPYmplY3QuY3JlYXRlKGJMaW5lKTtcbiAgICAgICAgICAgICAgICAgICAgc3NyYzJtbFtzc3JjXSA9IHVMaW5lO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc291cmNlc1tzc3JjXS5tc2lkICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXNzaWduIHRoZSBtc2lkIG9mIHRoZSBzb3VyY2UgdG8gdGhlIG0tbGluZS4gTm90ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhhdCBpdCBpcyBub3QgZ3VhcmFudGVlZCB0aGF0IHRoZSBzb3VyY2Ugd2lsbCBoYXZlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtc2lkLiBJbiBwYXJ0aWN1bGFyIFwicmVjdm9ubHlcIiBzb3VyY2VzIGRvbid0IGhhdmUgYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1zaWQuIE5vdGUgdGhhdCBcInJlY3Zvbmx5XCIgaXMgYSB0ZXJtIG9ubHkgZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZm9yIG0tbGluZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5tc2lkID0gc291cmNlc1tzc3JjXS5tc2lkO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIGFzc2lnbiBvbmUgU1NSQyBwZXIgbWVkaWEgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID0gc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc3NyY0dyb3VwcyA9IHNzcmMyZ3JvdXBbc3NyY107XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHRoZSBjYWNoZWQgVW5pZmllZCBQbGFuIFNEUCAoaWYgaXQgZXhpc3RzKSB0byBhc3NpZ25cbiAgICAgICAgICAgICAgICAgICAgLy8gU1NSQ3MgdG8gbWlkcy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjYWNoZWQgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlb2YgY2FjaGVkLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShjYWNoZWQubWVkaWEpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZC5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtLnNvdXJjZXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKG0uc291cmNlcykuZm9yRWFjaChmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMgPT09IHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5taWQgPSBtLm1pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVMaW5lLm1pZCA9PT0gJ3VuZGVmaW5lZCcpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyBhbiBTU1JDIHRoYXQgd2Ugc2VlIGZvciB0aGUgZmlyc3QgdGltZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGl0IGEgbmV3IG1pZC4gVGhpcyBpcyB0eXBpY2FsbHkgdGhlIGNhc2Ugd2hlblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBtZXRob2QgaXMgY2FsbGVkIHRvIHRyYW5zZm9ybSBhIHJlbW90ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGVzY3JpcHRpb24gZm9yIHRoZSBmaXJzdCB0aW1lIG9yIHdoZW4gdGhlcmUgaXMgYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbmV3IFNTUkMgaW4gdGhlIHJlbW90ZSBkZXNjcmlwdGlvbiBiZWNhdXNlIGEgbmV3XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwZWVyIGhhcyBqb2luZWQgdGhlIGNvbmZlcmVuY2UuIExvY2FsIFNTUkNzIHNob3VsZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaGF2ZSBhbHJlYWR5IGJlZW4gYWRkZWQgdG8gdGhlIG1hcCBpbiB0aGUgdG9QbGFuQlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWV0aG9kLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2UgRkYgZ2VuZXJhdGVzIGFuc3dlcnMgaW4gVW5pZmllZCBQbGFuIHN0eWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UgTVVTVCBhbHJlYWR5IGhhdmUgYSBjYWNoZWQgYW5zd2VyIHdpdGggYWxsIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbG9jYWwgU1NSQ3MgbWFwcGVkIHRvIHNvbWUgbS1saW5lL21pZC5cblxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubWlkID0gW2JMaW5lLnR5cGUsICctJywgc3NyY10uam9pbignJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBJbmNsdWRlIHRoZSBjYW5kaWRhdGVzIGluIHRoZSAxc3QgbWVkaWEgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVVmcmFnID0gaWNlVWZyYWc7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUucG9ydCA9IHBvcnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgbWlkMnVsW3VMaW5lLm1pZF0gPSB1TGluZTtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlczJ1bFt1SWR4XSA9IHVMaW5lLnNvdXJjZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWNoZS5tbFUyQk1hcFt1SWR4XSA9IGJJZHg7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNhY2hlLm1sQjJVTWFwW2JJZHhdID0gdUlkeDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB1SWR4Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHVMaW5lID0gYkxpbmU7XG5cbiAgICAgICAgICB1TGluZS5jYW5kaWRhdGVzID0gY2FuZGlkYXRlcztcbiAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICB1TGluZS5maW5nZXJwcmludCA9IGZpbmdlcnByaW50O1xuICAgICAgICAgIHVMaW5lLnBvcnQgPSBwb3J0O1xuXG4gICAgICAgICAgbWlkMnVsW3VMaW5lLm1pZF0gPSB1TGluZTtcblxuICAgICAgICAgIHNlbGYuY2FjaGUubWxVMkJNYXBbdUlkeF0gPSBiSWR4O1xuICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHNlbGYuY2FjaGUubWxCMlVNYXBbYklkeF0gPSB1SWR4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGJJZHgrKztcbiAgICB9KTtcblxuICAgIC8vIFJlYnVpbGQgdGhlIG1lZGlhIGFycmF5IGluIHRoZSByaWdodCBvcmRlciBhbmQgYWRkIHRoZSBtaXNzaW5nIG1MaW5lc1xuICAgIC8vIChtaXNzaW5nIGZyb20gdGhlIFBsYW4gQiBTRFApLlxuICAgIHNlc3Npb24ubWVkaWEgPSBbXTtcbiAgICBtaWRzID0gW107IC8vIHJldXNlXG5cbiAgICBpZiAoZGVzYy50eXBlID09PSAnYW5zd2VyJykge1xuXG4gICAgICAgIC8vIFRoZSBtZWRpYSBsaW5lcyBpbiB0aGUgYW5zd2VyIG11c3QgbWF0Y2ggdGhlIG1lZGlhIGxpbmVzIGluIHRoZVxuICAgICAgICAvLyBvZmZlci4gVGhlIG9yZGVyIGlzIGltcG9ydGFudCB0b28uIEhlcmUgd2UgYXNzdW1lIHRoYXQgRmlyZWZveCBpc1xuICAgICAgICAvLyB0aGUgYW5zd2VyZXIsIHNvIHdlIG1lcmVseSBoYXZlIHRvIHVzZSB0aGUgcmVjb25zdHJ1Y3RlZCAodW5pZmllZClcbiAgICAgICAgLy8gYW5zd2VyIHRvIHVwZGF0ZSB0aGUgY2FjaGVkICh1bmlmaWVkKSBhbnN3ZXIgYWNjb3JkaW5nbHkuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEluIHRoZSBnZW5lcmFsIGNhc2UsIG9uZSB3b3VsZCBoYXZlIHRvIHVzZSB0aGUgY2FjaGVkICh1bmlmaWVkKVxuICAgICAgICAvLyBvZmZlciB0byBmaW5kIHRoZSBtLWxpbmVzIHRoYXQgYXJlIG1pc3NpbmcgZnJvbSB0aGUgcmVjb25zdHJ1Y3RlZFxuICAgICAgICAvLyBhbnN3ZXIsIHBvdGVudGlhbGx5IGdyYWJiaW5nIHRoZW0gZnJvbSB0aGUgY2FjaGVkICh1bmlmaWVkKSBhbnN3ZXIuXG4gICAgICAgIC8vIE9uZSBoYXMgdG8gYmUgY2FyZWZ1bCB3aXRoIHRoaXMgYXBwcm9hY2ggYmVjYXVzZSBpbmFjdGl2ZSBtLWxpbmVzIGRvXG4gICAgICAgIC8vIG5vdCBhbHdheXMgaGF2ZSBhbiBtaWQsIG1ha2luZyBpdCB0cmlja3kgKGltcG9zc2libGU/KSB0byBmaW5kIHdoZXJlXG4gICAgICAgIC8vIGV4YWN0bHkgYW5kIHdoaWNoIG0tbGluZXMgYXJlIG1pc3NpbmcgZnJvbSB0aGUgcmVjb25zdHJ1Y3RlZCBhbnN3ZXIuXG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjYWNoZWQubWVkaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB1TGluZSA9IGNhY2hlZC5tZWRpYVtpXTtcblxuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICBkZWxldGUgdUxpbmUuc291cmNlcztcbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zc3JjR3JvdXBzO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHNvdXJjZXMydWxbaV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAncmVjdm9ubHknO1xuICAgICAgICAgICAgICBlbHNlIGlmICh1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kb25seScpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnaW5hY3RpdmUnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKCF1TGluZS5kaXJlY3Rpb25cbiAgICAgICAgICAgICAgICAgIHx8IHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JylcbiAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICAgIGVsc2UgaWYgKHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3JlY3Zvbmx5JylcbiAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdzZW5kb25seSc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHVMaW5lLnNvdXJjZXMgPSBzb3VyY2VzMnVsW2ldO1xuICAgICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgICAgdUxpbmUuaWNlUHdkID0gaWNlUHdkO1xuICAgICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcblxuICAgICAgICAgICAgdUxpbmUucnRwID0gcnRwW3VMaW5lLnR5cGVdO1xuICAgICAgICAgICAgdUxpbmUucGF5bG9hZHMgPSBwYXlsb2Fkc1t1TGluZS50eXBlXTtcbiAgICAgICAgICAgIHVMaW5lLnJ0Y3BGYiA9IHJ0Y3BGYlt1TGluZS50eXBlXTtcblxuICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5taWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgLy8gaW5hY3RpdmUgbGluZXMgZG9uJ3QvbWF5IG5vdCBoYXZlIGFuIG1pZC5cbiAgICAgICAgICAgICAgICBtaWRzLnB1c2godUxpbmUubWlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgLy8gU0RQIG9mZmVyL2Fuc3dlciAoYW5kIHRoZSBKU0VQIHNwZWMpIGZvcmJpZHMgcmVtb3ZpbmcgYW4gbS1zZWN0aW9uXG4gICAgICAgIC8vIHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzLiBJZiB3ZSBhcmUgbm8gbG9uZ2VyIGludGVyZXN0ZWQgaW4gc2VuZGluZyBhXG4gICAgICAgIC8vIHRyYWNrLCB3ZSBqdXN0IHJlbW92ZSB0aGUgbXNpZCBhbmQgc3NyYyBhdHRyaWJ1dGVzIGFuZCBzZXQgaXQgdG9cbiAgICAgICAgLy8gZWl0aGVyIGE9cmVjdm9ubHkgKGFzIHRoZSByZW9mZmVyZXIsIHdlIG11c3QgdXNlIHJlY3Zvbmx5IGlmIHRoZVxuICAgICAgICAvLyBvdGhlciBzaWRlIHdhcyBwcmV2aW91c2x5IHNlbmRpbmcgb24gdGhlIG0tc2VjdGlvbiwgYnV0IHdlIGNhbiBhbHNvXG4gICAgICAgIC8vIGxlYXZlIHRoZSBwb3NzaWJpbGl0eSBvcGVuIGlmIGl0IHdhc24ndCBwcmV2aW91c2x5IGluIHVzZSksIG9yXG4gICAgICAgIC8vIGE9aW5hY3RpdmUuXG5cbiAgICAgICAgaWYgKHR5cGVvZiBjYWNoZWQgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICB0eXBlb2YgY2FjaGVkLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgQXJyYXkuaXNBcnJheShjYWNoZWQubWVkaWEpKSB7XG4gICAgICAgICAgICBjYWNoZWQubWVkaWEuZm9yRWFjaChmdW5jdGlvbih1TGluZSkge1xuICAgICAgICAgICAgICAgIG1pZHMucHVzaCh1TGluZS5taWQpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWlkMnVsW3VMaW5lLm1pZF0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaChtaWQydWxbdUxpbmUubWlkXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zb3VyY2VzO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdUxpbmUuc3NyY0dyb3VwcztcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXVMaW5lLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnc2VuZG9ubHknO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdyZWN2b25seScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdpbmFjdGl2ZSc7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhZGRTZXR1cEF0dHIgKHVMaW5lKTtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBhbGwgdGhlIHJlbWFpbmluZyAobmV3KSBtLWxpbmVzIG9mIHRoZSB0cmFuc2Zvcm1lZCBTRFAuXG4gICAgICAgIE9iamVjdC5rZXlzKG1pZDJ1bCkuZm9yRWFjaChmdW5jdGlvbihtaWQpIHtcbiAgICAgICAgICAgIGlmIChtaWRzLmluZGV4T2YobWlkKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtaWRzLnB1c2gobWlkKTtcbiAgICAgICAgICAgICAgICBpZiAobWlkMnVsW21pZF0uZGlyZWN0aW9uID09PSAncmVjdm9ubHknKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYSByZW1vdGUgcmVjdm9ubHkgY2hhbm5lbC4gQWRkIGl0cyBTU1JDIHRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyBhcHByb3ByaWF0ZSBzZW5kcmVjdiBvciBzZW5kb25seSBjaGFubmVsLlxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPKGdwKSB3aGF0IGlmIHdlIGRvbid0IGhhdmUgc2VuZHJlY3Yvc2VuZG9ubHlcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hhbm5lbD9cblxuICAgICAgICAgICAgICAgICAgICB2YXIgZG9uZSA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEuc29tZShmdW5jdGlvbiAodUxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLnR5cGUgPT09IG1pZDJ1bFttaWRdLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtaWQydWxbbWlkXSBzaG91bGRuJ3QgaGF2ZSBhbnkgc3NyYy1ncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhtaWQydWxbbWlkXS5zb3VyY2VzKS5mb3JFYWNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pZDJ1bFttaWRdLnNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb25lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2gobWlkMnVsW21pZF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKG1pZDJ1bFttaWRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEFmdGVyIHdlIGhhdmUgY29uc3RydWN0ZWQgdGhlIFBsYW4gVW5pZmllZCBtLWxpbmVzIHdlIGNhbiBmaWd1cmUgb3V0XG4gICAgLy8gd2hlcmUgKGluIHdoaWNoIG0tbGluZSkgdG8gcGxhY2UgdGhlICdyZWN2b25seSBTU1JDcycuXG4gICAgLy8gTm90ZTogd2UgYXNzdW1lIGhlcmUgdGhhdCB3ZSBhcmUgdGhlIGFuc3dlcmVyIGluIHRoZSBPL0EsIHNvIGFueSBvZmZlcnNcbiAgICAvLyB3aGljaCB3ZSB0cmFuc2xhdGUgY29tZSBmcm9tIHRoZSByZW1vdGUgc2lkZSwgd2hpbGUgYW5zd2VycyBhcmUgbG9jYWxcbiAgICAvLyAoYW5kIHNvIG91ciBsYXN0IGxvY2FsIGRlc2NyaXB0aW9uIGlzIGNhY2hlZCBhcyBhbiAnYW5zd2VyJykuXG4gICAgW1wiYXVkaW9cIiwgXCJ2aWRlb1wiXS5mb3JFYWNoKGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIGlmICghc2Vzc2lvbiB8fCAhc2Vzc2lvbi5tZWRpYSB8fCAhQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB2YXIgaWR4ID0gbnVsbDtcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGlkeCA9IHNlbGYuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyKHR5cGUpO1xuICAgICAgICAgICAgaWYgKGlkeCA9PT0gbnVsbCl7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyB0aGUgZmlyc3Qgb2ZmZXIgd2UgcmVjZWl2ZSwgd2UgZG9uJ3QgaGF2ZSBhXG4gICAgICAgICAgICAgICAgLy8gY2FjaGVkIGFuc3dlci4gQXNzdW1lIHRoYXQgd2Ugd2lsbCBiZSBzZW5kaW5nIG1lZGlhIHVzaW5nXG4gICAgICAgICAgICAgICAgLy8gdGhlIGZpcnN0IG0tbGluZSBmb3IgZWFjaCBtZWRpYSB0eXBlLlxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZXNzaW9uLm1lZGlhW2ldLnR5cGUgPT09IHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkeCA9IGk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpZHggJiYgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPiBpZHgpIHtcbiAgICAgICAgICAgIHZhciBtTGluZSA9IHNlc3Npb24ubWVkaWFbaWR4XTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmZvckVhY2goZnVuY3Rpb24oc3NyYykge1xuICAgICAgICAgICAgICAgIGlmIChtTGluZS5zb3VyY2VzICYmIG1MaW5lLnNvdXJjZXNbc3NyY10pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiUmVwbGFjaW5nIGFuIGV4aXN0aW5nIFNTUkMuXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIW1MaW5lLnNvdXJjZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgbUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIG1MaW5lLnNvdXJjZXNbc3NyY10gPSByZWN2b25seVNzcmNzW3R5cGVdW3NzcmNdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAvLyBXZSByZWdlbmVyYXRlIHRoZSBCVU5ETEUgZ3JvdXAgKHNpbmNlIHdlIHJlZ2VuZXJhdGVkIHRoZSBtaWRzKVxuICAgICAgc2Vzc2lvbi5ncm91cHMuc29tZShmdW5jdGlvbihncm91cCkge1xuXHQgIGlmIChncm91cC50eXBlID09PSAnQlVORExFJykge1xuXHQgICAgICBncm91cC5taWRzID0gbWlkcy5qb2luKCcgJyk7XG5cdCAgICAgIHJldHVybiB0cnVlO1xuXHQgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIG1zaWQgc2VtYW50aWNcbiAgICBzZXNzaW9uLm1zaWRTZW1hbnRpYyA9IHtcbiAgICAgICAgc2VtYW50aWM6ICdXTVMnLFxuICAgICAgICB0b2tlbjogJyonXG4gICAgfTtcblxuICAgIHZhciByZXNTdHIgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG5cbiAgICAvLyBDYWNoZSB0aGUgdHJhbnNmb3JtZWQgU0RQIChVbmlmaWVkIFBsYW4pIGZvciBsYXRlciByZS11c2UgaW4gdGhpc1xuICAgIC8vIGZ1bmN0aW9uLlxuICAgIHRoaXMuY2FjaGVbZGVzYy50eXBlXSA9IHJlc1N0cjtcblxuICAgIHJldHVybiBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgICAgdHlwZTogZGVzYy50eXBlLFxuICAgICAgICBzZHA6IHJlc1N0clxuICAgIH0pO1xuXG4gICAgLy8jZW5kcmVnaW9uXG59O1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgdHJhbnNmb3JtID0gcmVxdWlyZSgnc2RwLXRyYW5zZm9ybScpO1xuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24oc2Vzc2lvbiwgb3B0cykge1xuXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSkge1xuXG4gICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtTGluZSkge1xuICAgICAgLy8gZXhwYW5kIHNvdXJjZXMgdG8gc3NyY3NcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc291cmNlcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgT2JqZWN0LmtleXMobUxpbmUuc291cmNlcykubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbUxpbmUuc3NyY3MgPSBbXTtcbiAgICAgICAgICBPYmplY3Qua2V5cyhtTGluZS5zb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gbUxpbmUuc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHNvdXJjZSkuZm9yRWFjaChmdW5jdGlvbiAoYXR0cmlidXRlKSB7XG4gICAgICAgICAgICAgIG1MaW5lLnNzcmNzLnB1c2goe1xuICAgICAgICAgICAgICAgIGlkOiBzc3JjLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogYXR0cmlidXRlLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBzb3VyY2VbYXR0cmlidXRlXVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGRlbGV0ZSBtTGluZS5zb3VyY2VzO1xuICAgICAgICB9XG5cbiAgICAgIC8vIGpvaW4gc3NyY3MgaW4gc3NyYyBncm91cHNcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmNHcm91cC5zc3JjcykpIHtcbiAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzID0gc3NyY0dyb3VwLnNzcmNzLmpvaW4oJyAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gam9pbiBncm91cCBtaWRzXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLmdyb3VwcykpIHtcblxuICAgIHNlc3Npb24uZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgIGlmICh0eXBlb2YgZy5taWRzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KGcubWlkcykpIHtcbiAgICAgICAgZy5taWRzID0gZy5taWRzLmpvaW4oJyAnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbiwgb3B0cyk7XG59O1xuXG5leHBvcnRzLnBhcnNlID0gZnVuY3Rpb24oc2RwKSB7XG4gIHZhciBzZXNzaW9uID0gdHJhbnNmb3JtLnBhcnNlKHNkcCk7XG5cbiAgaWYgKHR5cGVvZiBzZXNzaW9uICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygc2Vzc2lvbi5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpIHtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICAgIC8vIGdyb3VwIHNvdXJjZXMgYXR0cmlidXRlcyBieSBzc3JjXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KG1MaW5lLnNzcmNzKSkge1xuICAgICAgICBtTGluZS5zb3VyY2VzID0ge307XG4gICAgICAgIG1MaW5lLnNzcmNzLmZvckVhY2goZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICBpZiAoIW1MaW5lLnNvdXJjZXNbc3NyYy5pZF0pXG4gICAgICAgICAgbUxpbmUuc291cmNlc1tzc3JjLmlkXSA9IHt9O1xuICAgICAgICBtTGluZS5zb3VyY2VzW3NzcmMuaWRdW3NzcmMuYXR0cmlidXRlXSA9IHNzcmMudmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlbGV0ZSBtTGluZS5zc3JjcztcbiAgICAgIH1cblxuICAgICAgLy8gc3BsaXQgc3NyY3MgaW4gc3NyYyBncm91cHNcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzID0gc3NyY0dyb3VwLnNzcmNzLnNwbGl0KCcgJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuICAvLyBzcGxpdCBncm91cCBtaWRzXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLmdyb3VwcykpIHtcblxuICAgIHNlc3Npb24uZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgIGlmICh0eXBlb2YgZy5taWRzID09PSAnc3RyaW5nJykge1xuICAgICAgICBnLm1pZHMgPSBnLm1pZHMuc3BsaXQoJyAnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzZXNzaW9uO1xufTtcblxuIiwiLyohXG4gKiBVQVBhcnNlci5qcyB2MC43LjE4XG4gKiBMaWdodHdlaWdodCBKYXZhU2NyaXB0LWJhc2VkIFVzZXItQWdlbnQgc3RyaW5nIHBhcnNlclxuICogaHR0cHM6Ly9naXRodWIuY29tL2ZhaXNhbG1hbi91YS1wYXJzZXItanNcbiAqXG4gKiBDb3B5cmlnaHQgwqkgMjAxMi0yMDE2IEZhaXNhbCBTYWxtYW4gPGZ5emxtYW5AZ21haWwuY29tPlxuICogRHVhbCBsaWNlbnNlZCB1bmRlciBHUEx2MiBvciBNSVRcbiAqL1xuXG4oZnVuY3Rpb24gKHdpbmRvdywgdW5kZWZpbmVkKSB7XG5cbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvLy8vLy8vLy8vLy8vL1xuICAgIC8vIENvbnN0YW50c1xuICAgIC8vLy8vLy8vLy8vLy9cblxuXG4gICAgdmFyIExJQlZFUlNJT04gID0gJzAuNy4xOCcsXG4gICAgICAgIEVNUFRZICAgICAgID0gJycsXG4gICAgICAgIFVOS05PV04gICAgID0gJz8nLFxuICAgICAgICBGVU5DX1RZUEUgICA9ICdmdW5jdGlvbicsXG4gICAgICAgIFVOREVGX1RZUEUgID0gJ3VuZGVmaW5lZCcsXG4gICAgICAgIE9CSl9UWVBFICAgID0gJ29iamVjdCcsXG4gICAgICAgIFNUUl9UWVBFICAgID0gJ3N0cmluZycsXG4gICAgICAgIE1BSk9SICAgICAgID0gJ21ham9yJywgLy8gZGVwcmVjYXRlZFxuICAgICAgICBNT0RFTCAgICAgICA9ICdtb2RlbCcsXG4gICAgICAgIE5BTUUgICAgICAgID0gJ25hbWUnLFxuICAgICAgICBUWVBFICAgICAgICA9ICd0eXBlJyxcbiAgICAgICAgVkVORE9SICAgICAgPSAndmVuZG9yJyxcbiAgICAgICAgVkVSU0lPTiAgICAgPSAndmVyc2lvbicsXG4gICAgICAgIEFSQ0hJVEVDVFVSRT0gJ2FyY2hpdGVjdHVyZScsXG4gICAgICAgIENPTlNPTEUgICAgID0gJ2NvbnNvbGUnLFxuICAgICAgICBNT0JJTEUgICAgICA9ICdtb2JpbGUnLFxuICAgICAgICBUQUJMRVQgICAgICA9ICd0YWJsZXQnLFxuICAgICAgICBTTUFSVFRWICAgICA9ICdzbWFydHR2JyxcbiAgICAgICAgV0VBUkFCTEUgICAgPSAnd2VhcmFibGUnLFxuICAgICAgICBFTUJFRERFRCAgICA9ICdlbWJlZGRlZCc7XG5cblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gSGVscGVyXG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgdXRpbCA9IHtcbiAgICAgICAgZXh0ZW5kIDogZnVuY3Rpb24gKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIHtcbiAgICAgICAgICAgIHZhciBtYXJnZWRSZWdleGVzID0ge307XG4gICAgICAgICAgICBmb3IgKHZhciBpIGluIHJlZ2V4ZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uc1tpXSAmJiBleHRlbnNpb25zW2ldLmxlbmd0aCAlIDIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2VkUmVnZXhlc1tpXSA9IGV4dGVuc2lvbnNbaV0uY29uY2F0KHJlZ2V4ZXNbaV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcmdlZFJlZ2V4ZXNbaV0gPSByZWdleGVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXJnZWRSZWdleGVzO1xuICAgICAgICB9LFxuICAgICAgICBoYXMgOiBmdW5jdGlvbiAoc3RyMSwgc3RyMikge1xuICAgICAgICAgIGlmICh0eXBlb2Ygc3RyMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHN0cjIudG9Mb3dlckNhc2UoKS5pbmRleE9mKHN0cjEudG9Mb3dlckNhc2UoKSkgIT09IC0xO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsb3dlcml6ZSA6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHIudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfSxcbiAgICAgICAgbWFqb3IgOiBmdW5jdGlvbiAodmVyc2lvbikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZih2ZXJzaW9uKSA9PT0gU1RSX1RZUEUgPyB2ZXJzaW9uLnJlcGxhY2UoL1teXFxkXFwuXS9nLCcnKS5zcGxpdChcIi5cIilbMF0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIHRyaW0gOiBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eW1xcc1xcdUZFRkZcXHhBMF0rfFtcXHNcXHVGRUZGXFx4QTBdKyQvZywgJycpO1xuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gTWFwIGhlbHBlclxuICAgIC8vLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciBtYXBwZXIgPSB7XG5cbiAgICAgICAgcmd4IDogZnVuY3Rpb24gKHVhLCBhcnJheXMpIHtcblxuICAgICAgICAgICAgLy92YXIgcmVzdWx0ID0ge30sXG4gICAgICAgICAgICB2YXIgaSA9IDAsIGosIGssIHAsIHEsIG1hdGNoZXMsIG1hdGNoOy8vLCBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAgICAgICAvKi8vIGNvbnN0cnVjdCBvYmplY3QgYmFyZWJvbmVzXG4gICAgICAgICAgICBmb3IgKHAgPSAwOyBwIDwgYXJnc1sxXS5sZW5ndGg7IHArKykge1xuICAgICAgICAgICAgICAgIHEgPSBhcmdzWzFdW3BdO1xuICAgICAgICAgICAgICAgIHJlc3VsdFt0eXBlb2YgcSA9PT0gT0JKX1RZUEUgPyBxWzBdIDogcV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9Ki9cblxuICAgICAgICAgICAgLy8gbG9vcCB0aHJvdWdoIGFsbCByZWdleGVzIG1hcHNcbiAgICAgICAgICAgIHdoaWxlIChpIDwgYXJyYXlzLmxlbmd0aCAmJiAhbWF0Y2hlcykge1xuXG4gICAgICAgICAgICAgICAgdmFyIHJlZ2V4ID0gYXJyYXlzW2ldLCAgICAgICAvLyBldmVuIHNlcXVlbmNlICgwLDIsNCwuLilcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSBhcnJheXNbaSArIDFdOyAgIC8vIG9kZCBzZXF1ZW5jZSAoMSwzLDUsLi4pXG4gICAgICAgICAgICAgICAgaiA9IGsgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gdHJ5IG1hdGNoaW5nIHVhc3RyaW5nIHdpdGggcmVnZXhlc1xuICAgICAgICAgICAgICAgIHdoaWxlIChqIDwgcmVnZXgubGVuZ3RoICYmICFtYXRjaGVzKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IHJlZ2V4W2orK10uZXhlYyh1YSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwID0gMDsgcCA8IHByb3BzLmxlbmd0aDsgcCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBtYXRjaGVzWysra107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcSA9IHByb3BzW3BdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIGdpdmVuIHByb3BlcnR5IGlzIGFjdHVhbGx5IGFycmF5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBxID09PSBPQkpfVFlQRSAmJiBxLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHEubGVuZ3RoID09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcVsxXSA9PSBGVU5DX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhc3NpZ24gbW9kaWZpZWQgbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXS5jYWxsKHRoaXMsIG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGdpdmVuIHZhbHVlLCBpZ25vcmUgcmVnZXggbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayB3aGV0aGVyIGZ1bmN0aW9uIG9yIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHFbMV0gPT09IEZVTkNfVFlQRSAmJiAhKHFbMV0uZXhlYyAmJiBxWzFdLnRlc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FsbCBmdW5jdGlvbiAodXN1YWxseSBzdHJpbmcgbWFwcGVyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbcVswXV0gPSBtYXRjaCA/IHFbMV0uY2FsbCh0aGlzLCBtYXRjaCwgcVsyXSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNhbml0aXplIG1hdGNoIHVzaW5nIGdpdmVuIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gbWF0Y2gucmVwbGFjZShxWzFdLCBxWzJdKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gcVszXS5jYWxsKHRoaXMsIG1hdGNoLnJlcGxhY2UocVsxXSwgcVsyXSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txXSA9IG1hdGNoID8gbWF0Y2ggOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMpO1xuICAgICAgICAgICAgLy9yZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICBzdHIgOiBmdW5jdGlvbiAoc3RyLCBtYXApIHtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBtYXApIHtcbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBhcnJheVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWFwW2ldID09PSBPQkpfVFlQRSAmJiBtYXBbaV0ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1hcFtpXS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHV0aWwuaGFzKG1hcFtpXVtqXSwgc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoaSA9PT0gVU5LTk9XTikgPyB1bmRlZmluZWQgOiBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh1dGlsLmhhcyhtYXBbaV0sIHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChpID09PSBVTktOT1dOKSA/IHVuZGVmaW5lZCA6IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgICAgfVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIFN0cmluZyBtYXBcbiAgICAvLy8vLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgbWFwcyA9IHtcblxuICAgICAgICBicm93c2VyIDoge1xuICAgICAgICAgICAgb2xkc2FmYXJpIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICcxLjAnICAgOiAnLzgnLFxuICAgICAgICAgICAgICAgICAgICAnMS4yJyAgIDogJy8xJyxcbiAgICAgICAgICAgICAgICAgICAgJzEuMycgICA6ICcvMycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAnICAgOiAnLzQxMicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMicgOiAnLzQxNicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMycgOiAnLzQxNycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuNCcgOiAnLzQxOScsXG4gICAgICAgICAgICAgICAgICAgICc/JyAgICAgOiAnLydcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGV2aWNlIDoge1xuICAgICAgICAgICAgYW1hem9uIDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRmlyZSBQaG9uZScgOiBbJ1NEJywgJ0tGJ11cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3ByaW50IDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRXZvIFNoaWZ0IDRHJyA6ICc3MzczS1QnXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB2ZW5kb3IgOiB7XG4gICAgICAgICAgICAgICAgICAgICdIVEMnICAgICAgIDogJ0FQQScsXG4gICAgICAgICAgICAgICAgICAgICdTcHJpbnQnICAgIDogJ1NwcmludCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgb3MgOiB7XG4gICAgICAgICAgICB3aW5kb3dzIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICdNRScgICAgICAgIDogJzQuOTAnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgMy4xMScgICA6ICdOVDMuNTEnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgNC4wJyAgICA6ICdOVDQuMCcsXG4gICAgICAgICAgICAgICAgICAgICcyMDAwJyAgICAgIDogJ05UIDUuMCcsXG4gICAgICAgICAgICAgICAgICAgICdYUCcgICAgICAgIDogWydOVCA1LjEnLCAnTlQgNS4yJ10sXG4gICAgICAgICAgICAgICAgICAgICdWaXN0YScgICAgIDogJ05UIDYuMCcsXG4gICAgICAgICAgICAgICAgICAgICc3JyAgICAgICAgIDogJ05UIDYuMScsXG4gICAgICAgICAgICAgICAgICAgICc4JyAgICAgICAgIDogJ05UIDYuMicsXG4gICAgICAgICAgICAgICAgICAgICc4LjEnICAgICAgIDogJ05UIDYuMycsXG4gICAgICAgICAgICAgICAgICAgICcxMCcgICAgICAgIDogWydOVCA2LjQnLCAnTlQgMTAuMCddLFxuICAgICAgICAgICAgICAgICAgICAnUlQnICAgICAgICA6ICdBUk0nXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy9cbiAgICAvLyBSZWdleCBtYXBcbiAgICAvLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciByZWdleGVzID0ge1xuXG4gICAgICAgIGJyb3dzZXIgOiBbW1xuXG4gICAgICAgICAgICAvLyBQcmVzdG8gYmFzZWRcbiAgICAgICAgICAgIC8ob3BlcmFcXHNtaW5pKVxcLyhbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1pbmlcbiAgICAgICAgICAgIC8ob3BlcmFcXHNbbW9iaWxldGFiXSspLit2ZXJzaW9uXFwvKFtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1vYmkvVGFibGV0XG4gICAgICAgICAgICAvKG9wZXJhKS4rdmVyc2lvblxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhID4gOS44MFxuICAgICAgICAgICAgLyhvcGVyYSlbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgPCA5LjgwXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhvcGlvcylbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgbWluaSBvbiBpcGhvbmUgPj0gOC4wXG4gICAgICAgICAgICBdLCBbW05BTUUsICdPcGVyYSBNaW5pJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9cXHMob3ByKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIFdlYmtpdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gTWl4ZWRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvKGx1bmFzY2FwZXxtYXh0aG9ufG5ldGZyb250fGphc21pbmV8YmxhemVyKVtcXC9cXHNdPyhbXFx3XFwuXSopL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEx1bmFzY2FwZS9NYXh0aG9uL05ldGZyb250L0phc21pbmUvQmxhemVyXG5cbiAgICAgICAgICAgIC8vIFRyaWRlbnQgYmFzZWRcbiAgICAgICAgICAgIC8oYXZhbnRcXHN8aWVtb2JpbGV8c2xpbXxiYWlkdSkoPzpicm93c2VyKT9bXFwvXFxzXT8oW1xcd1xcLl0qKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdmFudC9JRU1vYmlsZS9TbGltQnJvd3Nlci9CYWlkdVxuICAgICAgICAgICAgLyg/Om1zfFxcKCkoaWUpXFxzKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW50ZXJuZXQgRXhwbG9yZXJcblxuICAgICAgICAgICAgLy8gV2Via2l0L0tIVE1MIGJhc2VkXG4gICAgICAgICAgICAvKHJla29ucSlcXC8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJla29ucVxuICAgICAgICAgICAgLyhjaHJvbWl1bXxmbG9ja3xyb2NrbWVsdHxtaWRvcml8ZXBpcGhhbnl8c2lsa3xza3lmaXJlfG92aWJyb3dzZXJ8Ym9sdHxpcm9ufHZpdmFsZGl8aXJpZGl1bXxwaGFudG9tanN8Ym93c2VyfHF1YXJrKVxcLyhbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9taXVtL0Zsb2NrL1JvY2tNZWx0L01pZG9yaS9FcGlwaGFueS9TaWxrL1NreWZpcmUvQm9sdC9Jcm9uL0lyaWRpdW0vUGhhbnRvbUpTL0Jvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8odHJpZGVudCkuK3J2WzpcXHNdKFtcXHdcXC5dKykuK2xpa2VcXHNnZWNrby9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElFMTFcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0lFJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oZWRnZXxlZGdpb3N8ZWRnZWEpXFwvKChcXGQrKT9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBFZGdlXG4gICAgICAgICAgICBdLCBbW05BTUUsICdFZGdlJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oeWFicm93c2VyKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWWFuZGV4XG4gICAgICAgICAgICBdLCBbW05BTUUsICdZYW5kZXgnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhwdWZmaW4pXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQdWZmaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ1B1ZmZpbiddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKCg/OltcXHNcXC9dKXVjP1xccz9icm93c2VyfCg/Omp1Yy4rKXVjd2ViKVtcXC9cXHNdPyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVUNCcm93c2VyXG4gICAgICAgICAgICBdLCBbW05BTUUsICdVQ0Jyb3dzZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb21vZG9fZHJhZ29uKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb21vZG8gRHJhZ29uXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obWljcm9tZXNzZW5nZXIpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2VDaGF0XG4gICAgICAgICAgICBdLCBbW05BTUUsICdXZUNoYXQnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhxcWJyb3dzZXJsaXRlKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUUJyb3dzZXJMaXRlXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhRUSlcXC8oW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUSwgYWthIFNob3VRXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL20/KHFxYnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUVFCcm93c2VyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhCSURVQnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmFpZHUgQnJvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oMjM0NUV4cGxvcmVyKVtcXC9cXHNdPyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDIzNDUgQnJvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oTWV0YVNyKVtcXC9cXHNdPyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvdUdvdUJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAvKExCQlJPV1NFUikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGllQmFvIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAveGlhb21pXFwvbWl1aWJyb3dzZXJcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNSVVJIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ01JVUkgQnJvd3NlciddXSwgW1xuXG4gICAgICAgICAgICAvO2ZiYXZcXC8oW1xcd1xcLl0rKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZhY2Vib29rIEFwcCBmb3IgaU9TICYgQW5kcm9pZFxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnRmFjZWJvb2snXV0sIFtcblxuICAgICAgICAgICAgL2hlYWRsZXNzY2hyb21lKD86XFwvKFtcXHdcXC5dKyl8XFxzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lIEhlYWRsZXNzXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdDaHJvbWUgSGVhZGxlc3MnXV0sIFtcblxuICAgICAgICAgICAgL1xcc3d2XFwpLisoY2hyb21lKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9tZSBXZWJWaWV3XG4gICAgICAgICAgICBdLCBbW05BTUUsIC8oLispLywgJyQxIFdlYlZpZXcnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLygoPzpvY3VsdXN8c2Ftc3VuZylicm93c2VyKVxcLyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgLyguKyg/Omd8dXMpKSguKykvLCAnJDEgJDInXSwgVkVSU0lPTl0sIFsgICAgICAgICAgICAgICAgLy8gT2N1bHVzIC8gU2Ftc3VuZyBCcm93c2VyXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLit2ZXJzaW9uXFwvKFtcXHdcXC5dKylcXHMrKD86bW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpKi9pICAgICAgICAvLyBBbmRyb2lkIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0FuZHJvaWQgQnJvd3NlciddXSwgW1xuXG4gICAgICAgICAgICAvKGNocm9tZXxvbW5pd2VifGFyb3JhfFt0aXplbm9rYV17NX1cXHM/YnJvd3NlcilcXC92PyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lL09tbmlXZWIvQXJvcmEvVGl6ZW4vTm9raWFcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGRvbGZpbilcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvbHBoaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0RvbHBoaW4nXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLygoPzphbmRyb2lkLispY3Jtb3xjcmlvcylcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaHJvbWUgZm9yIEFuZHJvaWQvaU9TXG4gICAgICAgICAgICBdLCBbW05BTUUsICdDaHJvbWUnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb2FzdClcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPcGVyYSBDb2FzdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEgQ29hc3QnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL2Z4aW9zXFwvKFtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IGZvciBpT1NcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0ZpcmVmb3gnXV0sIFtcblxuICAgICAgICAgICAgL3ZlcnNpb25cXC8oW1xcd1xcLl0rKS4rP21vYmlsZVxcL1xcdytcXHMoc2FmYXJpKS9pICAgICAgICAgICAgICAgICAgICAgICAvLyBNb2JpbGUgU2FmYXJpXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdNb2JpbGUgU2FmYXJpJ11dLCBbXG5cbiAgICAgICAgICAgIC92ZXJzaW9uXFwvKFtcXHdcXC5dKykuKz8obW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpL2kgICAgICAgICAgICAgICAgICAgIC8vIFNhZmFyaSAmIFNhZmFyaSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXSwgW1xuXG4gICAgICAgICAgICAvd2Via2l0Lis/KGdzYSlcXC8oW1xcd1xcLl0rKS4rPyhtb2JpbGVcXHM/c2FmYXJpfHNhZmFyaSkoXFwvW1xcd1xcLl0rKS9pICAvLyBHb29nbGUgU2VhcmNoIEFwcGxpYW5jZSBvbiBpT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0dTQSddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvd2Via2l0Lis/KG1vYmlsZVxccz9zYWZhcml8c2FmYXJpKShcXC9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAvLyBTYWZhcmkgPCAzLjBcbiAgICAgICAgICAgIF0sIFtOQU1FLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5icm93c2VyLm9sZHNhZmFyaS52ZXJzaW9uXV0sIFtcblxuICAgICAgICAgICAgLyhrb25xdWVyb3IpXFwvKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLb25xdWVyb3JcbiAgICAgICAgICAgIC8od2Via2l0fGtodG1sKVxcLyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBHZWNrbyBiYXNlZFxuICAgICAgICAgICAgLyhuYXZpZ2F0b3J8bmV0c2NhcGUpXFwvKFtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOZXRzY2FwZVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnTmV0c2NhcGUnXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oc3dpZnRmb3gpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3dpZnRmb3hcbiAgICAgICAgICAgIC8oaWNlZHJhZ29ufGljZXdlYXNlbHxjYW1pbm98Y2hpbWVyYXxmZW5uZWN8bWFlbW9cXHNicm93c2VyfG1pbmltb3xjb25rZXJvcilbXFwvXFxzXT8oW1xcd1xcLlxcK10rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJY2VEcmFnb24vSWNld2Vhc2VsL0NhbWluby9DaGltZXJhL0Zlbm5lYy9NYWVtby9NaW5pbW8vQ29ua2Vyb3JcbiAgICAgICAgICAgIC8oZmlyZWZveHxzZWFtb25rZXl8ay1tZWxlb258aWNlY2F0fGljZWFwZXxmaXJlYmlyZHxwaG9lbml4fHBhbGVtb29ufGJhc2lsaXNrfHdhdGVyZm94KVxcLyhbXFx3XFwuLV0rKSQvaSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94L1NlYU1vbmtleS9LLU1lbGVvbi9JY2VDYXQvSWNlQXBlL0ZpcmViaXJkL1Bob2VuaXhcbiAgICAgICAgICAgIC8obW96aWxsYSlcXC8oW1xcd1xcLl0rKS4rcnZcXDouK2dlY2tvXFwvXFxkKy9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW96aWxsYVxuXG4gICAgICAgICAgICAvLyBPdGhlclxuICAgICAgICAgICAgLyhwb2xhcmlzfGx5bnh8ZGlsbG98aWNhYnxkb3Jpc3xhbWF5YXx3M218bmV0c3VyZnxzbGVpcG5pcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQb2xhcmlzL0x5bngvRGlsbG8vaUNhYi9Eb3Jpcy9BbWF5YS93M20vTmV0U3VyZi9TbGVpcG5pclxuICAgICAgICAgICAgLyhsaW5rcylcXHNcXCgoW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGlua3NcbiAgICAgICAgICAgIC8oZ29icm93c2VyKVxcLz8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29Ccm93c2VyXG4gICAgICAgICAgICAvKGljZVxccz9icm93c2VyKVxcL3Y/KFtcXHdcXC5fXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQ0UgQnJvd3NlclxuICAgICAgICAgICAgLyhtb3NhaWMpW1xcL1xcc10oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9zYWljXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cblxuICAgICAgICAgICAgLyogLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAgICAgICAvLyBNZWRpYSBwbGF5ZXJzIEJFR0lOXG4gICAgICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICAgICAgICAgICAgLCBbXG5cbiAgICAgICAgICAgIC8oYXBwbGUoPzpjb3JlbWVkaWF8KSlcXC8oKFxcZCspW1xcd1xcLl9dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQXBwbGUgQ29yZU1lZGlhXG4gICAgICAgICAgICAvKGNvcmVtZWRpYSkgdigoXFxkKylbXFx3XFwuX10rKS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhhcXVhbHVuZ3xseXNzbmF8YnNwbGF5ZXIpXFwvKChcXGQrKT9bXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgLy8gQXF1YWx1bmcvTHlzc25hL0JTUGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhhcmVzfG9zc3Byb3h5KVxccygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXJlcy9PU1NQcm94eVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oYXVkYWNpb3VzfGF1ZGltdXNpY3N0cmVhbXxhbWFyb2t8YmFzc3xjb3JlfGRhbHZpa3xnbm9tZW1wbGF5ZXJ8bXVzaWMgb24gY29uc29sZXxuc3BsYXllcnxwc3AtaW50ZXJuZXRyYWRpb3BsYXllcnx2aWRlb3MpXFwvKChcXGQrKVtcXHdcXC4tXSspL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF1ZGFjaW91cy9BdWRpTXVzaWNTdHJlYW0vQW1hcm9rL0JBU1MvT3BlbkNPUkUvRGFsdmlrL0dub21lTXBsYXllci9Nb0NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTlNQbGF5ZXIvUFNQLUludGVybmV0UmFkaW9QbGF5ZXIvVmlkZW9zXG4gICAgICAgICAgICAvKGNsZW1lbnRpbmV8bXVzaWMgcGxheWVyIGRhZW1vbilcXHMoKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAvLyBDbGVtZW50aW5lL01QRFxuICAgICAgICAgICAgLyhsZyBwbGF5ZXJ8bmV4cGxheWVyKVxccygoXFxkKylbXFxkXFwuXSspL2ksXG4gICAgICAgICAgICAvcGxheWVyXFwvKG5leHBsYXllcnxsZyBwbGF5ZXIpXFxzKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgLy8gTmV4UGxheWVyL0xHIFBsYXllclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKG5leHBsYXllcilcXHMoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOZXhwbGF5ZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGZscnApXFwvKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGbGlwIFBsYXllclxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnRmxpcCBQbGF5ZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhmc3RyZWFtfG5hdGl2ZWhvc3R8cXVlcnlzZWVrc3BpZGVyfGlhLWFyY2hpdmVyfGZhY2Vib29rZXh0ZXJuYWxoaXQpL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRlN0cmVhbS9OYXRpdmVIb3N0L1F1ZXJ5U2Vla1NwaWRlci9JQSBBcmNoaXZlci9mYWNlYm9va2V4dGVybmFsaGl0XG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcblxuICAgICAgICAgICAgLyhnc3RyZWFtZXIpIHNvdXBodHRwc3JjICg/OlxcKFteXFwpXStcXCkpezAsMX0gbGlic291cFxcLygoXFxkKylbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdzdHJlYW1lclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjIHN0cmVhbWluZyBwbGF5ZXIpXFxzW1xcd19dK1xcc1xcL1xccygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAvLyBIVEMgU3RyZWFtaW5nIFBsYXllclxuICAgICAgICAgICAgLyhqYXZhfHB5dGhvbi11cmxsaWJ8cHl0aG9uLXJlcXVlc3RzfHdnZXR8bGliY3VybClcXC8oKFxcZCspW1xcd1xcLi1fXSspL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEphdmEvdXJsbGliL3JlcXVlc3RzL3dnZXQvY1VSTFxuICAgICAgICAgICAgLyhsYXZmKSgoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMYXZmIChGRk1QRUcpXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhodGNfb25lX3MpXFwvKChcXGQrKVtcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFRDIE9uZSBTXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikoPzpcXHN8XFwvKSg/Oig/OnNoZXJweWEtKXswLDF9c3ZuKSg/Oi18XFxzKShyXFxkKyg/Oi1cXGQrW1xcd1xcLi1dKyl7MCwxfSkvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyIFNWTlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikoPzpcXHN8XFwvfFt1bmtvdy1dKykoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhtcGxheWVyKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyIChubyBvdGhlciBpbmZvKVxuICAgICAgICAgICAgLyh5b3VybXV6ZSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBZb3VyTXV6ZVxuICAgICAgICAgICAgLyhtZWRpYSBwbGF5ZXIgY2xhc3NpY3xuZXJvIHNob3d0aW1lKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNZWRpYSBQbGF5ZXIgQ2xhc3NpYy9OZXJvIFNob3dUaW1lXG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcblxuICAgICAgICAgICAgLyhuZXJvICg/OmhvbWV8c2NvdXQpKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmVybyBIb21lL05lcm8gU2NvdXRcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG5va2lhXFxkKylcXC8oKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvXFxzKHNvbmdiaXJkKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29uZ2JpcmQvUGhpbGlwcy1Tb25nYmlyZFxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8od2luYW1wKTMgdmVyc2lvbiAoKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luYW1wXG4gICAgICAgICAgICAvKHdpbmFtcClcXHMoKFxcZCspW1xcd1xcLi1dKykvaSxcbiAgICAgICAgICAgIC8od2luYW1wKW1wZWdcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8ob2Ntcy1ib3R8dGFwaW5yYWRpb3x0dW5laW4gcmFkaW98dW5rbm93bnx3aW5hbXB8aW5saWdodCByYWRpbykvaSAgLy8gT0NNUy1ib3QvdGFwIGluIHJhZGlvL3R1bmVpbi91bmtub3duL3dpbmFtcCAobm8gb3RoZXIgaW5mbylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5saWdodCByYWRpb1xuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG5cbiAgICAgICAgICAgIC8ocXVpY2t0aW1lfHJtYXxyYWRpb2FwcHxyYWRpb2NsaWVudGFwcGxpY2F0aW9ufHNvdW5kdGFwfHRvdGVtfHN0YWdlZnJpZ2h0fHN0cmVhbWl1bSlcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRdWlja1RpbWUvUmVhbE1lZGlhL1JhZGlvQXBwL1JhZGlvQ2xpZW50QXBwbGljYXRpb24vXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvdW5kVGFwL1RvdGVtL1N0YWdlZnJpZ2h0L1N0cmVhbWl1bVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oc21wKSgoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU01QXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyh2bGMpIG1lZGlhIHBsYXllciAtIHZlcnNpb24gKChcXGQrKVtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAvLyBWTEMgVmlkZW9sYW5cbiAgICAgICAgICAgIC8odmxjKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLFxuICAgICAgICAgICAgLyh4Ym1jfGd2ZnN8eGluZXx4bW1zfGlyYXBwKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgLy8gWEJNQy9ndmZzL1hpbmUvWE1NUy9pcmFwcFxuICAgICAgICAgICAgLyhmb29iYXIyMDAwKVxcLygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRm9vYmFyMjAwMFxuICAgICAgICAgICAgLyhpdHVuZXMpXFwvKChcXGQrKVtcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVR1bmVzXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyh3bXBsYXllcilcXC8oKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBNZWRpYSBQbGF5ZXJcbiAgICAgICAgICAgIC8od2luZG93cy1tZWRpYS1wbGF5ZXIpXFwvKChcXGQrKVtcXHdcXC4tXSspL2lcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgLy0vZywgJyAnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL3dpbmRvd3NcXC8oKFxcZCspW1xcd1xcLi1dKykgdXBucFxcL1tcXGRcXC5dKyBkbG5hZG9jXFwvW1xcZFxcLl0rIChob21lIG1lZGlhIHNlcnZlcikvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaW5kb3dzIE1lZGlhIFNlcnZlclxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnV2luZG93cyddXSwgW1xuXG4gICAgICAgICAgICAvKGNvbVxcLnJpc2V1cHJhZGlvYWxhcm0pXFwvKChcXGQrKVtcXGRcXC5dKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmlzZVVQIFJhZGlvIEFsYXJtXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhyYWQuaW8pXFxzKChcXGQrKVtcXGRcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmFkLmlvXG4gICAgICAgICAgICAvKHJhZGlvLig/OmRlfGF0fGZyKSlcXHMoKFxcZCspW1xcZFxcLl0rKS9pXG4gICAgICAgICAgICBdLCBbW05BTUUsICdyYWQuaW8nXSwgVkVSU0lPTl1cblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gTWVkaWEgcGxheWVycyBFTkRcbiAgICAgICAgICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGNwdSA6IFtbXG5cbiAgICAgICAgICAgIC8oPzooYW1kfHgoPzooPzo4Nnw2NClbXy1dKT98d293fHdpbik2NClbO1xcKV0vaSAgICAgICAgICAgICAgICAgICAgIC8vIEFNRDY0XG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2FtZDY0J11dLCBbXG5cbiAgICAgICAgICAgIC8oaWEzMig/PTspKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUEzMiAocXVpY2t0aW1lKVxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIHV0aWwubG93ZXJpemVdXSwgW1xuXG4gICAgICAgICAgICAvKCg/OmlbMzQ2XXx4KTg2KVs7XFwpXS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQTMyXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2lhMzInXV0sIFtcblxuICAgICAgICAgICAgLy8gUG9ja2V0UEMgbWlzdGFrZW5seSBpZGVudGlmaWVkIGFzIFBvd2VyUENcbiAgICAgICAgICAgIC93aW5kb3dzXFxzKGNlfG1vYmlsZSk7XFxzcHBjOy9pXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2FybSddXSwgW1xuXG4gICAgICAgICAgICAvKCg/OnBwY3xwb3dlcnBjKSg/OjY0KT8pKD86XFxzbWFjfDt8XFwpKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUG93ZXJQQ1xuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIC9vd2VyLywgJycsIHV0aWwubG93ZXJpemVdXSwgW1xuXG4gICAgICAgICAgICAvKHN1bjRcXHcpWztcXCldL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU1BBUkNcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCAnc3BhcmMnXV0sIFtcblxuICAgICAgICAgICAgLygoPzphdnIzMnxpYTY0KD89OykpfDY4ayg/PVxcKSl8YXJtKD86NjR8KD89dlxcZCs7KSl8KD89YXRtZWxcXHMpYXZyfCg/OmlyaXh8bWlwc3xzcGFyYykoPzo2NCk/KD89Oyl8cGEtcmlzYykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQTY0LCA2OEssIEFSTS82NCwgQVZSLzMyLCBJUklYLzY0LCBNSVBTLzY0LCBTUEFSQy82NCwgUEEtUklTQ1xuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIHV0aWwubG93ZXJpemVdXVxuICAgICAgICBdLFxuXG4gICAgICAgIGRldmljZSA6IFtbXG5cbiAgICAgICAgICAgIC9cXCgoaXBhZHxwbGF5Ym9vayk7W1xcd1xcc1xcKTstXSsocmltfGFwcGxlKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQYWQvUGxheUJvb2tcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgVkVORE9SLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FwcGxlY29yZW1lZGlhXFwvW1xcd1xcLl0rIFxcKChpcGFkKS8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVBhZFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQXBwbGUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oYXBwbGVcXHN7MCwxfXR2KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFwcGxlIFRWXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnQXBwbGUgVFYnXSwgW1ZFTkRPUiwgJ0FwcGxlJ11dLCBbXG5cbiAgICAgICAgICAgIC8oYXJjaG9zKVxccyhnYW1lcGFkMj8pL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFyY2hvc1xuICAgICAgICAgICAgLyhocCkuKyh0b3VjaHBhZCkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIUCBUb3VjaFBhZFxuICAgICAgICAgICAgLyhocCkuKyh0YWJsZXQpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIUCBUYWJsZXRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvXFxzKG5vb2spW1xcd1xcc10rYnVpbGRcXC8oXFx3KykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9va1xuICAgICAgICAgICAgLyhkZWxsKVxccyhzdHJlYVtrcHJcXHNcXGRdKltcXGRrb10pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVsbCBTdHJlYWtcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhrZltBLXpdKylcXHNidWlsZFxcLy4rc2lsa1xcLy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLaW5kbGUgRmlyZSBIRFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhzZHxrZilbMDM0OWhpam9yc3R1d10rXFxzYnVpbGRcXC8uK3NpbGtcXC8vaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlIFBob25lXG4gICAgICAgICAgICBdLCBbW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5hbWF6b24ubW9kZWxdLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFwoKGlwW2hvbmVkfFxcc1xcdypdKyk7LisoYXBwbGUpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQb2QvaVBob25lXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFZFTkRPUiwgW1RZUEUsIE1PQklMRV1dLCBbXG4gICAgICAgICAgICAvXFwoKGlwW2hvbmVkfFxcc1xcdypdKyk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQb2QvaVBob25lXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBcHBsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhibGFja2JlcnJ5KVtcXHMtXT8oXFx3KykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnlcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeXxiZW5xfHBhbG0oPz1cXC0pfHNvbnllcmljc3NvbnxhY2VyfGFzdXN8ZGVsbHxtZWl6dXxtb3Rvcm9sYXxwb2x5dHJvbilbXFxzXy1dPyhbXFx3LV0qKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCZW5RL1BhbG0vU29ueS1Fcmljc3Nvbi9BY2VyL0FzdXMvRGVsbC9NZWl6dS9Nb3Rvcm9sYS9Qb2x5dHJvblxuICAgICAgICAgICAgLyhocClcXHMoW1xcd1xcc10rXFx3KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgaVBBUVxuICAgICAgICAgICAgLyhhc3VzKS0/KFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXN1c1xuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL1xcKGJiMTA7XFxzKFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCbGFja0JlcnJ5IDEwXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdCbGFja0JlcnJ5J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBc3VzIFRhYmxldHNcbiAgICAgICAgICAgIC9hbmRyb2lkLisodHJhbnNmb1twcmltZVxcc117NCwxMH1cXHNcXHcrfGVlZXBjfHNsaWRlclxcc1xcdyt8bmV4dXMgN3xwYWRmb25lKS9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBc3VzJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKHNvbnkpXFxzKHRhYmxldFxcc1twc10pXFxzYnVpbGRcXC8vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueVxuICAgICAgICAgICAgLyhzb255KT8oPzpzZ3AuKylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NvbnknXSwgW01PREVMLCAnWHBlcmlhIFRhYmxldCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcbiAgICAgICAgICAgIC9hbmRyb2lkLitcXHMoW2MtZ11cXGR7NH18c29bLWxdXFx3KylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFxzKG91eWEpXFxzL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3V5YVxuICAgICAgICAgICAgLyhuaW50ZW5kbylcXHMoW3dpZHMzdV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG9cbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKHNoaWVsZClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOdmlkaWFcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ052aWRpYSddLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC8ocGxheXN0YXRpb25cXHNbMzRwb3J0YWJsZXZpXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYXlzdGF0aW9uXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBDT05TT0xFXV0sIFtcblxuICAgICAgICAgICAgLyhzcHJpbnRcXHMoXFx3KykpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNwcmludCBQaG9uZXNcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQudmVuZG9yXSwgW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQubW9kZWxdLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhsZW5vdm8pXFxzPyhTKD86NTAwMHw2MDAwKSsoPzpbLV1bXFx3K10pKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92byB0YWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjKVs7X1xccy1dKyhbXFx3XFxzXSsoPz1cXCkpfFxcdyspKi9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIVENcbiAgICAgICAgICAgIC8oenRlKS0oXFx3KikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURVxuICAgICAgICAgICAgLyhhbGNhdGVsfGdlZWtzcGhvbmV8bGVub3ZvfG5leGlhbnxwYW5hc29uaWN8KD89O1xccylzb255KVtfXFxzLV0/KFtcXHctXSopL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxjYXRlbC9HZWVrc1Bob25lL0xlbm92by9OZXhpYW4vUGFuYXNvbmljL1NvbnlcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIFtNT0RFTCwgL18vZywgJyAnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8obmV4dXNcXHM5KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhUQyBOZXh1cyA5XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdIVEMnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9kXFwvaHVhd2VpKFtcXHdcXHMtXSspWztcXCldL2ksXG4gICAgICAgICAgICAvKG5leHVzXFxzNnApL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdWF3ZWlcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0h1YXdlaSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtaWNyb3NvZnQpO1xccyhsdW1pYVtcXHNcXHddKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaWNyb3NvZnQgTHVtaWFcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL1tcXHNcXCg7XSh4Ym94KD86XFxzb25lKT8pW1xcc1xcKTtdL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBYYm94XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNaWNyb3NvZnQnXSwgW1RZUEUsIENPTlNPTEVdXSwgW1xuICAgICAgICAgICAgLyhraW5cXC5bb25ldHddezN9KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWljcm9zb2Z0IEtpblxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgL1xcLi9nLCAnICddLCBbVkVORE9SLCAnTWljcm9zb2Z0J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1vdG9yb2xhXG4gICAgICAgICAgICAvXFxzKG1pbGVzdG9uZXxkcm9pZCg/OlsyLTR4XXxcXHMoPzpiaW9uaWN8eDJ8cHJvfHJhenIpKT86PyhcXHM0Zyk/KVtcXHdcXHNdK2J1aWxkXFwvL2ksXG4gICAgICAgICAgICAvbW90W1xccy1dPyhcXHcqKS9pLFxuICAgICAgICAgICAgLyhYVFxcZHszLDR9KSBidWlsZFxcLy9pLFxuICAgICAgICAgICAgLyhuZXh1c1xcczYpL2lcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01vdG9yb2xhJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuK1xccyhtejYwXFxkfHhvb21bXFxzMl17MCwyfSlcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNb3Rvcm9sYSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2hiYnR2XFwvXFxkK1xcLlxcZCtcXC5cXGQrXFxzK1xcKFtcXHdcXHNdKjtcXHMqKFxcd1teO10qKTsoW147XSopL2kgICAgICAgICAgICAvLyBIYmJUViBkZXZpY2VzXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgdXRpbC50cmltXSwgW01PREVMLCB1dGlsLnRyaW1dLCBbVFlQRSwgU01BUlRUVl1dLCBbXG5cbiAgICAgICAgICAgIC9oYmJ0di4rbWFwbGU7KFxcZCspL2lcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIC9eLywgJ1NtYXJ0VFYnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFNNQVJUVFZdXSwgW1xuXG4gICAgICAgICAgICAvXFwoZHR2W1xcKTtdLisoYXF1b3MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2hhcnBcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1NoYXJwJ10sIFtUWVBFLCBTTUFSVFRWXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKygoc2NoLWlbODldMFxcZHxzaHctbTM4MHN8Z3QtcFxcZHs0fXxndC1uXFxkK3xzZ2gtdDhbNTZdOXxuZXh1cyAxMCkpL2ksXG4gICAgICAgICAgICAvKChTTS1UXFx3KykpL2lcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnU2Ftc3VuZyddLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZ1xuICAgICAgICAgICAgL3NtYXJ0LXR2Lisoc2Ftc3VuZykvaVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgW1RZUEUsIFNNQVJUVFZdLCBNT0RFTF0sIFtcbiAgICAgICAgICAgIC8oKHNbY2dwXWgtXFx3K3xndC1cXHcrfGdhbGF4eVxcc25leHVzfHNtLVxcd1tcXHdcXGRdKykpL2ksXG4gICAgICAgICAgICAvKHNhbVtzdW5nXSopW1xccy1dKihcXHcrLT9bXFx3LV0qKS9pLFxuICAgICAgICAgICAgL3NlYy0oKHNnaFxcdyspKS9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvc2llLShcXHcqKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaWVtZW5zXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTaWVtZW5zJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKG1hZW1vfG5va2lhKS4qKG45MDB8bHVtaWFcXHNcXGQrKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIC8obm9raWEpW1xcc18tXT8oW1xcdy1dKikvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdOb2tpYSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkXFxzM1xcLltcXHNcXHc7LV17MTB9KGFcXGR7M30pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBY2VyXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBY2VyJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKFt2bF1rXFwtP1xcZHszfSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTEcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZFxcczNcXC5bXFxzXFx3Oy1dezEwfShsZz8pLShbMDZjdjldezMsNH0pL2kgICAgICAgICAgICAgICAgICAgICAvLyBMRyBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnTEcnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhsZykgbmV0Y2FzdFxcLnR2L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTEcgU21hcnRUVlxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBTTUFSVFRWXV0sIFtcbiAgICAgICAgICAgIC8obmV4dXNcXHNbNDVdKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHXG4gICAgICAgICAgICAvbGdbZTtcXHNcXC8tXSsoXFx3KikvaSxcbiAgICAgICAgICAgIC9hbmRyb2lkLitsZyhcXC0/W1xcZFxcd10rKVxccytidWlsZC9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdMRyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKyhpZGVhdGFiW2EtejAtOVxcLVxcc10rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92b1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTGVub3ZvJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvbGludXg7LisoKGpvbGxhKSk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEpvbGxhXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8oKHBlYmJsZSkpYXBwXFwvW1xcZFxcLl0rXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBlYmJsZVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBXRUFSQUJMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKG9wcG8pXFxzPyhbXFx3XFxzXSspXFxzYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPUFBPXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9jcmtleS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIENocm9tZWNhc3RcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdDaHJvbWVjYXN0J10sIFtWRU5ET1IsICdHb29nbGUnXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMoZ2xhc3MpXFxzXFxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHb29nbGUgR2xhc3NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dvb2dsZSddLCBbVFlQRSwgV0VBUkFCTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhwaXhlbCBjKVxccy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIFBpeGVsIENcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dvb2dsZSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMocGl4ZWwgeGx8cGl4ZWwpXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdvb2dsZSBQaXhlbFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnR29vZ2xlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhcXHcrKVxccytidWlsZFxcL2htXFwxL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWGlhb21pIEhvbmdtaSAnbnVtZXJpYycgbW9kZWxzXG4gICAgICAgICAgICAvYW5kcm9pZC4rKGhtW1xcc1xcLV9dKm5vdGU/W1xcc19dKig/OlxcZFxcdyk/KVxccytidWlsZC9pLCAgICAgICAgICAgICAgIC8vIFhpYW9taSBIb25nbWlcbiAgICAgICAgICAgIC9hbmRyb2lkLisobWlbXFxzXFwtX10qKD86b25lfG9uZVtcXHNfXXBsdXN8bm90ZSBsdGUpP1tcXHNfXSooPzpcXGQ/XFx3PylbXFxzX10qKD86cGx1cyk/KVxccytidWlsZC9pLCAgICAvLyBYaWFvbWkgTWlcbiAgICAgICAgICAgIC9hbmRyb2lkLisocmVkbWlbXFxzXFwtX10qKD86bm90ZSk/KD86W1xcc19dKltcXHdcXHNdKykpXFxzK2J1aWxkL2kgICAgICAgLy8gUmVkbWkgUGhvbmVzXG4gICAgICAgICAgICBdLCBbW01PREVMLCAvXy9nLCAnICddLCBbVkVORE9SLCAnWGlhb21pJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuKyhtaVtcXHNcXC1fXSooPzpwYWQpKD86W1xcc19dKltcXHdcXHNdKykpXFxzK2J1aWxkL2kgICAgICAgICAgICAvLyBNaSBQYWQgdGFibGV0c1xuICAgICAgICAgICAgXSxbW01PREVMLCAvXy9nLCAnICddLCBbVkVORE9SLCAnWGlhb21pJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMobVsxLTVdXFxzbm90ZSlcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNZWl6dSBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01laXp1J10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rYTAwMCgxKVxccytidWlsZC9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmVQbHVzXG4gICAgICAgICAgICAvYW5kcm9pZC4rb25lcGx1c1xccyhhXFxkezR9KVxccytidWlsZC9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdPbmVQbHVzJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihSQ1RbXFxkXFx3XSspXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUkNBIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1JDQSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXFxzXSsoVmVudWVbXFxkXFxzXXsyLDd9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGwgVmVudWUgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnRGVsbCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooUVtUfE1dW1xcZFxcd10rKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFZlcml6b24gVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdWZXJpem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhCYXJuZXNbJlxcc10rTm9ibGVcXHMrfEJOW1JUXSkoVj8uKilcXHMrYnVpbGQvaSAgICAgLy8gQmFybmVzICYgTm9ibGUgVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0Jhcm5lcyAmIE5vYmxlJ10sIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccysoVE1cXGR7M30uKlxcYilcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJhcm5lcyAmIE5vYmxlIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTnVWaXNpb24nXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKGs4OClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBaVEUgSyBTZXJpZXMgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdaVEUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKGdlblxcZHszfSlcXHMrYnVpbGQuKjQ5aC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN3aXNzIEdFTiBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1N3aXNzJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKih6dXJcXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTd2lzcyBaVVIgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTd2lzcyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooKFpla2kpP1RCLipcXGIpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWmVraSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdaZWtpJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKGFuZHJvaWQpLitbO1xcL11cXHMrKFtZUl1cXGR7Mn0pXFxzK2J1aWxkL2ksXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhEcmFnb25bXFwtXFxzXStUb3VjaFxccyt8RFQpKFxcd3s1fSlcXHNidWlsZC9pICAgICAgICAvLyBEcmFnb24gVG91Y2ggVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0RyYWdvbiBUb3VjaCddLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKE5TLT9cXHd7MCw5fSlcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluc2lnbmlhIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0luc2lnbmlhJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKigoTlh8TmV4dCktP1xcd3swLDl9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAvLyBOZXh0Qm9vayBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdOZXh0Qm9vayddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooWHRyZW1lXFxfKT8oVigxWzA0NV18MlswMTVdfDMwfDQwfDYwfDdbMDVdfDkwKSlcXHMrYnVpbGQvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdWb2ljZSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbICAgICAgICAgICAgICAgICAgICAvLyBWb2ljZSBYdHJlbWUgUGhvbmVzXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKExWVEVMXFwtKT8oVjFbMTJdKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgLy8gTHZUZWwgUGhvbmVzXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0x2VGVsJ10sIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooVigxMDBNRHw3MDBOQXw3MDExfDkxN0cpLipcXGIpXFxzK2J1aWxkL2kgICAgICAgICAgLy8gRW52aXplbiBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdFbnZpemVuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihMZVtcXHNcXC1dK1BhbilbXFxzXFwtXSsoXFx3ezEsOX0pXFxzK2J1aWxkL2kgICAgICAgICAgLy8gTGUgUGFuIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooVHJpb1tcXHNcXC1dKi4qKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hY2hTcGVlZCBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNYWNoU3BlZWQnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFRyaW5pdHkpW1xcLVxcc10qKFRcXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgLy8gVHJpbml0eSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqVFVfKDE0OTEpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUm90b3IgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnUm90b3InXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLisoS1MoLispKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFtYXpvbiBLaW5kbGUgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKEdpZ2FzZXQpW1xcc1xcLV0rKFFcXHd7MSw5fSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAvLyBHaWdhc2V0IFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL1xccyh0YWJsZXR8dGFiKVs7XFwvXS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVuaWRlbnRpZmlhYmxlIFRhYmxldFxuICAgICAgICAgICAgL1xccyhtb2JpbGUpKD86WztcXC9dfFxcc3NhZmFyaSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVbmlkZW50aWZpYWJsZSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtbVFlQRSwgdXRpbC5sb3dlcml6ZV0sIFZFTkRPUiwgTU9ERUxdLCBbXG5cbiAgICAgICAgICAgIC8oYW5kcm9pZFtcXHdcXC5cXHNcXC1dezAsOX0pOy4rYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQW5kcm9pZCBEZXZpY2VcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dlbmVyaWMnXV1cblxuXG4gICAgICAgIC8qLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgICAgICAgIC8vIFRPRE86IG1vdmUgdG8gc3RyaW5nIG1hcFxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAgICAgICAvKEM2NjAzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbnkgWHBlcmlhIFogQzY2MDNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdYcGVyaWEgWiBDNjYwMyddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oQzY5MDMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueSBYcGVyaWEgWiAxXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnWHBlcmlhIFogMSddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhTTS1HOTAwW0Z8SF0pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBTNVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBTNSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzcxMDIpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgR3JhbmQgMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCAyJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1HNTMwSCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBHcmFuZCBQcmltZVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCBQcmltZSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzMxM0haKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBWJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1UODA1KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBUYWIgUyAxMC41XG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiBTIDEwLjUnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvKFNNLUc4MDBGKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhbXN1bmcgR2FsYXh5IFM1IE1pbmlcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdHYWxheHkgUzUgTWluaSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tVDMxMSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVGFiIDMgOC4wXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiAzIDguMCddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhUM0MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBUM0NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBUMUpcXCspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWR2YW4gVmFuZHJvaWQgVDFKK1xuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1ZhbmRyb2lkIFQxSisnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBTNEEpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBTNEFcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdWYW5kcm9pZCBTNEEnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKFY5NzJNKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURSBWOTcyTVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnWlRFJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKGktbW9iaWxlKVxccyhJUVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhJUTYuMykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUSBJUSA2LjNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdJUSA2LjMnXSwgW1ZFTkRPUiwgJ2ktbW9iaWxlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLW1vYmlsZSlcXHMoaS1zdHlsZVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaS1tb2JpbGUgaS1TVFlMRVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLVNUWUxFMi4xKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBpLVNUWUxFIDIuMVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ2ktU1RZTEUgMi4xJ10sIFtWRU5ET1IsICdpLW1vYmlsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1RvdWNoIExBSSA1MTInXSwgW1ZFTkRPUiwgJ21vYmlpc3RhciddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gRU5EIFRPRE9cbiAgICAgICAgICAgIC8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGVuZ2luZSA6IFtbXG5cbiAgICAgICAgICAgIC93aW5kb3dzLitcXHNlZGdlXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVkZ2VIVE1MXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdFZGdlSFRNTCddXSwgW1xuXG4gICAgICAgICAgICAvKHByZXN0bylcXC8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZXN0b1xuICAgICAgICAgICAgLyh3ZWJraXR8dHJpZGVudHxuZXRmcm9udHxuZXRzdXJmfGFtYXlhfGx5bnh8dzNtKVxcLyhbXFx3XFwuXSspL2ksICAgICAvLyBXZWJLaXQvVHJpZGVudC9OZXRGcm9udC9OZXRTdXJmL0FtYXlhL0x5bngvdzNtXG4gICAgICAgICAgICAvKGtodG1sfHRhc21hbnxsaW5rcylbXFwvXFxzXVxcKD8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS0hUTUwvVGFzbWFuL0xpbmtzXG4gICAgICAgICAgICAvKGljYWIpW1xcL1xcc10oWzIzXVxcLltcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaUNhYlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9ydlxcOihbXFx3XFwuXXsxLDl9KS4rKGdlY2tvKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2Vja29cbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXVxuICAgICAgICBdLFxuXG4gICAgICAgIG9zIDogW1tcblxuICAgICAgICAgICAgLy8gV2luZG93cyBiYXNlZFxuICAgICAgICAgICAgL21pY3Jvc29mdFxccyh3aW5kb3dzKVxccyh2aXN0YXx4cCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgKGlUdW5lcylcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyh3aW5kb3dzKVxcc250XFxzNlxcLjI7XFxzKGFybSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBSVFxuICAgICAgICAgICAgLyh3aW5kb3dzXFxzcGhvbmUoPzpcXHNvcykqKVtcXHNcXC9dPyhbXFxkXFwuXFxzXFx3XSopL2ksICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgUGhvbmVcbiAgICAgICAgICAgIC8od2luZG93c1xcc21vYmlsZXx3aW5kb3dzKVtcXHNcXC9dPyhbbnRjZVxcZFxcLlxcc10rXFx3KS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgW1ZFUlNJT04sIG1hcHBlci5zdHIsIG1hcHMub3Mud2luZG93cy52ZXJzaW9uXV0sIFtcbiAgICAgICAgICAgIC8od2luKD89M3w5fG4pfHdpblxcczl4XFxzKShbbnRcXGRcXC5dKykvaVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnV2luZG93cyddLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5vcy53aW5kb3dzLnZlcnNpb25dXSwgW1xuXG4gICAgICAgICAgICAvLyBNb2JpbGUvRW1iZWRkZWQgT1NcbiAgICAgICAgICAgIC9cXCgoYmIpKDEwKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnkgMTBcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0JsYWNrQmVycnknXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeSlcXHcqXFwvPyhbXFx3XFwuXSopL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrYmVycnlcbiAgICAgICAgICAgIC8odGl6ZW4pW1xcL1xcc10oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRpemVuXG4gICAgICAgICAgICAvKGFuZHJvaWR8d2Vib3N8cGFsbVxcc29zfHFueHxiYWRhfHJpbVxcc3RhYmxldFxcc29zfG1lZWdvfGNvbnRpa2kpW1xcL1xccy1dPyhbXFx3XFwuXSopL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFuZHJvaWQvV2ViT1MvUGFsbS9RTlgvQmFkYS9SSU0vTWVlR28vQ29udGlraVxuICAgICAgICAgICAgL2xpbnV4Oy4rKHNhaWxmaXNoKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYWlsZmlzaCBPU1xuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKHN5bWJpYW5cXHM/b3N8c3ltYm9zfHM2MCg/PTspKVtcXC9cXHMtXT8oW1xcd1xcLl0qKS9pICAgICAgICAgICAgICAgICAgLy8gU3ltYmlhblxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU3ltYmlhbiddLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgL1xcKChzZXJpZXM0MCk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2VyaWVzIDQwXG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcbiAgICAgICAgICAgIC9tb3ppbGxhLitcXChtb2JpbGU7LitnZWNrby4rZmlyZWZveC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0ZpcmVmb3ggT1MnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gQ29uc29sZVxuICAgICAgICAgICAgLyhuaW50ZW5kb3xwbGF5c3RhdGlvbilcXHMoW3dpZHMzNHBvcnRhYmxldnVdKykvaSwgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG8vUGxheXN0YXRpb25cblxuICAgICAgICAgICAgLy8gR05VL0xpbnV4IGJhc2VkXG4gICAgICAgICAgICAvKG1pbnQpW1xcL1xcc1xcKF0/KFxcdyopL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaW50XG4gICAgICAgICAgICAvKG1hZ2VpYXx2ZWN0b3JsaW51eClbO1xcc10vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWdlaWEvVmVjdG9yTGludXhcbiAgICAgICAgICAgIC8oam9saXxba3hsbl0/dWJ1bnR1fGRlYmlhbnxzdXNlfG9wZW5zdXNlfGdlbnRvb3woPz1cXHMpYXJjaHxzbGFja3dhcmV8ZmVkb3JhfG1hbmRyaXZhfGNlbnRvc3xwY2xpbnV4b3N8cmVkaGF0fHplbndhbGt8bGlucHVzKVtcXC9cXHMtXT8oPyFjaHJvbSkoW1xcd1xcLi1dKikvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSm9saS9VYnVudHUvRGViaWFuL1NVU0UvR2VudG9vL0FyY2gvU2xhY2t3YXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZlZG9yYS9NYW5kcml2YS9DZW50T1MvUENMaW51eE9TL1JlZEhhdC9aZW53YWxrL0xpbnB1c1xuICAgICAgICAgICAgLyhodXJkfGxpbnV4KVxccz8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdXJkL0xpbnV4XG4gICAgICAgICAgICAvKGdudSlcXHM/KFtcXHdcXC5dKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdOVVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oY3JvcylcXHNbXFx3XStcXHMoW1xcd1xcLl0rXFx3KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21pdW0gT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0Nocm9taXVtIE9TJ10sIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgLyhzdW5vcylcXHM/KFtcXHdcXC5cXGRdKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU29sYXJpcyddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBCU0QgYmFzZWRcbiAgICAgICAgICAgIC9cXHMoW2ZyZW50b3BjLV17MCw0fWJzZHxkcmFnb25mbHkpXFxzPyhbXFx3XFwuXSopL2kgICAgICAgICAgICAgICAgICAgIC8vIEZyZWVCU0QvTmV0QlNEL09wZW5CU0QvUEMtQlNEL0RyYWdvbkZseVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLyhoYWlrdSlcXHMoXFx3KykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhhaWt1XG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sW1xuXG4gICAgICAgICAgICAvY2ZuZXR3b3JrXFwvLitkYXJ3aW4vaSxcbiAgICAgICAgICAgIC9pcFtob25lYWRdezIsNH0oPzouKm9zXFxzKFtcXHddKylcXHNsaWtlXFxzbWFjfDtcXHNvcGVyYSkvaSAgICAgICAgICAgICAvLyBpT1NcbiAgICAgICAgICAgIF0sIFtbVkVSU0lPTiwgL18vZywgJy4nXSwgW05BTUUsICdpT1MnXV0sIFtcblxuICAgICAgICAgICAgLyhtYWNcXHNvc1xcc3gpXFxzPyhbXFx3XFxzXFwuXSopL2ksXG4gICAgICAgICAgICAvKG1hY2ludG9zaHxtYWMoPz1fcG93ZXJwYylcXHMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWMgT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ01hYyBPUyddLCBbVkVSU0lPTiwgL18vZywgJy4nXV0sIFtcblxuICAgICAgICAgICAgLy8gT3RoZXJcbiAgICAgICAgICAgIC8oKD86b3Blbik/c29sYXJpcylbXFwvXFxzLV0/KFtcXHdcXC5dKikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbGFyaXNcbiAgICAgICAgICAgIC8oYWl4KVxccygoXFxkKSg/PVxcLnxcXCl8XFxzKVtcXHdcXC5dKSovaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFJWFxuICAgICAgICAgICAgLyhwbGFuXFxzOXxtaW5peHxiZW9zfG9zXFwvMnxhbWlnYW9zfG1vcnBob3N8cmlzY1xcc29zfG9wZW52bXMpL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYW45L01pbml4L0JlT1MvT1MyL0FtaWdhT1MvTW9ycGhPUy9SSVNDT1MvT3BlblZNU1xuICAgICAgICAgICAgLyh1bml4KVxccz8oW1xcd1xcLl0qKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVTklYXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cbiAgICAgICAgXVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQ29uc3RydWN0b3JcbiAgICAvLy8vLy8vLy8vLy8vLy8vXG4gICAgLypcbiAgICB2YXIgQnJvd3NlciA9IGZ1bmN0aW9uIChuYW1lLCB2ZXJzaW9uKSB7XG4gICAgICAgIHRoaXNbTkFNRV0gPSBuYW1lO1xuICAgICAgICB0aGlzW1ZFUlNJT05dID0gdmVyc2lvbjtcbiAgICB9O1xuICAgIHZhciBDUFUgPSBmdW5jdGlvbiAoYXJjaCkge1xuICAgICAgICB0aGlzW0FSQ0hJVEVDVFVSRV0gPSBhcmNoO1xuICAgIH07XG4gICAgdmFyIERldmljZSA9IGZ1bmN0aW9uICh2ZW5kb3IsIG1vZGVsLCB0eXBlKSB7XG4gICAgICAgIHRoaXNbVkVORE9SXSA9IHZlbmRvcjtcbiAgICAgICAgdGhpc1tNT0RFTF0gPSBtb2RlbDtcbiAgICAgICAgdGhpc1tUWVBFXSA9IHR5cGU7XG4gICAgfTtcbiAgICB2YXIgRW5naW5lID0gQnJvd3NlcjtcbiAgICB2YXIgT1MgPSBCcm93c2VyO1xuICAgICovXG4gICAgdmFyIFVBUGFyc2VyID0gZnVuY3Rpb24gKHVhc3RyaW5nLCBleHRlbnNpb25zKSB7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB1YXN0cmluZyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGV4dGVuc2lvbnMgPSB1YXN0cmluZztcbiAgICAgICAgICAgIHVhc3RyaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFVBUGFyc2VyKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBVQVBhcnNlcih1YXN0cmluZywgZXh0ZW5zaW9ucykuZ2V0UmVzdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdWEgPSB1YXN0cmluZyB8fCAoKHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yICYmIHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50KSA/IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50IDogRU1QVFkpO1xuICAgICAgICB2YXIgcmd4bWFwID0gZXh0ZW5zaW9ucyA/IHV0aWwuZXh0ZW5kKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIDogcmVnZXhlcztcbiAgICAgICAgLy92YXIgYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgIC8vdmFyIGNwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgLy92YXIgZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAvL3ZhciBlbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgIC8vdmFyIG9zID0gbmV3IE9TKCk7XG5cbiAgICAgICAgdGhpcy5nZXRCcm93c2VyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGJyb3dzZXIgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoYnJvd3NlciwgdWEsIHJneG1hcC5icm93c2VyKTtcbiAgICAgICAgICAgIGJyb3dzZXIubWFqb3IgPSB1dGlsLm1ham9yKGJyb3dzZXIudmVyc2lvbik7IC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgICAgIHJldHVybiBicm93c2VyO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENQVSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjcHUgPSB7IGFyY2hpdGVjdHVyZTogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoY3B1LCB1YSwgcmd4bWFwLmNwdSk7XG4gICAgICAgICAgICByZXR1cm4gY3B1O1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldERldmljZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBkZXZpY2UgPSB7IHZlbmRvcjogdW5kZWZpbmVkLCBtb2RlbDogdW5kZWZpbmVkLCB0eXBlOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChkZXZpY2UsIHVhLCByZ3htYXAuZGV2aWNlKTtcbiAgICAgICAgICAgIHJldHVybiBkZXZpY2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0RW5naW5lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVuZ2luZSA9IHsgbmFtZTogdW5kZWZpbmVkLCB2ZXJzaW9uOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChlbmdpbmUsIHVhLCByZ3htYXAuZW5naW5lKTtcbiAgICAgICAgICAgIHJldHVybiBlbmdpbmU7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0T1MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgb3MgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwob3MsIHVhLCByZ3htYXAub3MpO1xuICAgICAgICAgICAgcmV0dXJuIG9zO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldFJlc3VsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdWEgICAgICA6IHRoaXMuZ2V0VUEoKSxcbiAgICAgICAgICAgICAgICBicm93c2VyIDogdGhpcy5nZXRCcm93c2VyKCksXG4gICAgICAgICAgICAgICAgZW5naW5lICA6IHRoaXMuZ2V0RW5naW5lKCksXG4gICAgICAgICAgICAgICAgb3MgICAgICA6IHRoaXMuZ2V0T1MoKSxcbiAgICAgICAgICAgICAgICBkZXZpY2UgIDogdGhpcy5nZXREZXZpY2UoKSxcbiAgICAgICAgICAgICAgICBjcHUgICAgIDogdGhpcy5nZXRDUFUoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRVQSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB1YTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZXRVQSA9IGZ1bmN0aW9uICh1YXN0cmluZykge1xuICAgICAgICAgICAgdWEgPSB1YXN0cmluZztcbiAgICAgICAgICAgIC8vYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgICAgICAvL2NwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgICAgIC8vZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAgICAgLy9lbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgICAgICAvL29zID0gbmV3IE9TKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIFVBUGFyc2VyLlZFUlNJT04gPSBMSUJWRVJTSU9OO1xuICAgIFVBUGFyc2VyLkJST1dTRVIgPSB7XG4gICAgICAgIE5BTUUgICAgOiBOQU1FLFxuICAgICAgICBNQUpPUiAgIDogTUFKT1IsIC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgVkVSU0lPTiA6IFZFUlNJT05cbiAgICB9O1xuICAgIFVBUGFyc2VyLkNQVSA9IHtcbiAgICAgICAgQVJDSElURUNUVVJFIDogQVJDSElURUNUVVJFXG4gICAgfTtcbiAgICBVQVBhcnNlci5ERVZJQ0UgPSB7XG4gICAgICAgIE1PREVMICAgOiBNT0RFTCxcbiAgICAgICAgVkVORE9SICA6IFZFTkRPUixcbiAgICAgICAgVFlQRSAgICA6IFRZUEUsXG4gICAgICAgIENPTlNPTEUgOiBDT05TT0xFLFxuICAgICAgICBNT0JJTEUgIDogTU9CSUxFLFxuICAgICAgICBTTUFSVFRWIDogU01BUlRUVixcbiAgICAgICAgVEFCTEVUICA6IFRBQkxFVCxcbiAgICAgICAgV0VBUkFCTEU6IFdFQVJBQkxFLFxuICAgICAgICBFTUJFRERFRDogRU1CRURERURcbiAgICB9O1xuICAgIFVBUGFyc2VyLkVOR0lORSA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICBVQVBhcnNlci5PUyA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICAvL1VBUGFyc2VyLlV0aWxzID0gdXRpbDtcblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gRXhwb3J0XG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICAvLyBjaGVjayBqcyBlbnZpcm9ubWVudFxuICAgIGlmICh0eXBlb2YoZXhwb3J0cykgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgLy8gbm9kZWpzIGVudlxuICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gVU5ERUZfVFlQRSAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogdGVzdCEhISEhISEhXG4gICAgICAgIC8qXG4gICAgICAgIGlmIChyZXF1aXJlICYmIHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlICYmIHByb2Nlc3MpIHtcbiAgICAgICAgICAgIC8vIGNsaVxuICAgICAgICAgICAgdmFyIGpzb25pemUgPSBmdW5jdGlvbiAoYXJyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gYXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wdXNoKG5ldyBVQVBhcnNlcihhcnJbaV0pLmdldFJlc3VsdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoSlNPTi5zdHJpbmdpZnkocmVzLCBudWxsLCAyKSArICdcXG4nKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAocHJvY2Vzcy5zdGRpbi5pc1RUWSkge1xuICAgICAgICAgICAgICAgIC8vIHZpYSBhcmdzXG4gICAgICAgICAgICAgICAganNvbml6ZShwcm9jZXNzLmFyZ3Yuc2xpY2UoMikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB2aWEgcGlwZVxuICAgICAgICAgICAgICAgIHZhciBzdHIgPSAnJztcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdyZWFkYWJsZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVhZCA9IHByb2Nlc3Muc3RkaW4ucmVhZCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVhZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyICs9IHJlYWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGpzb25pemUoc3RyLnJlcGxhY2UoL1xcbiQvLCAnJykuc3BsaXQoJ1xcbicpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICBleHBvcnRzLlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVxdWlyZWpzIGVudiAob3B0aW9uYWwpXG4gICAgICAgIGlmICh0eXBlb2YoZGVmaW5lKSA9PT0gRlVOQ19UWVBFICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFVBUGFyc2VyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAod2luZG93KSB7XG4gICAgICAgICAgICAvLyBicm93c2VyIGVudlxuICAgICAgICAgICAgd2luZG93LlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBqUXVlcnkvWmVwdG8gc3BlY2lmaWMgKG9wdGlvbmFsKVxuICAgIC8vIE5vdGU6XG4gICAgLy8gICBJbiBBTUQgZW52IHRoZSBnbG9iYWwgc2NvcGUgc2hvdWxkIGJlIGtlcHQgY2xlYW4sIGJ1dCBqUXVlcnkgaXMgYW4gZXhjZXB0aW9uLlxuICAgIC8vICAgalF1ZXJ5IGFsd2F5cyBleHBvcnRzIHRvIGdsb2JhbCBzY29wZSwgdW5sZXNzIGpRdWVyeS5ub0NvbmZsaWN0KHRydWUpIGlzIHVzZWQsXG4gICAgLy8gICBhbmQgd2Ugc2hvdWxkIGNhdGNoIHRoYXQuXG4gICAgdmFyICQgPSB3aW5kb3cgJiYgKHdpbmRvdy5qUXVlcnkgfHwgd2luZG93LlplcHRvKTtcbiAgICBpZiAodHlwZW9mICQgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgdmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcigpO1xuICAgICAgICAkLnVhID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAkLnVhLmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZXIuZ2V0VUEoKTtcbiAgICAgICAgfTtcbiAgICAgICAgJC51YS5zZXQgPSBmdW5jdGlvbiAodWFzdHJpbmcpIHtcbiAgICAgICAgICAgIHBhcnNlci5zZXRVQSh1YXN0cmluZyk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAkLnVhW3Byb3BdID0gcmVzdWx0W3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxufSkodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgPyB3aW5kb3cgOiB0aGlzKTtcbiIsInZhciB2MSA9IHJlcXVpcmUoJy4vdjEnKTtcbnZhciB2NCA9IHJlcXVpcmUoJy4vdjQnKTtcblxudmFyIHV1aWQgPSB2NDtcbnV1aWQudjEgPSB2MTtcbnV1aWQudjQgPSB2NDtcblxubW9kdWxlLmV4cG9ydHMgPSB1dWlkO1xuIiwiLyoqXG4gKiBDb252ZXJ0IGFycmF5IG9mIDE2IGJ5dGUgdmFsdWVzIHRvIFVVSUQgc3RyaW5nIGZvcm1hdCBvZiB0aGUgZm9ybTpcbiAqIFhYWFhYWFhYLVhYWFgtWFhYWC1YWFhYLVhYWFhYWFhYWFhYWFxuICovXG52YXIgYnl0ZVRvSGV4ID0gW107XG5mb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgKytpKSB7XG4gIGJ5dGVUb0hleFtpXSA9IChpICsgMHgxMDApLnRvU3RyaW5nKDE2KS5zdWJzdHIoMSk7XG59XG5cbmZ1bmN0aW9uIGJ5dGVzVG9VdWlkKGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gb2Zmc2V0IHx8IDA7XG4gIHZhciBidGggPSBieXRlVG9IZXg7XG4gIHJldHVybiBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxuXG4vLyBnZXRSYW5kb21WYWx1ZXMgbmVlZHMgdG8gYmUgaW52b2tlZCBpbiBhIGNvbnRleHQgd2hlcmUgXCJ0aGlzXCIgaXMgYSBDcnlwdG8gaW1wbGVtZW50YXRpb24uXG52YXIgZ2V0UmFuZG9tVmFsdWVzID0gKHR5cGVvZihjcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChjcnlwdG8pKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICh0eXBlb2YobXNDcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIG1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKG1zQ3J5cHRvKSk7XG5pZiAoZ2V0UmFuZG9tVmFsdWVzKSB7XG4gIC8vIFdIQVRXRyBjcnlwdG8gUk5HIC0gaHR0cDovL3dpa2kud2hhdHdnLm9yZy93aWtpL0NyeXB0b1xuICB2YXIgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBnZXRSYW5kb21WYWx1ZXMocm5kczgpO1xuICAgIHJldHVybiBybmRzODtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWF0aFJORygpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbi8vICoqYHYxKClgIC0gR2VuZXJhdGUgdGltZS1iYXNlZCBVVUlEKipcbi8vXG4vLyBJbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vTGlvc0svVVVJRC5qc1xuLy8gYW5kIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS91dWlkLmh0bWxcblxudmFyIF9ub2RlSWQ7XG52YXIgX2Nsb2Nrc2VxO1xuXG4vLyBQcmV2aW91cyB1dWlkIGNyZWF0aW9uIHRpbWVcbnZhciBfbGFzdE1TZWNzID0gMDtcbnZhciBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB2YXIgbm9kZSA9IG9wdGlvbnMubm9kZSB8fCBfbm9kZUlkO1xuICB2YXIgY2xvY2tzZXEgPSBvcHRpb25zLmNsb2Nrc2VxICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb2Nrc2VxIDogX2Nsb2Nrc2VxO1xuXG4gIC8vIG5vZGUgYW5kIGNsb2Nrc2VxIG5lZWQgdG8gYmUgaW5pdGlhbGl6ZWQgdG8gcmFuZG9tIHZhbHVlcyBpZiB0aGV5J3JlIG5vdFxuICAvLyBzcGVjaWZpZWQuICBXZSBkbyB0aGlzIGxhemlseSB0byBtaW5pbWl6ZSBpc3N1ZXMgcmVsYXRlZCB0byBpbnN1ZmZpY2llbnRcbiAgLy8gc3lzdGVtIGVudHJvcHkuICBTZWUgIzE4OVxuICBpZiAobm9kZSA9PSBudWxsIHx8IGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICB2YXIgc2VlZEJ5dGVzID0gcm5nKCk7XG4gICAgaWYgKG5vZGUgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuNSwgY3JlYXRlIGFuZCA0OC1iaXQgbm9kZSBpZCwgKDQ3IHJhbmRvbSBiaXRzICsgbXVsdGljYXN0IGJpdCA9IDEpXG4gICAgICBub2RlID0gX25vZGVJZCA9IFtcbiAgICAgICAgc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgICAgICAgc2VlZEJ5dGVzWzFdLCBzZWVkQnl0ZXNbMl0sIHNlZWRCeXRlc1szXSwgc2VlZEJ5dGVzWzRdLCBzZWVkQnl0ZXNbNV1cbiAgICAgIF07XG4gICAgfVxuICAgIGlmIChjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC4yLjIsIHJhbmRvbWl6ZSAoMTQgYml0KSBjbG9ja3NlcVxuICAgICAgY2xvY2tzZXEgPSBfY2xvY2tzZXEgPSAoc2VlZEJ5dGVzWzZdIDw8IDggfCBzZWVkQnl0ZXNbN10pICYgMHgzZmZmO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVVSUQgdGltZXN0YW1wcyBhcmUgMTAwIG5hbm8tc2Vjb25kIHVuaXRzIHNpbmNlIHRoZSBHcmVnb3JpYW4gZXBvY2gsXG4gIC8vICgxNTgyLTEwLTE1IDAwOjAwKS4gIEpTTnVtYmVycyBhcmVuJ3QgcHJlY2lzZSBlbm91Z2ggZm9yIHRoaXMsIHNvXG4gIC8vIHRpbWUgaXMgaGFuZGxlZCBpbnRlcm5hbGx5IGFzICdtc2VjcycgKGludGVnZXIgbWlsbGlzZWNvbmRzKSBhbmQgJ25zZWNzJ1xuICAvLyAoMTAwLW5hbm9zZWNvbmRzIG9mZnNldCBmcm9tIG1zZWNzKSBzaW5jZSB1bml4IGVwb2NoLCAxOTcwLTAxLTAxIDAwOjAwLlxuICB2YXIgbXNlY3MgPSBvcHRpb25zLm1zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1zZWNzIDogbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIHVzZSBjb3VudCBvZiB1dWlkJ3MgZ2VuZXJhdGVkIGR1cmluZyB0aGUgY3VycmVudCBjbG9ja1xuICAvLyBjeWNsZSB0byBzaW11bGF0ZSBoaWdoZXIgcmVzb2x1dGlvbiBjbG9ja1xuICB2YXIgbnNlY3MgPSBvcHRpb25zLm5zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5zZWNzIDogX2xhc3ROU2VjcyArIDE7XG5cbiAgLy8gVGltZSBzaW5jZSBsYXN0IHV1aWQgY3JlYXRpb24gKGluIG1zZWNzKVxuICB2YXIgZHQgPSAobXNlY3MgLSBfbGFzdE1TZWNzKSArIChuc2VjcyAtIF9sYXN0TlNlY3MpLzEwMDAwO1xuXG4gIC8vIFBlciA0LjIuMS4yLCBCdW1wIGNsb2Nrc2VxIG9uIGNsb2NrIHJlZ3Jlc3Npb25cbiAgaWYgKGR0IDwgMCAmJiBvcHRpb25zLmNsb2Nrc2VxID09PSB1bmRlZmluZWQpIHtcbiAgICBjbG9ja3NlcSA9IGNsb2Nrc2VxICsgMSAmIDB4M2ZmZjtcbiAgfVxuXG4gIC8vIFJlc2V0IG5zZWNzIGlmIGNsb2NrIHJlZ3Jlc3NlcyAobmV3IGNsb2Nrc2VxKSBvciB3ZSd2ZSBtb3ZlZCBvbnRvIGEgbmV3XG4gIC8vIHRpbWUgaW50ZXJ2YWxcbiAgaWYgKChkdCA8IDAgfHwgbXNlY3MgPiBfbGFzdE1TZWNzKSAmJiBvcHRpb25zLm5zZWNzID09PSB1bmRlZmluZWQpIHtcbiAgICBuc2VjcyA9IDA7XG4gIH1cblxuICAvLyBQZXIgNC4yLjEuMiBUaHJvdyBlcnJvciBpZiB0b28gbWFueSB1dWlkcyBhcmUgcmVxdWVzdGVkXG4gIGlmIChuc2VjcyA+PSAxMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXVpZC52MSgpOiBDYW5cXCd0IGNyZWF0ZSBtb3JlIHRoYW4gMTBNIHV1aWRzL3NlYycpO1xuICB9XG5cbiAgX2xhc3RNU2VjcyA9IG1zZWNzO1xuICBfbGFzdE5TZWNzID0gbnNlY3M7XG4gIF9jbG9ja3NlcSA9IGNsb2Nrc2VxO1xuXG4gIC8vIFBlciA0LjEuNCAtIENvbnZlcnQgZnJvbSB1bml4IGVwb2NoIHRvIEdyZWdvcmlhbiBlcG9jaFxuICBtc2VjcyArPSAxMjIxOTI5MjgwMDAwMDtcblxuICAvLyBgdGltZV9sb3dgXG4gIHZhciB0bCA9ICgobXNlY3MgJiAweGZmZmZmZmYpICogMTAwMDAgKyBuc2VjcykgJSAweDEwMDAwMDAwMDtcbiAgYltpKytdID0gdGwgPj4+IDI0ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDE2ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfbWlkYFxuICB2YXIgdG1oID0gKG1zZWNzIC8gMHgxMDAwMDAwMDAgKiAxMDAwMCkgJiAweGZmZmZmZmY7XG4gIGJbaSsrXSA9IHRtaCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRtaCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfaGlnaF9hbmRfdmVyc2lvbmBcbiAgYltpKytdID0gdG1oID4+PiAyNCAmIDB4ZiB8IDB4MTA7IC8vIGluY2x1ZGUgdmVyc2lvblxuICBiW2krK10gPSB0bWggPj4+IDE2ICYgMHhmZjtcblxuICAvLyBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGAgKFBlciA0LjIuMiAtIGluY2x1ZGUgdmFyaWFudClcbiAgYltpKytdID0gY2xvY2tzZXEgPj4+IDggfCAweDgwO1xuXG4gIC8vIGBjbG9ja19zZXFfbG93YFxuICBiW2krK10gPSBjbG9ja3NlcSAmIDB4ZmY7XG5cbiAgLy8gYG5vZGVgXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgNjsgKytuKSB7XG4gICAgYltpICsgbl0gPSBub2RlW25dO1xuICB9XG5cbiAgcmV0dXJuIGJ1ZiA/IGJ1ZiA6IGJ5dGVzVG9VdWlkKGIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHYxO1xuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuZnVuY3Rpb24gdjQob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG5cbiAgaWYgKHR5cGVvZihvcHRpb25zKSA9PSAnc3RyaW5nJykge1xuICAgIGJ1ZiA9IG9wdGlvbnMgPT09ICdiaW5hcnknID8gbmV3IEFycmF5KDE2KSA6IG51bGw7XG4gICAgb3B0aW9ucyA9IG51bGw7XG4gIH1cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgdmFyIHJuZHMgPSBvcHRpb25zLnJhbmRvbSB8fCAob3B0aW9ucy5ybmcgfHwgcm5nKSgpO1xuXG4gIC8vIFBlciA0LjQsIHNldCBiaXRzIGZvciB2ZXJzaW9uIGFuZCBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGBcbiAgcm5kc1s2XSA9IChybmRzWzZdICYgMHgwZikgfCAweDQwO1xuICBybmRzWzhdID0gKHJuZHNbOF0gJiAweDNmKSB8IDB4ODA7XG5cbiAgLy8gQ29weSBieXRlcyB0byBidWZmZXIsIGlmIHByb3ZpZGVkXG4gIGlmIChidWYpIHtcbiAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgMTY7ICsraWkpIHtcbiAgICAgIGJ1ZltpICsgaWldID0gcm5kc1tpaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZiB8fCBieXRlc1RvVXVpZChybmRzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2NDtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi40IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odGhpcyB8fCB7fSkpO1xuIiwiaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1L09wZW5WaWR1JztcblxuaWYgKHdpbmRvdykge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zdHJpbmctbGl0ZXJhbFxuICAgIHdpbmRvd1snT3BlblZpZHUnXSA9IE9wZW5WaWR1O1xufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0Nvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwnIDogJ1JlbW90ZScpLCAnY2FuZGlkYXRlIGZvcicsXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCwgSlNPTi5zdHJpbmdpZnkoY2FuZGlkYXRlKSk7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdvbkljZUNhbmRpZGF0ZScsIHtcbiAgICAgICAgICAgIGVuZHBvaW50TmFtZTogdGhpcy5jb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IGNhbmRpZGF0ZS5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBjYW5kaWRhdGUuc2RwTUxpbmVJbmRleFxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzZW5kaW5nIElDRSBjYW5kaWRhdGU6ICdcbiAgICAgICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdFJlbW90ZVN0cmVhbXMob3B0aW9uczogU3RyZWFtT3B0aW9uc1NlcnZlcltdKTogdm9pZCB7XG5cbiAgICAgICAgLy8gVGhpcyBpcyByZWFkeSBmb3Igc3VwcG9ydGluZyBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uIG9iamVjdC4gUmlnaHQgbm93IHRoZSBsb29wIHdpbGwgYWx3YXlzIHJ1biBqdXN0IG9uY2VcbiAgICAgICAgLy8gdGhpcy5zdHJlYW0gc2hvdWxkIGFsc28gYmUgcmVwbGFjZWQgYnkgYSBjb2xsZWN0aW9uIG9mIHN0cmVhbXMgdG8gc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uXG4gICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgZnJhbWVSYXRlOiBvcHRzLmZyYW1lUmF0ZSxcbiAgICAgICAgICAgICAgICByZWN2QXVkaW86IG9wdHMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgcmVjdlZpZGVvOiBvcHRzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiBvcHRzLnR5cGVPZlZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLnNlc3Npb24sIHN0cmVhbU9wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJSZW1vdGUgJ0Nvbm5lY3Rpb24nIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiAnLCB0aGlzLnN0cmVhbS5pbmJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFkZFN0cmVhbShzdHJlYW06IFN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uY29ubmVjdGlvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVTdHJlYW0oc3RyZWFtSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3RyZWFtKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyU3RhdGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL0xvY2FsUmVjb3JkZXJTdGF0ZSc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuXG4gKlxuICogPiBXQVJOSU5HOiBQZXJmb3JtaW5nIGJyb3dzZXIgbG9jYWwgcmVjb3JkaW5nIG9mICoqcmVtb3RlIHN0cmVhbXMqKiBtYXkgY2F1c2Ugc29tZSB0cm91Ymxlcy4gQSBsb25nIHdhaXRpbmcgdGltZSBtYXkgYmUgcmVxdWlyZWQgYWZ0ZXIgY2FsbGluZyBfTG9jYWxSZWNvcmRlci5zdG9wKClfIGluIHRoaXMgY2FzZVxuICovXG5leHBvcnQgY2xhc3MgTG9jYWxSZWNvcmRlciB7XG5cbiAgICBzdGF0ZTogTG9jYWxSZWNvcmRlclN0YXRlO1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uSWQ6IHN0cmluZztcbiAgICBwcml2YXRlIG1lZGlhUmVjb3JkZXI6IGFueTtcbiAgICBwcml2YXRlIGNodW5rczogYW55W10gPSBbXTtcbiAgICBwcml2YXRlIGJsb2I6IEJsb2I7XG4gICAgcHJpdmF0ZSBjb3VudCA9IDA7XG4gICAgcHJpdmF0ZSBpZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3U3JjOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBodG1sUGFyZW50RWxlbWVudElkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXc6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzdHJlYW06IFN0cmVhbSkge1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9ICghIXRoaXMuc3RyZWFtLmNvbm5lY3Rpb24pID8gdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgOiAnZGVmYXVsdC1jb25uZWN0aW9uJztcbiAgICAgICAgdGhpcy5pZCA9IHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnX2xvY2FscmVjb3JkJztcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFN0YXJ0cyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUFEWWAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RhcnRlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVjb3JkKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRyeSB7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZWNvcmQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUFEWVxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLmNsZWFuKClcXCcgb3IgaW5pdCBhIG5ldyBMb2NhbFJlY29yZGVyIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJTdGFydGluZyBsb2NhbCByZWNvcmRpbmcgb2Ygc3RyZWFtICdcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgXCInIG9mIGNvbm5lY3Rpb24gJ1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyBcIidcIik7XG5cblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9wdGlvbnM7XG4gICAgICAgICAgICAgICAgICAgIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA5JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA5JyB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA4JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA4JyB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdVc2luZyBtaW1lVHlwZSAnICsgb3B0aW9ucy5taW1lVHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCksIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignaXNUeXBlU3VwcG9ydGVkIGlzIG5vdCBzdXBwb3J0ZWQsIHVzaW5nIGRlZmF1bHQgY29kZWNzIGZvciBicm93c2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdGFydCgxMCk7XG5cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25kYXRhYXZhaWxhYmxlID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUuZGF0YSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25lcnJvciA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBlcnJvcjogJywgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdGFydCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdGFydGVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25wYXVzZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBwYXVzZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucmVzdW1lID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHJlc3VtZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ud2FybmluZyA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgd2FybmluZzogJyArIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBFbmRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2Agb3IgYFBBVVNFRGAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYEZJTklTSEVEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdG9wcGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBzdG9wKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyBvciBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdG9wKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFBhdXNlcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBQQVVTRURgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSBwYXVzZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHBhdXNlKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQucGF1c2UoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIG9yIFxcJ0xvY2FsUmVjb3JkZXIucmVzdW1lKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucGF1c2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzdW1lcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSByZXN1bWVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZXN1bWUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZXN1bWUoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5wYXVzZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnJlc3VtZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByZXZpZXdzIHRoZSByZWNvcmRpbmcsIGFwcGVuZGluZyBhIG5ldyBIVE1MVmlkZW9FbGVtZW50IHRvIGVsZW1lbnQgd2l0aCBpZCBgcGFyZW50SWRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgcHJldmlldyhwYXJlbnRFbGVtZW50KTogSFRNTFZpZGVvRWxlbWVudCB7XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5wcmV2aWV3KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmlkID0gdGhpcy5pZDtcbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuYXV0b3BsYXkgPSB0cnVlO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcGFyZW50RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhcmVudEVsZW1lbnREb20gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRFbGVtZW50KTtcbiAgICAgICAgICAgIGlmIChwYXJlbnRFbGVtZW50RG9tKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50RG9tLmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQuaWQ7XG4gICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuc3JjID0gdGhpcy52aWRlb1ByZXZpZXdTcmM7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9QcmV2aWV3O1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogR3JhY2VmdWxseSBzdG9wcyBhbmQgY2xlYW5zIHRoZSBjdXJyZW50IHJlY29yZGluZyAoV0FSTklORzogaXQgaXMgY29tcGxldGVseSBkaXNtaXNzZWQpLiBTZXRzIFtbc3RhdGVdXSB0byBgUkVBRFlgIHNvIHRoZSByZWNvcmRpbmcgY2FuIHN0YXJ0IGFnYWluXG4gICAgICovXG4gICAgY2xlYW4oKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGYgPSAoKSA9PiB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5ibG9iO1xuICAgICAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubWVkaWFSZWNvcmRlcjtcbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcCgpLnRoZW4oKCkgPT4gZigpKS5jYXRjaCgoKSA9PiBmKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBEb3dubG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIHRocm91Z2ggdGhlIGJyb3dzZXIuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBkb3dubG9hZCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5kb3dubG9hZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGE6IEhUTUxBbmNob3JFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICAgICAgYS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgICAgIGEuZG93bmxvYWQgPSB0aGlzLmlkICsgJy53ZWJtJztcbiAgICAgICAgICAgIGEuY2xpY2soKTtcbiAgICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSByYXcgQmxvYiBmaWxlLiBNZXRob2RzIHByZXZpZXcsIGRvd25sb2FkLCB1cGxvYWRBc0JpbmFyeSBhbmQgdXBsb2FkQXNNdWx0aXBhcnRmaWxlIHVzZSB0aGlzIHNhbWUgZmlsZSB0byBwZXJmb3JtIHRoZWlyIHNwZWNpZmljIGFjdGlvbnMuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBnZXRCbG9iKCk6IEJsb2Ige1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ0NhbGwgXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIGJlZm9yZSBnZXR0aW5nIEJsb2IgZmlsZScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJsb2I7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgYmluYXJ5IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3RcbiAgICAgKi9cbiAgICB1cGxvYWRBc0JpbmFyeShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzQmluYXJ5KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGh0dHAuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHRoaXMuYmxvYik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBsb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gYXMgYSBtdWx0aXBhcnQgZmlsZSBwZXJmb3JtaW5nIGFuIEhUVFAvUE9TVCBvcGVyYXRpb24gdG8gVVJMIGBlbmRwb2ludGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGAuIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBjYW4gYmUgcGFzc2VkIGFzIHNlY29uZCBwYXJhbWV0ZXIuIEZvciBleGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHZhciBoZWFkZXJzID0ge1xuICAgICAqICBcIkNvb2tpZVwiOiBcIiRWZXJzaW9uPTE7IFNraW49bmV3O1wiLFxuICAgICAqICBcIkF1dGhvcml6YXRpb25cIjpcIkJhc2ljIFFXeGhaR3BianB1SUhObGN0WlE9PVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB3aXRoIHRoZSBgaHR0cC5yZXNwb25zZVRleHRgIGZyb20gc2VydmVyIGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggdGhlIGZhaWxlZCBgaHR0cC5zdGF0dXNgIGlmIG5vdDpcbiAgICAgKi9cbiAgICB1cGxvYWRBc011bHRpcGFydGZpbGUoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc011bHRpcGFydGZpbGUoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3Qgc2VuZGFibGUgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgICAgICAgICBzZW5kYWJsZS5hcHBlbmQoJ2ZpbGUnLCB0aGlzLmJsb2IsIHRoaXMuaWQgKyAnLndlYm0nKTtcblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGh0dHAuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBodHRwLnNlbmQoc2VuZGFibGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBvblN0b3BEZWZhdWx0KCk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdG9wcGVkICAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG5cbiAgICAgICAgdGhpcy5ibG9iID0gbmV3IEJsb2IodGhpcy5jaHVua3MsIHsgdHlwZTogJ3ZpZGVvL3dlYm0nIH0pO1xuICAgICAgICB0aGlzLmNodW5rcyA9IFtdO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3U3JjID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEO1xuICAgIH1cblxufVxuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyIH0gZnJvbSAnLi9Mb2NhbFJlY29yZGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4vUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBScGNCdWlsZGVyIGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYyc7XG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbi8qKlxuICogRW50cnlwb2ludCBvZiBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKiBVc2UgaXQgdG8gaW5pdGlhbGl6ZSBvYmplY3RzIG9mIHR5cGUgW1tTZXNzaW9uXV0sIFtbUHVibGlzaGVyXV0gYW5kIFtbTG9jYWxSZWNvcmRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgcHJpdmF0ZSBqc29uUnBjQ2xpZW50OiBhbnk7XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlc3Npb246IFNlc3Npb247XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICB3c1VyaTogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VjcmV0ID0gJyc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByZWNvcmRlciA9IGZhbHNlO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgYWR2YW5jZWRDb25maWd1cmF0aW9uOiBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGNvbnNvbGUuaW5mbyhcIidPcGVuVmlkdScgaW5pdGlhbGl6ZWRcIik7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIG5ldyBzZXNzaW9uXG4gICAqL1xuICBpbml0U2Vzc2lvbigpOiBTZXNzaW9uIHtcbiAgICB0aGlzLnNlc3Npb24gPSBuZXcgU2Vzc2lvbih0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uO1xuICB9XG5cblxuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgcHVibGlzaGVyXG4gICAqXG4gICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0RpYWxvZ09wZW5lZGAgZXZlbnQsIG9ubHkgaWYgdGhlIHBvcC11cCBzaG93biBieSB0aGUgYnJvd3NlciB0byByZXF1ZXN0IHBlcm1pc3Npb25zIGZvciB0aGUgY2FtZXJhIGlzIG9wZW5lZC4gWW91IGNhbiB1c2UgdGhpcyBldmVudCB0byBhbGVydCB0aGUgdXNlciBhYm91dCBncmFudGluZyBwZXJtaXNzaW9uc1xuICAgKiBmb3IgeW91ciB3ZWJzaXRlLiBBbiBgYWNjZXNzRGlhbG9nQ2xvc2VkYCBldmVudCB3aWxsIGFsc28gYmUgZGlzcGF0Y2hlZCBhZnRlciB1c2VyIGNsaWNrcyBvbiBcIkFsbG93XCIgb3IgXCJCbG9ja1wiIGluIHRoZSBwb3AtdXAuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NBbGxvd2VkYCBvciBgYWNjZXNzRGVuaWVkYCBldmVudCBvbmNlIGl0IGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3QuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgYSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIGxvY2FsIHN0cmVhbXMgc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50ICBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgUHVibGlzaGVyLlxuICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1B1Ymxpc2hlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1B1Ymxpc2hlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgaW5pdFB1Ymxpc2hlcmAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgYGNvbXBsZXRpb25IYW5kbGVyYCBmdW5jdGlvbiBpcyBjYWxsZWQgYmVmb3JlIHRoZSBQdWJsaXNoZXIgZGlzcGF0Y2hlcyBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYW4gYGFjY2Vzc0RlbmllZGAgZXZlbnRcbiAgICovXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMj8sIHBhcmFtMz8pOiBQdWJsaXNoZXIge1xuXG4gICAgbGV0IHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXM7XG5cbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgIT09ICdmdW5jdGlvbicpKSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9ICg8UHVibGlzaGVyUHJvcGVydGllcz5wYXJhbTIpO1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBhdWRpb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlIDogdW5kZWZpbmVkLFxuICAgICAgICBmcmFtZVJhdGU6IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5mcmFtZVJhdGUgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuZnJhbWVSYXRlIDogdW5kZWZpbmVkKSxcbiAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3Byb3BlcnRpZXMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiAodHlwZW9mIHByb3BlcnRpZXMubWlycm9yICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLm1pcnJvciA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaFZpZGVvIDogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogdGhpcy5pc01lZGlhU3RyZWFtVHJhY2socHJvcGVydGllcy52aWRlb1NvdXJjZSkgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLnJlc29sdXRpb24gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucmVzb2x1dGlvbiA6ICc2NDB4NDgwJyksXG4gICAgICAgIHZpZGVvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgOiB1bmRlZmluZWRcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50KScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiAnNjQweDQ4MCdcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgcHVibGlzaGVyOiBQdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIHRoaXMpO1xuXG4gICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0yO1xuICAgIH0gZWxzZSBpZiAoISFwYXJhbTMpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgIH1cblxuICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgfSk7XG5cbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lICE9PSAnRmlyZWZveCcpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVELCAnWW91IGNhbiBvbmx5IHNjcmVlbiBzaGFyZSBpbiBkZXNrdG9wIENocm9tZSBhbmQgRmlyZWZveC4gRGV0ZWN0ZWQgYnJvd3NlcjogJyArIHBsYXRmb3JtLm5hbWUpO1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24pIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbi5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbklkLCAoc3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWVuYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0U2NyZWVuQ29uc3RyYWludHMoKGVycm9yLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yICYmIGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICg8c3RyaW5nPnRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uKSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9zY3JlZW4tY2FwdHVyaW5nL2FqaGlmZGRpbWthcGdjaWZnY29kbW1mZGxrbmFoZmZrJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQsICdZb3UgbXVzdCBhbGxvdyBhY2Nlc3MgdG8gb25lIHdpbmRvdyBvZiB5b3VyIGRlc2t0b3AnKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHMudmlkZW87XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID0gJ3NjcmVlbic7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLXN0cmluZy1saXRlcmFsXG4gICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvWydkZXZpY2VJZCddID0geyBleGFjdDogcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSB9O1xuICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzdGFydFdzKG9uQ29ubmVjdFN1Y2NlczogKGVycm9yOiBFcnJvcikgPT4gdm9pZCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIGhlYXJ0YmVhdDogNTAwMCxcbiAgICAgIHNlbmRDbG9zZU1lc3NhZ2U6IGZhbHNlLFxuICAgICAgd3M6IHtcbiAgICAgICAgdXJpOiB0aGlzLndzVXJpLFxuICAgICAgICB1c2VTb2NrSlM6IGZhbHNlLFxuICAgICAgICBvbmNvbm5lY3RlZDogb25Db25uZWN0U3VjY2VzLFxuICAgICAgICBvbmRpc2Nvbm5lY3Q6IHRoaXMuZGlzY29ubmVjdENhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0aW5nOiB0aGlzLnJlY29ubmVjdGluZ0NhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0ZWQ6IHRoaXMucmVjb25uZWN0ZWRDYWxsYmFjay5iaW5kKHRoaXMpXG4gICAgICB9LFxuICAgICAgcnBjOiB7XG4gICAgICAgIHJlcXVlc3RUaW1lb3V0OiAxNTAwMCxcbiAgICAgICAgcGFydGljaXBhbnRKb2luZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50Sm9pbmVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRQdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50UHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRVbnB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50TGVmdDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRMZWZ0LmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRFdmljdGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEV2aWN0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdGFydGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdGFydGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RvcHBlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RvcHBlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHNlbmRNZXNzYWdlOiB0aGlzLnNlc3Npb24ub25OZXdNZXNzYWdlLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgaWNlQ2FuZGlkYXRlOiB0aGlzLnNlc3Npb24ucmVjdkljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIG1lZGlhRXJyb3I6IHRoaXMuc2Vzc2lvbi5vbk1lZGlhRXJyb3IuYmluZCh0aGlzLnNlc3Npb24pXG4gICAgICB9XG4gICAgfTtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQgPSBuZXcgUnBjQnVpbGRlci5jbGllbnRzLkpzb25ScGNDbGllbnQoY29uZmlnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBjbG9zZVdzKCk6IHZvaWQge1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5jbG9zZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlbmRSZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCBwYXJhbXM6IGFueSwgY2FsbGJhY2s/KTogdm9pZCB7XG4gICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgY2FsbGJhY2sgPSBwYXJhbXM7XG4gICAgICBwYXJhbXMgPSB7fTtcbiAgICB9XG4gICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyByZXF1ZXN0OiB7bWV0aG9kOlwiJyArIG1ldGhvZCArICdcIiwgcGFyYW1zOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSArICd9Jyk7XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50LnNlbmQobWV0aG9kLCBwYXJhbXMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpc01lZGlhU3RyZWFtVHJhY2sobWVkaWFTb3VyY2U6IGFueSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGlzID0gKCEhbWVkaWFTb3VyY2UgJiZcbiAgICAgIG1lZGlhU291cmNlLmVuYWJsZWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuZW5hYmxlZCA9PT0gJ2Jvb2xlYW4nICYmXG4gICAgICBtZWRpYVNvdXJjZS5pZCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5pZCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLmtpbmQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2Uua2luZCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLmxhYmVsICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmxhYmVsID09PSAnc3RyaW5nJyAmJlxuICAgICAgbWVkaWFTb3VyY2UubXV0ZWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UubXV0ZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5yZWFkeVN0YXRlID09PSAnc3RyaW5nJyk7XG4gICAgcmV0dXJuIGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFdzVXJpKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMud3NVcmk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2V0U2VjcmV0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc2VjcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFJlY29yZGVyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnJlY29yZGVyO1xuICB9XG5cblxuICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICBwcml2YXRlIGRpc2Nvbm5lY3RDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGluZ0NhbGxiYWNrKCk6IHZvaWQge1xuICAgIGNvbnNvbGUud2FybignV2Vic29ja2V0IGNvbm5lY3Rpb24gbG9zdCAocmVjb25uZWN0aW5nKScpO1xuICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICB0aGlzLnNlc3Npb24ub25Mb3N0Q29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVjb25uZWN0ZWRDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCByZWNvbm5lY3RlZCcpO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1Jvb21BdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuc2Vzc2lvbiAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc2Vzc2lvbiBpbnN0YW5jZW9mIFNlc3Npb24pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gaW5zdGFuY2Ugbm90IGZvdW5kJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgRXZlbnREaXNwYXRjaGVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9FdmVudERpc3BhdGNoZXInO1xuaW1wb3J0IHsgUHVibGlzaGVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvUHVibGlzaGVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbUV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBwcml2YXRlIG9wZW52aWR1OiBPcGVuVmlkdSkge1xuICAgICAgICBzdXBlcihuZXcgU3RyZWFtKCghIW9wZW52aWR1LnNlc3Npb24pID8gb3BlbnZpZHUuc2Vzc2lvbiA6IG5ldyBTZXNzaW9uKG9wZW52aWR1KSwgeyBwdWJsaXNoZXJQcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLCBtZWRpYUNvbnN0cmFpbnRzOiB7fSB9KSwgdGFyZ0VsKTtcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZC1ieS1kaXNjb25uZWN0JywgKHJlYXNvbjogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgdGhpcy5zdHJlYW0sIHJlYXNvbik7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIGF1ZGlvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoQXVkaW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmF1ZGlvRW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBoYXMgXCIgKyAodmFsdWUgPyAncHVibGlzaGVkJyA6ICd1bnB1Ymxpc2hlZCcpICsgJyBpdHMgYXVkaW8gc3RyZWFtJyk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaFZpZGVvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS52aWRlb0VuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogQ2FsbCB0aGlzIG1ldGhvZCBiZWZvcmUgW1tTZXNzaW9uLnB1Ymxpc2hdXSB0byBzdWJzY3JpYmUgdG8geW91ciBQdWJsaXNoZXIncyByZW1vdGUgc3RyZWFtIGluc3RlYWQgb2YgdXNpbmcgdGhlIGxvY2FsIHN0cmVhbSwgYXMgYW55IG90aGVyIHVzZXIgd291bGQgZG8uXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9SZW1vdGUodmFsdWU/OiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHZhbHVlID0gKHZhbHVlICE9PSB1bmRlZmluZWQpID8gdmFsdWUgOiB0cnVlO1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlZFRvUmVtb3RlID0gdmFsdWU7XG4gICAgICAgIHRoaXMuc3RyZWFtLnN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWUpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICBzdXBlci5vbih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1DcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLm9uKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBlcnJvckNhbGxiYWNrID0gKG9wZW5WaWR1RXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc0NhbGxiYWNrID0gKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmlzTWVkaWFTdHJlYW1UcmFjayh0aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjaygoPE1lZGlhU3RyZWFtVHJhY2s+dGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBBcHBseSBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyBhbmQgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW9cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZW5hYmxlZCA9ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuXG4gICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5maXJzdFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZVZpZGVvRWxlbWVudCh0aGlzLmZpcnN0VmlkZW9FbGVtZW50LnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+dGhpcy5wcm9wZXJ0aWVzLmluc2VydE1vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbjogU2Vzc2lvbik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lZS5nZXRMaXN0ZW5lcnMoJ3N0cmVhbVBsYXlpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ09wZW5lZCcsIFtdKTtcbiAgICAgICAgfSwgd2FpdFRpbWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lOiBudW1iZXIsIHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQpO1xuICAgICAgICBpZiAoKERhdGUubm93KCkgLSBzdGFydFRpbWUpID4gd2FpdFRpbWUpIHtcbiAgICAgICAgICAgIC8vIFBlcm1pc3Npb24gZGlhbG9nIHdhcyBzaG93biBhbmQgbm93IGlzIGNsb3NlZFxuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ0Nsb3NlZCcsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgT2JqTWFwIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT2JqTWFwJztcbmltcG9ydCB7IFNlc3Npb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU2Vzc2lvbk9wdGlvbnMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbkV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvbkV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFJlY29yZGluZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFNpZ25hbEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSB2aWRlbyBjYWxsLiBJdCBjYW4gYWxzbyBiZSBzZWVuIGFzIGEgdmlkZW9jb25mZXJlbmNlIHJvb20gd2hlcmUgbXVsdGlwbGUgdXNlcnMgY2FuIGNvbm5lY3QuXG4gKiBQYXJ0aWNpcGFudHMgd2hvIHB1Ymxpc2ggdGhlaXIgdmlkZW9zIHRvIGEgc2Vzc2lvbiBjYW4gYmUgc2VlbiBieSB0aGUgcmVzdCBvZiB1c2VycyBjb25uZWN0ZWQgdG8gdGhhdCBzcGVjaWZpYyBzZXNzaW9uLlxuICogSW5pdGlhbGl6ZWQgd2l0aCBbW09wZW5WaWR1LmluaXRTZXNzaW9uXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXNzaW9uIGltcGxlbWVudHMgRXZlbnREaXNwYXRjaGVyIHtcblxuICAgIC8qKlxuICAgICAqIExvY2FsIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24uIFRoaXMgb2JqZWN0IGlzIGRlZmluZWQgb25seSBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBleGVjdXRlZCwgYW5kIGNhbiBiZSByZXRyaWV2ZWQgc3Vic2NyaWJpbmcgdG8gYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgU2Vzc2lvblxuICAgICAqL1xuICAgIHNlc3Npb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ29sbGVjdGlvbiBvZiBhbGwgU3RyZWFtTWFuYWdlcnMgb2YgdGhpcyBTZXNzaW9uIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSlcbiAgICAgKi9cbiAgICBzdHJlYW1NYW5hZ2VyczogU3RyZWFtTWFuYWdlcltdID0gW107XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBPYmpNYXA8Ym9vbGVhbj4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVDb25uZWN0aW9uczogT2JqTWFwPENvbm5lY3Rpb24+ID0ge307XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PjtcbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnkpOiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0cyB0byB0aGUgc2Vzc2lvbiB1c2luZyBgdG9rZW5gLiBQYXJhbWV0ZXIgYG1ldGFkYXRhYCBhbGxvd3MgeW91IHRvIHBhc3MgZXh0cmEgZGF0YSB0byBzaGFyZSB3aXRoIG90aGVyIHVzZXJzIHdoZW5cbiAgICAgKiB0aGV5IHJlY2VpdmUgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LiBUaGUgc3RydWN0dXJlIG9mIGBtZXRhZGF0YWAgc3RyaW5nIGlzIHVwIHRvIHlvdSAobWF5YmUgc29tZSBzdGFuZGFyaXplZCBmb3JtYXRcbiAgICAgKiBhcyBKU09OIG9yIFhNTCBpcyBhIGdvb2QgaWRlYSksIHRoZSBvbmx5IHJlc3RyaWN0aW9uIGlzIGEgbWF4aW11bSBsZW5ndGggb2YgMTAwMDAgY2hhcnMuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGFkYXRhIGlzIG5vdCBjb25zaWRlcmVkIHNlY3VyZSwgYXMgaXQgaXMgZ2VuZXJhdGVkIGluIHRoZSBjbGllbnQgc2lkZS4gVG8gcGFzcyBzZWN1cml6ZWQgZGF0YSwgYWRkIGl0IGFzIGEgcGFyYW1ldGVyIGluIHRoZVxuICAgICAqIHRva2VuIGdlbmVyYXRpb24gb3BlcmF0aW9uICh0aHJvdWdoIHRoZSBBUEkgUkVTVCwgb3BlbnZpZHUtamF2YS1jbGllbnQgb3Igb3BlbnZpZHUtbm9kZS1jbGllbnQpLlxuICAgICAqXG4gICAgICogT25seSBhZnRlciB0aGUgcmV0dXJuZWQgUHJvbWlzZSBpcyBzdWNjZXNzZnVsbHkgcmVzb2x2ZWQgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBvYmplY3Qgd2lsbCBiZSBhdmFpbGFibGUgYW5kIHByb3Blcmx5IGRlZmluZWQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGZpcnN0IGRpc3BhdGNoIG9uZSBvciBtb3JlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzIHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZDpcbiAgICAgKiAtIEZpcnN0IG9uZSBmb3IgeW91ciBvd24gbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QsIHNvIHlvdSBjYW4gcmV0cmlldmUgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBwcm9wZXJ0eS5cbiAgICAgKiAtIFRoZW4gb25lIGZvciBlYWNoIHJlbW90ZSBDb25uZWN0aW9uIHByZXZpb3VzbHkgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uLCBpZiBhbnkuIEFueSBvdGhlciByZW1vdGUgdXNlciBjb25uZWN0aW5nIHRvIHRoZSBTZXNzaW9uIGFmdGVyIHlvdSBoYXZlXG4gICAgICogc3VjY2Vzc2Z1bGx5IGNvbm5lY3RlZCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50IHdoZW4gdGhleSBkbyBzby5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBmb3IgZWFjaCByZW1vdGUgYWN0aXZlIFtbUHVibGlzaGVyXV0gdGhhdCB3YXMgYWxyZWFkeSBzdHJlYW1pbmdcbiAgICAgKiB3aGVuIGNvbm5lY3RpbmcsIGp1c3QgYWZ0ZXIgZGlzcGF0Y2hpbmcgYWxsIHJlbW90ZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gYW5kIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIHRvIHdoaWNoIHlvdSBtdXN0IHN1YnNjcmliZSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSB0aGUgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICpcbiAgICAgKi9cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIW1ldGFkYXRhID8gdGhpcy5zdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YSkgOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0QXV4KHRva2VuKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIHBsYXRmb3JtLm5hbWUgKyAnICcgKyBwbGF0Zm9ybS52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCB0byBhdm9pZCB0aGlzIGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgYWxsIHRoZSBTdWJzY3JpYmVyIG9iamVjdHMgeW91cnNlbGYuXG4gICAgICogU2VlIFtbU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGVyZSBpcyBhIFtbUHVibGlzaGVyXV0gb2JqZWN0IHB1Ymxpc2hpbmcgdG8gdGhlIHNlc3Npb24uXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgc3RvcCBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIGlmIHlvdSB3YW50IHRvIGNsZWFuIHRoZSBQdWJsaXNoZXIgb2JqZWN0IG9uIHlvdXIgb3duIG9yIHJlLXB1Ymxpc2ggaXQgaW4gYSBkaWZmZXJlbnQgU2Vzc2lvbiAodG8gZG8gc28gaXQgaXMgYSBtYW5kYXRvcnkgcmVxdWlyZW1lbnQgdG8gY2FsbCBgU2Vzc2lvbi51bnB1Ymxpc2goKWBcbiAgICAgKiBvci9hbmQgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBpbiB0aGUgcHJldmlvdXMgc2Vzc2lvbikuIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBkaXNjb25uZWN0ZWQgcGFydGljaXBhbnQgd2FzIHB1Ymxpc2hpbmcuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBpbiBhbnkgY2FzZS4gU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKi9cbiAgICBkaXNjb25uZWN0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxlYXZlKGZhbHNlLCAnZGlzY29ubmVjdCcpO1xuICAgIH1cblxuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZXMgdG8gYSBgc3RyZWFtYCwgYWRkaW5nIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCB0byBET00gd2l0aCBgc3Vic2NyaWJlclByb3BlcnRpZXNgIHNldHRpbmdzLiBUaGlzIG1ldGhvZCBpcyB1c3VhbGx5IGNhbGxlZCBpbiB0aGUgY2FsbGJhY2sgb2YgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIHJlbW90ZSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc3RyZWFtIFN0cmVhbSBvYmplY3QgdG8gc3Vic2NyaWJlIHRvXG4gICAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tTdWJzY3JpYmVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgU3Vic2NyaWJlci5cbiAgICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1N1YnNjcmliZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24pXG4gICAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYHN1YnNjcmliZWAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgICAqL1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMz86ICgoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSB8IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBwYXJhbTQ/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkpOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgbGV0IHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzID0ge307XG4gICAgICAgIGlmICghIXBhcmFtMyAmJiB0eXBlb2YgcGFyYW0zICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcGFyYW0zLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlID09PSAnc3RyaW5nJykgPyBWaWRlb0luc2VydE1vZGVbcGFyYW0zLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogKHR5cGVvZiBwYXJhbTMuc3Vic2NyaWJlVG9BdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gOiB0cnVlLFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvVmlkZW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvIDogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb0F1ZGlvOiB0cnVlLFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvVmlkZW86IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gICAgICAgIGlmICghIXBhcmFtMyAmJiAodHlwZW9mIHBhcmFtMyA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgICAgICB9IGVsc2UgaWYgKCEhcGFyYW00KSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtNDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJpbmcgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgc3RyZWFtLnN1YnNjcmliZSgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdTdWJzY3JpYmVkIGNvcnJlY3RseSB0byAnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgc3Vic2NyaWJlciA9IG5ldyBTdWJzY3JpYmVyKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyk7XG4gICAgICAgIGlmICghIXN1YnNjcmliZXIudGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgc3RyZWFtLnN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KHN1YnNjcmliZXIudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT5wcm9wZXJ0aWVzLmluc2VydE1vZGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdWJzY3JpYmVyO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW1Nlc3Npb24uc3Vic2NyaWJlXV1cbiAgICAgKi9cbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFN1YnNjcmliZXI+O1xuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBQcm9taXNlPFN1YnNjcmliZXI+O1xuXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzPzogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBQcm9taXNlPFN1YnNjcmliZXI+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPFN1YnNjcmliZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgbGV0IHN1YnNjcmliZXI6IFN1YnNjcmliZXI7XG5cbiAgICAgICAgICAgIGNvbnN0IGNhbGxiYWNrID0gKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShzdWJzY3JpYmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAoISFwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyID0gdGhpcy5zdWJzY3JpYmUoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVbnN1YnNjcmliZXMgZnJvbSBgc3Vic2NyaWJlcmAsIGF1dG9tYXRpY2FsbHkgcmVtb3ZpbmcgaXRzIGFzc29jaWF0ZWQgSFRNTCB2aWRlbyBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50IGZvciBlYWNoIHZpZGVvIGFzc29jaWF0ZWQgdG8gaXQgdGhhdCB3YXMgcmVtb3ZlZCBmcm9tIERPTS5cbiAgICAgKiBPbmx5IHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IHJlbW92ZWRcbiAgICAgKlxuICAgICAqIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZVxuICAgICAqL1xuICAgIHVuc3Vic2NyaWJlKHN1YnNjcmliZXI6IFN1YnNjcmliZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbklkID0gc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQ7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliaW5nIGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICd1bnN1YnNjcmliZUZyb21WaWRlbycsXG4gICAgICAgICAgICB7IHNlbmRlcjogc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgfSxcbiAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgdW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1Vuc3Vic2NyaWJlZCBjb3JyZWN0bHkgZnJvbSAnICsgY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2hlcyB0byB0aGUgU2Vzc2lvbiB0aGUgUHVibGlzaGVyIG9iamVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgdXBvbiBzdWNjZXNzZnVsIHRlcm1pbmF0aW9uIG9mIHRoaXMgbWV0aG9kLiBTZWUgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgbG9jYWwgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBvbmNlIHRoZSBtZWRpYSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHNvIHRoZXkgY2FuIHN1YnNjcmliZSB0byBpdC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHB1Ymxpc2hlciB3YXMgc3VjY2Vzc2Z1bGx5IHB1Ymxpc2hlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcik6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBwdWJsaXNoZXIuc2Vzc2lvbiA9IHRoaXM7XG4gICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnNlc3Npb24gPSB0aGlzO1xuXG4gICAgICAgICAgICBpZiAoIXB1Ymxpc2hlci5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgTk9UIGJlZW4gY2FsbGVkXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZFN0cmVhbShwdWJsaXNoZXIuc3RyZWFtKTtcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gJ1Nlc3Npb24udW5wdWJsaXNoKFB1Ymxpc2hlciknIGhhcyBiZWVuIGNhbGxlZC4gTXVzdCBpbml0aWFsaXplIGFnYWluIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZFN0cmVhbShwdWJsaXNoZXIuc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5yZWVzdGFibGlzaFN0cmVhbVBsYXlpbmdFdmVudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5wdWJsaXNoZXMgZnJvbSB0aGUgU2Vzc2lvbiB0aGUgUHVibGlzaGVyIG9iamVjdC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGlzIFB1Ymxpc2hlclxuICAgICAqIChvbmx5IHRob3NlIHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3VyIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyB0aGUgU3Vic2NyaWJlciBvYmplY3Qgb24geW91ciBvd24uXG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKi9cbiAgICB1bnB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzdHJlYW0gPSBwdWJsaXNoZXIuc3RyZWFtO1xuXG4gICAgICAgIGlmICghc3RyZWFtLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG51bGwnLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHN0cmVhbS5jb25uZWN0aW9uICE9PSB0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG5vdCB5b3VyIGxvY2FsIENvbm5lY3Rpb24uJyArXG4gICAgICAgICAgICAgICAgXCJPbmx5IG1vZGVyYXRvcnMgY2FuIGZvcmNlIHVucHVibGlzaCBvbiByZW1vdGUgU3RyZWFtcyB2aWEgJ2ZvcmNlVW5wdWJsaXNoJyBtZXRob2RcIiwgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnB1Ymxpc2hpbmcgbG9jYWwgbWVkaWEgKCcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgKyAnKScpO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCd1bnB1Ymxpc2hWaWRlbycsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdNZWRpYSB1bnB1Ymxpc2hlZCBjb3JyZWN0bHknKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBkZWxldGUgc3RyZWFtLmNvbm5lY3Rpb24uc3RyZWFtO1xuXG4gICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCBwdWJsaXNoZXIsICdzdHJlYW1EZXN0cm95ZWQnLCBwdWJsaXNoZXIuc3RyZWFtLCAndW5wdWJsaXNoJyk7XG4gICAgICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlbmRzIG9uZSBzaWduYWwuIGBzaWduYWxgIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBvcHRpb25hbCBwcm9wZXJ0aWVzOlxuICAgICAqIGBgYGpzb25cbiAgICAgKiB7ZGF0YTpzdHJpbmcsIHRvOkNvbm5lY3Rpb25bXSwgdHlwZTpzdHJpbmd9XG4gICAgICogYGBgXG4gICAgICogQWxsIHVzZXJzIHN1YnNjcmliZWQgdG8gdGhhdCBzaWduYWwgKGBzZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIC4uLilgIG9yIGBzZXNzaW9uLm9uKCdzaWduYWwnLCAuLi4pYCBmb3IgYWxsIHNpZ25hbHMpIGFuZCB3aG9zZSBDb25uZWN0aW9uIG9iamVjdHMgYXJlIGluIGB0b2AgYXJyYXkgd2lsbCByZWNlaXZlIGl0LiBUaGVpciBsb2NhbFxuICAgICAqIFNlc3Npb24gb2JqZWN0cyB3aWxsIGRpc3BhdGNoIGEgYHNpZ25hbGAgb3IgYHNpZ25hbDp0eXBlYCBldmVudC4gU2VlIFtbU2lnbmFsRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSBtZXNzYWdlIHN1Y2Nlc3NmdWxseSByZWFjaGVkIG9wZW52aWR1LXNlcnZlciBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90LiBfVGhpcyBkb2Vzbid0XG4gICAgICogbWVhbiB0aGF0IG9wZW52aWR1LXNlcnZlciBjb3VsZCByZXNlbmQgdGhlIG1lc3NhZ2UgdG8gYWxsIHRoZSBsaXN0ZWQgcmVjZWl2ZXJzLl9cbiAgICAgKi9cbiAgICAvKiB0c2xpbnQ6ZGlzYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuICAgIHNpZ25hbChzaWduYWw6IFNpZ25hbE9wdGlvbnMpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBzaWduYWxNZXNzYWdlID0ge307XG5cbiAgICAgICAgICAgIGlmIChzaWduYWwudG8gJiYgc2lnbmFsLnRvLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uSWRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgICAgICAgICAgc2lnbmFsLnRvLmZvckVhY2goY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25JZHMucHVzaChjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IGNvbm5lY3Rpb25JZHM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsnZGF0YSddID0gc2lnbmFsLmRhdGEgPyBzaWduYWwuZGF0YSA6ICcnO1xuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndHlwZSddID0gc2lnbmFsLnR5cGUgPyBzaWduYWwudHlwZSA6ICcnO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdzZW5kTWVzc2FnZScsIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBKU09OLnN0cmluZ2lmeShzaWduYWxNZXNzYWdlKVxuICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyogdHNsaW50OmVuYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcblxuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGVuYWJsZSBoYXJrICdzcGVha2luZycgZXZlbnQgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhc3RyLnNwZWVjaEV2ZW50ICYmIHN0ci5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZW5hYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGVuYWJsZSBoYXJrIGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuXG4gICAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnModHlwZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVlLm9mZih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZGlzYWJsYWUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICEhc3RyLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRKb2luZWQocmVzcG9uc2U6IENvbm5lY3Rpb25PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIC8vIENvbm5lY3Rpb24gc2hvdWxkbid0IGV4aXN0XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihyZXNwb25zZS5pZCwgJycpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQ29ubmVjdGlvbiAnICsgcmVzcG9uc2UuaWQgKyAnIGFscmVhZHkgZXhpc3RzIGluIGNvbm5lY3Rpb25zIGxpc3QnKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW3Jlc3BvbnNlLmlkXSA9IGNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRMZWZ0KG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLm5hbWUgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW0uc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBjb25uZWN0aW9uLCBtc2cucmVhc29uKV0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRQdWJsaXNoZWQocmVzcG9uc2U6IENvbm5lY3Rpb25PcHRpb25zKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgYWZ0ZXJDb25uZWN0aW9uRm91bmQgPSAoY29ubmVjdGlvbikgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdKSB7XG4gICAgICAgICAgICAgICAgLy8gQXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiBzdHJlYW0uc3Vic2NyaWJlKCkgaW4gXCJvblBhcnRpY2lwYW50UHVibGlzaGVkXCIgYW5kIGluIFwiam9pblJvb21cIiBycGMgY2FsbGJhY2tcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGNvbmRpdGlvbiBpcyBmYWxzZSBpZiBvcGVudmlkdS1zZXJ2ZXIgc2VuZHMgXCJwYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGV2ZW50IHRvIGEgc3Vic2NyaWJlciBwYXJ0aWNpcGFudCB0aGF0IGhhc1xuICAgICAgICAgICAgICAgIC8vIGFscmVhZHkgc3Vic2NyaWJlZCB0byBjZXJ0YWluIHN0cmVhbSBpbiB0aGUgY2FsbGJhY2sgb2YgXCJqb2luUm9vbVwiIG1ldGhvZFxuXG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIGNvbm5lY3Rpb24uc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEdldCB0aGUgZXhpc3RpbmcgQ29ubmVjdGlvbiBjcmVhdGVkIG9uICdvblBhcnRpY2lwYW50Sm9pbmVkJyBmb3JcbiAgICAgICAgLy8gZXhpc3RpbmcgcGFydGljaXBhbnRzIG9yIGNyZWF0ZSBhIG5ldyBvbmUgZm9yIG5ldyBwYXJ0aWNpcGFudHNcbiAgICAgICAgbGV0IGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG4gICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihyZXNwb25zZS5pZCwgXCJSZW1vdGUgY29ubmVjdGlvbiAnXCIgKyByZXNwb25zZS5pZCArIFwiJyB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb24gPT4ge1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBleGlzdGluZyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IGNvbjtcbiAgICAgICAgICAgICAgICByZXNwb25zZS5tZXRhZGF0YSA9IGNvbi5kYXRhO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ub3B0aW9ucyA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uaW5pdFJlbW90ZVN0cmVhbXMocmVzcG9uc2Uuc3RyZWFtcyk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBuZXcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFVucHVibGlzaGVkKG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgbXNnLm5hbWUgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oc3RyZWFtSWQpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZyk6IHZvaWQge1xuICAgICAgICAvKnRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cubmFtZSwgJ1JlbW90ZSBjb25uZWN0aW9uICcgKyBtc2cubmFtZSArIFwiIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudExlZnQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgc3RyZWFtLCAnZm9yY2VEaXNjb25uZWN0Jyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW0uc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBjb25uZWN0aW9uLCAnZm9yY2VEaXNjb25uZWN0JyldKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pOyovXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTmV3TWVzc2FnZShtc2cpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmZyb20sIFwiQ29ubmVjdGlvbiAnXCIgKyBtc2cuZnJvbSArIFwiJyB1bmtub3cgd2hlbiAnb25OZXdNZXNzYWdlJy4gRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiBcIlxuICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkgKyAnLiBFeGlzdGluZyBsb2NhbCBjb25uZWN0aW9uOiAnICsgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZClcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbCcsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmVuZHBvaW50TmFtZSwgJ0Nvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICcuIEljZSBjYW5kaWRhdGUgd2lsbCBiZSBpZ25vcmVkOiAnICsgY2FuZGlkYXRlKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGFkZGluZyBjYW5kaWRhdGUgZm9yICcgKyBzdHJlYW0uc3RyZWFtSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU2Vzc2lvbkNsb3NlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5pbmZvKCdTZXNzaW9uIGNsb3NlZDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuICAgICAgICBjb25zdCBzID0gbXNnLnJvb207XG4gICAgICAgIGlmIChzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uLWNsb3NlZCcsIFt7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbjogc1xuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIHVuZGVmaW5lZCBvbiBzZXNzaW9uIGNsb3NlZCcsIG1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25Mb3N0Q29ubmVjdGlvbigpOiB2b2lkIHtcblxuICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKHBhcmFtcyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIGNvbnN0IGVyciA9IHBhcmFtcy5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOicsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsZWF2ZShmb3JjZWQ6IGJvb2xlYW4sIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgZm9yY2VkID0gISFmb3JjZWQ7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnTGVhdmluZyBTZXNzaW9uIChmb3JjZWQ9JyArIGZvcmNlZCArICcpJyk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnbGVhdmVSb29tJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgIC8vIERpc3Bvc2UgUHVibGlzaGVyJ3MgIGxvY2FsIHN0cmVhbVxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgUHVibGlzaGVyIG9iamVjdCBkaXNwYXRjaCAnc3RyZWFtRGVzdHJveWVkJyBldmVudCBpZiB0aGUgU3RyZWFtIHdhcyBwdWJsaXNoZWRcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQtYnktZGlzY29ubmVjdCcsIFtyZWFzb25dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBTZXNzaW9uIG9iamVjdCBkaXNwYXRjaCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcgZXZlbnQgKGlmIGl0IGlzIG5vdCBhbHJlYWR5IGRpc3Bvc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMsIHJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICAgICAgICAgIHNlc3Npb25EaXNjb25uZWN0RXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IHdlcmUgbm90IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc3RhcnRXcygoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgam9pblBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiAoISF0b2tlbikgPyB0b2tlbiA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISF0aGlzLm9wdGlvbnMubWV0YWRhdGEgPyB0aGlzLm9wdGlvbnMubWV0YWRhdGEgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVudmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZGVyOiB0aGlzLm9wZW52aWR1LmdldFJlY29yZGVyKCksXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnam9pblJvb20nLCBqb2luUGFyYW1zLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSBsb2NhbCBDb25uZWN0aW9uIG9iamVjdCB3aXRoIHZhbHVlcyByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmRhdGEgPSByZXNwb25zZS5tZXRhZGF0YTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgcmVtb3RlIENvbm5lY3Rpb25zIHdpdGggdmFsdWUgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXZlbnRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uczogbmV3IEFycmF5PENvbm5lY3Rpb24+KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbXM6IG5ldyBBcnJheTxTdHJlYW0+KClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nUGFydGljaXBhbnRzOiBDb25uZWN0aW9uT3B0aW9uc1tdID0gcmVzcG9uc2UudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdQYXJ0aWNpcGFudHMuZm9yRWFjaChwYXJ0aWNpcGFudCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCBwYXJ0aWNpcGFudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLnB1c2goY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5wdXNoKGNvbm5lY3Rpb24uc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3duICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgdGhpcy5jb25uZWN0aW9uLCAnJyldKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGV4aXN0aW5nIGNvbm5lY3Rpb24gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMuZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdzdHJlYW1DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBhY3RpdmUgc3RyZWFtIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMuZm9yRWFjaChzdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGE6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0YWRhdGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPT09IGNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGxvY2FsIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmVtb3RlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZywgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbm5lY3Rpb24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSByZW1vdGUgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgIHJlc29sdmUoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBjb25uZWN0aW9uIG5vdCBmb3VuZC4gUmVqZWN0IHdpdGggT3BlblZpZHVFcnJvclxuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHRva2VuKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSA8c3RyaW5nPnVybC5zZWFyY2hQYXJhbXMuZ2V0KCdzZXNzaW9uSWQnKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0ID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3NlY3JldCcpO1xuICAgICAgICBjb25zdCByZWNvcmRlciA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyZWNvcmRlcicpO1xuXG4gICAgICAgIGlmICghIXNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcmVjb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucmVjb3JkZXIgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS53c1VyaSA9ICd3c3M6Ly8nICsgdXJsLmhvc3QgKyAnL29wZW52aWR1JztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFdlYlJ0Y1N0YXRzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cyc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5pbXBvcnQgKiBhcyBrdXJlbnRvVXRpbHMgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcyc7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBzdHJlYW1cbiAgICAgKi9cbiAgICBzdHJlYW1JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogYFwiQ0FNRVJBXCJgIG9yIGBcIlNDUkVFTlwiYC4gKnVuZGVmaW5lZCogaWYgc3RyZWFtIGlzIGF1ZGlvLW9ubHlcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbU1hbmFnZXIgb2JqZWN0IChbW1B1Ymxpc2hlcl1dIG9yIFtbU3Vic2NyaWJlcl1dKSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGlzIHN0cmVhbSBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcjogU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIHByaXZhdGUgd2ViUnRjUGVlcjogYW55O1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5ib3VuZFN0cmVhbU9wdHM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3BlZWNoRXZlbnQ6IGFueTtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlc3Npb246IFNlc3Npb24sIG9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zIHwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIHwge30pIHtcblxuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCdpZCcpKSB7XG4gICAgICAgICAgICAvLyBJbmJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBTdWJzY3JpYmVyXG4gICAgICAgICAgICB0aGlzLmluYm91bmRTdHJlYW1PcHRzID0gPEluYm91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9ICdTQ1JFRU4nO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ1NDUkVFTic7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NBTUVSQSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSAnTUlDUk8nO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnR5cGVPZlZpZGVvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaXNTZW5kQXVkaW8oKTtcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmlzU2VuZFZpZGVvKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVlLm9uKCdtZWRpYXN0cmVhbS11cGRhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnVwZGF0ZU1lZGlhU3RyZWFtKHRoaXMubWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnVmlkZW8gc3JjT2JqZWN0IFsnICsgdGhpcy5tZWRpYVN0cmVhbSArICddIHVwZGF0ZWQgaW4gc3RyZWFtIFsnICsgdGhpcy5zdHJlYW1JZCArICddJyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRNZWRpYVN0cmVhbSgpOiBNZWRpYVN0cmVhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRXZWJSdGNQZWVyKCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wZWVyQ29ubmVjdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLmhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1BlZXJTZW5kKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgb3B0aW9uczogYW55ID0ge1xuICAgICAgICAgICAgICAgIHZpZGVvU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoZXJyb3IsIHNkcE9mZmVyUGFyYW0sIHdwKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhwdWJsaXNoKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTZW5kaW5nIFNEUCBvZmZlciB0byBwdWJsaXNoIGFzICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncHVibGlzaFZpZGVvJywge1xuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbSxcbiAgICAgICAgICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHRoaXMuaXNTZW5kVmlkZW8oKSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86ICgodGhpcy5pc1NlbmRWaWRlbygpKSA/ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJykgOiAnJyksXG4gICAgICAgICAgICAgICAgICAgIGZyYW1lUmF0ZTogISF0aGlzLmZyYW1lUmF0ZSA/IHRoaXMuZnJhbWVSYXRlIDogLTFcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdFcnJvciBvbiBwdWJsaXNoVmlkZW86ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzU2RwQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiByZW1vdGUgbm93IHdlIGNhbiBzZXQgdGhlIHNyY09iamVjdCB2YWx1ZSBvZiB2aWRlbyBlbGVtZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gJ3N0cmVhbVBsYXlpbmcnIGV2ZW50IHdpbGwgYmUgdHJpZ2dlcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0ga3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIuV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGVyciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKHN1Y2Nlc3NDYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLldlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zLCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcihzdWNjZXNzQ2FsbGJhY2spO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5yZWN2VmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiJ1Nlc3Npb24uc3Vic2NyaWJlKFN0cmVhbSknIGNhbGxlZC4gQ29uc3RyYWludHMgb2YgZ2VuZXJhdGUgU0RQIG9mZmVyXCIsXG4gICAgICAgICAgICAgICAgb2ZmZXJDb25zdHJhaW50cyk7XG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogb2ZmZXJDb25zdHJhaW50c1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc0NhbGxiYWNrID0gKGVycm9yLCBzZHBPZmZlclBhcmFtLCB3cCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTZW5kaW5nIFNEUCBvZmZlciB0byBzdWJzY3JpYmUgdG8gJ1xuICAgICAgICAgICAgICAgICAgICArIHRoaXMuc3RyZWFtSWQsIHNkcE9mZmVyUGFyYW0pO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncmVjZWl2ZVZpZGVvRnJvbScsIHtcbiAgICAgICAgICAgICAgICAgICAgc2VuZGVyOiB0aGlzLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbVxuICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdFcnJvciBvbiByZWN2VmlkZW9Gcm9tOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NTZHBBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBrdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5XZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcihzdWNjZXNzQ2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcHJvY2Vzc1NkcEFuc3dlcihzZHBBbnN3ZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXIsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1Zyh0aGlzLnN0cmVhbUlkICsgJzogc2V0IHBlZXIgY29ubmVjdGlvbiB3aXRoIHJlY3ZkIFNEUCBhbnN3ZXInLCBzZHBBbnN3ZXIpO1xuXG4gICAgICAgICAgICBjb25zdCBzdHJlYW1JZCA9IHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgICAgICBjb25zdCBwZWVyQ29ubmVjdGlvbiA9IHRoaXMud2ViUnRjUGVlci5wZWVyQ29ubmVjdGlvbjtcbiAgICAgICAgICAgIHBlZXJDb25uZWN0aW9uLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlciwgKCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHJlbW90ZSBNZWRpYVN0cmVhbSBvYmplY3QgZXhjZXB0IHdoZW4gbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzTG9jYWwoKSB8fCB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBwZWVyQ29ubmVjdGlvbi5nZXRSZW1vdGVTdHJlYW1zKClbMF07XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1BlZXIgcmVtb3RlIHN0cmVhbScsIHRoaXMubWVkaWFTdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghIXRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0gJiYgdGhpcy5zZXNzaW9uLnNwZWFraW5nRXZlbnRzRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgICAgICB9LCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcih0aGlzLnN0cmVhbUlkICsgJzogRXJyb3Igc2V0dGluZyBTRFAgdG8gdGhlIHBlZXIgY29ubmVjdGlvbjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzID0gbmV3IFdlYlJ0Y1N0YXRzKHRoaXMpO1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RvcFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLndlYlJ0Y1N0YXRzICYmIHRoaXMud2ViUnRjU3RhdHMuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbCgpOiBib29sZWFuIHtcbiAgICAgICAgLy8gaW5ib3VuZCBvcHRpb25zIHVuZGVmaW5lZCBhbmQgb3V0Ym91bmQgb3B0aW9ucyBkZWZpbmVkXG4gICAgICAgIHJldHVybiAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgJiYgISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGB2aWRlb2AgZWxlbWVudCBwYXJhbWV0ZXIgZGlzcGxheSB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IGFyZVxuICAgICAqIFttYW5hZ2luZyB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd25dKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpXG4gICAgICpcbiAgICAgKiBDYWxsaW5nIHRoaXMgbWV0aG9kIHdpdGggYSB2aWRlbyBhbHJlYWR5IGFkZGVkIHRvIG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgY2F1c2UgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYmVcbiAgICAgKiBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBwcmV2aW91cyBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgdG8gYmUgYXNzb2NpYXRlZCB0byB0aGlzIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIDEgaWYgdGhlIHZpZGVvIHdhc24ndCBhc3NvY2lhdGVkIHRvIGFueSBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqIDAgaWYgdGhlIHZpZGVvIHdhcyBhbHJlYWR5IGFkZGVkIHRvIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXIuIC0xIGlmIHRoZSB2aWRlbyB3YXMgcHJldmlvdXNseSBhc3NvY2lhdGVkIHRvIGFueSBvdGhlclxuICAgICAqIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgb25lIGFuZCBwcm9wZXJseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKi9cbiAgICBhZGRWaWRlb0VsZW1lbnQodmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgLy8gSWYgdGhlIHZpZGVvIGVsZW1lbnQgaXMgYWxyZWFkeSBwYXJ0IG9mIHRoaXMgU3RyZWFtTWFuYWdlciBkbyBub3RoaW5nXG4gICAgICAgIGZvciAoY29uc3QgdiBvZiB0aGlzLnZpZGVvcykge1xuICAgICAgICAgICAgaWYgKHYudmlkZW8gPT09IHZpZGVvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmV0dXJuTnVtYmVyID0gMTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3Muc2xpY2UoKS5yZXZlcnNlKCkuZm9yRWFjaCgoc3RyZWFtTWFuYWdlclZpZGVvLCBpbmRleCwgdmlkZW9zKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgb25jYW5wbGF5IGV2ZW50IGxpc3RlbmVyIChvbmx5IE9wZW5WaWR1IGJyb3dzZXIgb25lLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICAgICAgaWYgKCEhc3RyZWFtTWFuYWdlclZpZGVvLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbW92ZSB2aWRlb3MgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyICh0aG9zZSBnZW5lcmF0ZWQgYnkgcGFzc2luZyBhIHZhbGlkIHRhcmdldEVsZW1lbnQgaW4gT3BlblZpZHUuaW5pdFB1Ymxpc2hlciBhbmQgU2Vzc2lvbi5zdWJzY3JpYmVcbiAgICAgICAgICAgICAgICAvLyBvciB0aG9zZSBjcmVhdGVkIGJ5IFN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KS4gVGhlc2UgYXJlIGFsc28gdGhlIHZpZGVvcyB0aGF0IHRyaWdnZXJlZCBhIHZpZGVvRWxlbWVudENyZWF0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucGFyZW50Tm9kZSEucmVtb3ZlQ2hpbGQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50RGVzdHJveWVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZSh2aWRlb3MubGVuZ3RoIC0gMSAtIGluZGV4LCAxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHNyY09iamVjdCBpbiBhbGwgdmlkZW9zIG1hbmFnZWQgYnkgdGhlIHVzZXJcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwcG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gY2FwdHVyZSBzb21lIGRlc2t0b3Agc2NyZWVuIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBoYXMgYmVlbiBjYWxsZWQgd2l0aCBwcm9wZXJ0aWVzIGB2aWRlb1NvdXJjZWAgYW5kIGBhdWRpb1NvdXJjZWAgb2ZcbiAgICAgKiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBwYXJhbWV0ZXIgYm90aCBzZXQgdG8gKmZhbHNlKiBvciAqbnVsbCpcbiAgICAgKi9cbiAgICBOT19JTlBVVF9TT1VSQ0VfU0VUID0gJ05PX0lOUFVUX1NPVVJDRV9TRVQnLFxuXG4gICAgLyoqXG4gICAgICogU29tZSBtZWRpYSBwcm9wZXJ0eSBvZiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBzdWNoIGFzIGBmcmFtZVJhdGVgIG9yIGByZXNvbHV0aW9uYCBpcyBub3Qgc3VwcG9ydGVkXG4gICAgICogYnkgdGhlIGlucHV0IGRldmljZXMgKHdoZW5ldmVyIGl0IGlzIHBvc3NpYmxlIHRoZXkgYXJlIGF1dG9tYXRpY2FsbHkgYWRqdXN0ZWQgdG8gdGhlIG1vc3Qgc2ltaWxhciB2YWx1ZSkuXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEID0gJ09QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuLyoqXG4gKiBTaW1wbGUgb2JqZWN0IHRvIGlkZW50aWZ5IHJ1bnRpbWUgZXJyb3JzIG9uIHRoZSBjbGllbnQgc2lkZVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHVFcnJvciB7XG5cbiAgICBuYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBIb3cgdGhlIHZpZGVvIHdpbGwgYmUgaW5zZXJ0ZWQgaW4gdGhlIERPTSBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuIFNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dIGFuZCBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXVxuICovXG5leHBvcnQgZW51bSBWaWRlb0luc2VydE1vZGUge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHRhcmdldCBlbGVtZW50IChhcyBuZXh0IHNpYmxpbmcpXG4gICAgICovXG4gICAgQUZURVIgPSAnQUZURVInLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGxhc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgQVBQRU5EID0gJ0FQUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYmVmb3JlIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgcHJldmlvdXMgc2libGluZylcbiAgICAgKi9cbiAgICBCRUZPUkUgPSAnQkVGT1JFJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBmaXJzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBQUkVQRU5EID0gJ1BSRVBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIHJlcGxhY2VzIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUkVQTEFDRSA9ICdSRVBMQUNFJ1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYGNvbm5lY3Rpb25DcmVhdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgY29ubmVjdGlvbkRlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgd2FzIGNyZWF0ZWQgb3IgZGVzdHJveWVkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZvciAnY29ubmVjdGlvbkRlc3Ryb3llZCcgZXZlbnQ6XG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3VyIHRoYXQgbWF5IGJlIHByZXZlbnRlZCBieSBjYWxsaW5nIFtbRXZlbnQucHJldmVudERlZmF1bHRdXVxuICAgICAqL1xuICAgIGNhbmNlbGFibGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0IHRoYXQgZGlzcGF0Y2hlZCB0aGUgZXZlbnRcbiAgICAgKi9cbiAgICB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHR5cGUgb2YgZXZlbnQuIFRoaXMgaXMgdGhlIHNhbWUgc3RyaW5nIHlvdSBwYXNzIGFzIGZpcnN0IHBhcmFtZXRlciB3aGVuIGNhbGxpbmcgbWV0aG9kIGBvbigpYCBvZiBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBbW0V2ZW50RGlzcGF0Y2hlcl1dIGludGVyZmFjZVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIHByaXZhdGUgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvdXI6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvdXIgPSAoKSA9PiB7IH07XG4gICAgICAgIHRoaXMuaGFzQmVlblByZXZlbnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHJlY29yZGluZ1N0YXJ0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGByZWNvcmRpbmdTdG9wcGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIElEIGdlbmVyYXRlZCBpbiBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlY29yZGluZyBuYW1lIHlvdSBzdXBwbGllZCB0byBvcGVudmlkdS1zZXJ2ZXIuIEZvciBleGFtcGxlLCB0byBuYW1lIHlvdXIgcmVjb3JkaW5nIGZpbGUgTVlfUkVDT1JESU5HOlxuICAgICAqIC0gV2l0aCAqKkFQSSBSRVNUKio6IFBPU1QgdG8gYC9hcGkvcmVjb3JkaW5ncy9zdGFydGAgcGFzc2luZyBKU09OIGJvZHkgYHtcInNlc3Npb25cIjpcInNlc3Npb25JZFwiLFwibmFtZVwiOlwiTVlfUkVDT1JESU5HXCJ9YFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LWphdmEtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIE1ZX1JFQ09SRElORylgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKE1ZX1JFQ09SRElORykuYnVpbGQoKSlgXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtbm9kZS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgTVlfUkVDT1JESU5HKWAgb3IgYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgbmV3IFJlY29yZGluZ1Byb3BlcnRpZXMuQnVpbGRlcigpLm5hbWUoTVlfUkVDT1JESU5HKS5idWlsZCgpKWBcbiAgICAgKlxuICAgICAqIElmIG5vIG5hbWUgaXMgc3VwcGxpZWQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSB1bmRlZmluZWQgYW5kIHRoZSByZWNvcmRlZCBmaWxlIHdpbGwgYmUgbmFtZWQgYWZ0ZXIgcHJvcGVydHkgW1tpZF1dXG4gICAgICovXG4gICAgbmFtZT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIGlmIChuYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogeW91IGhhdmUgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogeW91ciBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHRydWUsIHRhcmdldCwgJ3Nlc3Npb25EaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkNhbGxpbmcgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvdXIoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEZvciAnc3RyZWFtRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwidW5wdWJsaXNoXCI6IG1ldGhvZCBgU2Vzc2lvbi51bnB1Ymxpc2goKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogbWV0aG9kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcIm5ldHdvcmtEaXNjb25uZWN0XCI6IHRoZSB1c2VyJ3MgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ3N0cmVhbUNyZWF0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFB1Ymxpc2hlciwgdHlwZTogc3RyaW5nLCBzdHJlYW06IFN0cmVhbSwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgUHVibGlzaGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9jYWwgU3RyZWFtXG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW91ciB1cG9uICdcIiArIHRoaXMudHlwZSArIFwiJyBldmVudCBkaXNwYXRjaGVkIGJ5ICdQdWJsaXNoZXInXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHZpZGVvRWxlbWVudENyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuIFNlZVxuICogW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uLlxuICogLSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSB3aGVuZXZlciBhbiBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWRlb0VsZW1lbnRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGVsZW1lbnQgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBlbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQsIHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiZnVuY3Rpb24gTWFwcGVyKClcbntcbiAgdmFyIHNvdXJjZXMgPSB7fTtcblxuXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKVxuICB7XG4gICAgZm9yKHZhciBrZXkgaW4gc291cmNlcylcbiAgICB7XG4gICAgICB2YXIgc291cmNlID0gc291cmNlc1trZXldO1xuXG4gICAgICBmb3IodmFyIGtleTIgaW4gc291cmNlKVxuICAgICAgICBjYWxsYmFjayhzb3VyY2Vba2V5Ml0pO1xuICAgIH07XG4gIH07XG5cbiAgdGhpcy5nZXQgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBpZHNbaWRdO1xuICB9O1xuXG4gIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcblxuICAgIGRlbGV0ZSBpZHNbaWRdO1xuXG4gICAgLy8gQ2hlY2sgaXQncyBlbXB0eVxuICAgIGZvcih2YXIgaSBpbiBpZHMpe3JldHVybiBmYWxzZX1cblxuICAgIGRlbGV0ZSBzb3VyY2VzW3NvdXJjZV07XG4gIH07XG5cbiAgdGhpcy5zZXQgPSBmdW5jdGlvbih2YWx1ZSwgaWQsIHNvdXJjZSlcbiAge1xuICAgIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHNvdXJjZXNbc291cmNlXSA9IGlkcyA9IHt9O1xuXG4gICAgaWRzW2lkXSA9IHZhbHVlO1xuICB9O1xufTtcblxuXG5NYXBwZXIucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG57XG4gIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGlkLCBzb3VyY2UpO1xuICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICByZXR1cm4gdmFsdWU7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gTWFwcGVyO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBKc29uUnBjQ2xpZW50ICA9IHJlcXVpcmUoJy4vanNvbnJwY2NsaWVudCcpO1xuXG5cbmV4cG9ydHMuSnNvblJwY0NsaWVudCAgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uLycpO1xudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5EYXRlLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiArbmV3IERhdGU7XG59O1xuXG52YXIgUElOR19JTlRFUlZBTCA9IDUwMDA7XG5cbnZhciBSRUNPTk5FQ1RJTkcgPSAnUkVDT05ORUNUSU5HJztcbnZhciBDT05ORUNURUQgPSAnQ09OTkVDVEVEJztcbnZhciBESVNDT05ORUNURUQgPSAnRElTQ09OTkVDVEVEJztcblxudmFyIExvZ2dlciA9IGNvbnNvbGU7XG5cbi8qKlxuICpcbiAqIGhlYXJ0YmVhdDogaW50ZXJ2YWwgaW4gbXMgZm9yIGVhY2ggaGVhcnRiZWF0IG1lc3NhZ2UsXG4gKiBzZW5kQ2xvc2VNZXNzYWdlIDogdHJ1ZSAvIGZhbHNlLCBiZWZvcmUgY2xvc2luZyB0aGUgY29ubmVjdGlvbiwgaXQgc2VuZHMgYSBjbG9zZVNlc3Npb24gbWVzc2FnZVxuICogPHByZT5cbiAqIHdzIDoge1xuICogXHR1cmkgOiBVUkkgdG8gY29ubnRlY3QgdG8sXG4gKiAgdXNlU29ja0pTIDogdHJ1ZSAodXNlIFNvY2tKUykgLyBmYWxzZSAodXNlIFdlYlNvY2tldCkgYnkgZGVmYXVsdCxcbiAqIFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuICogXHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcbiAqIFx0b25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG4gKiBcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbiAqIFx0b25lcnJvciA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGVyZSBpcyBhbiBlcnJvclxuICogfSxcbiAqIHJwYyA6IHtcbiAqIFx0cmVxdWVzdFRpbWVvdXQgOiB0aW1lb3V0IGZvciBhIHJlcXVlc3QsXG4gKiBcdHNlc3Npb25TdGF0dXNDaGFuZ2VkOiBjYWxsYmFjayBtZXRob2QgZm9yIGNoYW5nZXMgaW4gc2Vzc2lvbiBzdGF0dXMsXG4gKiBcdG1lZGlhUmVuZWdvdGlhdGlvbjogbWVkaWFSZW5lZ290aWF0aW9uXG4gKiB9XG4gKiA8L3ByZT5cbiAqL1xuZnVuY3Rpb24gSnNvblJwY0NsaWVudChjb25maWd1cmF0aW9uKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgd3NDb25maWcgPSBjb25maWd1cmF0aW9uLndzO1xuXG4gICAgdmFyIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSAtMTtcblxuICAgIHZhciBwaW5nTmV4dE51bSA9IDA7XG4gICAgdmFyIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgdmFyIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgIHZhciBwaW5nSW50ZXJ2YWw7XG5cbiAgICB2YXIgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgdmFyIG9ucmVjb25uZWN0aW5nID0gd3NDb25maWcub25yZWNvbm5lY3Rpbmc7XG4gICAgdmFyIG9ucmVjb25uZWN0ZWQgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGVkO1xuICAgIHZhciBvbmNvbm5lY3RlZCA9IHdzQ29uZmlnLm9uY29ubmVjdGVkO1xuICAgIHZhciBvbmVycm9yID0gd3NDb25maWcub25lcnJvcjtcblxuICAgIGNvbmZpZ3VyYXRpb24ucnBjLnB1bGwgPSBmdW5jdGlvbihwYXJhbXMsIHJlcXVlc3QpIHtcbiAgICAgICAgcmVxdWVzdC5yZXBseShudWxsLCBcInB1c2hcIik7XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNUSU5HIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBSRUNPTk5FQ1RJTkcpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIFJFQ09OTkVDVElORyBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVElORyBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXR1cyA9IFJFQ09OTkVDVElORztcbiAgICAgICAgaWYgKG9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9ucmVjb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uY29ubmVjdGVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05DT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVzZVBpbmcoKTtcblxuICAgICAgICBpZiAob25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9ORVJST1IgLS0tLS0tLS0tLS1cIik7XG5cbiAgICAgICAgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgICAgIGlmIChvbmVycm9yKSB7XG4gICAgICAgICAgICBvbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKHdzQ29uZmlnKTtcblxuICAgIExvZ2dlci5kZWJ1ZygnQ29ubmVjdGluZyB3ZWJzb2NrZXQgdG8gVVJJOiAnICsgd3NDb25maWcudXJpKTtcblxuICAgIHZhciBycGNCdWlsZGVyT3B0aW9ucyA9IHtcbiAgICAgICAgcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5yZXF1ZXN0VGltZW91dCxcbiAgICAgICAgcGluZ19yZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLmhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0XG4gICAgfTtcblxuICAgIHZhciBycGMgPSBuZXcgUnBjQnVpbGRlcihScGNCdWlsZGVyLnBhY2tlcnMuSnNvblJQQywgcnBjQnVpbGRlck9wdGlvbnMsIHdzLFxuICAgICAgICBmdW5jdGlvbihyZXF1ZXN0KSB7XG5cbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVjZWl2ZWQgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IGNvbmZpZ3VyYXRpb24ucnBjW3JlcXVlc3QubWV0aG9kXTtcblxuICAgICAgICAgICAgICAgIGlmIChmdW5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWV0aG9kIFwiICsgcmVxdWVzdC5tZXRob2QgKyBcIiBub3QgcmVnaXN0ZXJlZCBpbiBjbGllbnRcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyhyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKCdFeGNlcHRpb24gcHJvY2Vzc2luZyByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAobWV0aG9kICE9PSAncGluZycpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVxdWVzdDogbWV0aG9kOicgKyBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgcnBjLmVuY29kZShtZXRob2QsIHBhcmFtcywgZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1I6XCIgKyBlcnJvci5tZXNzYWdlICsgXCIgaW4gUmVxdWVzdDogbWV0aG9kOlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyBcIiByZXF1ZXN0OlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1IgREFUQTpcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yLmRhdGEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdFRpbWUgPSByZXF1ZXN0VGltZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT0gdW5kZWZpbmVkICYmIHJlc3VsdC52YWx1ZSAhPT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVzcG9uc2U6ICcgKyBKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIm5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBcIiArIHBpbmdOZXh0TnVtICsgJyAob2xkPScgK1xuICAgICAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiArICcpJyk7XG4gICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBwaW5nTmV4dE51bTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZW5kUGluZygpIHtcbiAgICAgICAgaWYgKGVuYWJsZWRQaW5ncykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG51bGw7XG4gICAgICAgICAgICBpZiAocGluZ05leHROdW0gPT0gMCB8fCBwaW5nTmV4dE51bSA9PSBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbDogY29uZmlndXJhdGlvbi5oZWFydGJlYXQgfHwgUElOR19JTlRFUlZBTFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwaW5nTmV4dE51bSsrO1xuXG4gICAgICAgICAgICBzZWxmLnNlbmQoJ3BpbmcnLCBwYXJhbXMsIChmdW5jdGlvbihwaW5nTnVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJFcnJvciBpbiBwaW5nIHJlcXVlc3QgI1wiICsgcGluZ051bSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubWVzc2FnZSArIFwiKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaW5nTnVtID4gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZXJ2ZXIgZGlkIG5vdCByZXNwb25kIHRvIHBpbmcgbWVzc2FnZSAjXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5nTnVtICsgXCIuIFJlY29ubmVjdGluZy4uLiBcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKHBpbmdOZXh0TnVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUcnlpbmcgdG8gc2VuZCBwaW5nLCBidXQgcGluZyBpcyBub3QgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgKiBJZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0IGhhcyBhbnkgdmFsdWUsIHRoZSBwaW5nLXBvbmcgd2lsbCB3b3JrIHdpdGggdGhlIGludGVydmFsXG4gICAgKiBvZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0XG4gICAgKi9cbiAgICBmdW5jdGlvbiB1c2VQaW5nKCkge1xuICAgICAgICBpZiAoIXBpbmdQb25nU3RhcnRlZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgcGluZyAoaWYgY29uZmlndXJlZClcIilcbiAgICAgICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwaW5nSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzZW5kUGluZywgY29uZmlndXJhdGlvbi5oZWFydGJlYXQpO1xuICAgICAgICAgICAgICAgIHNlbmRQaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NpbmcganNvblJwY0NsaWVudCBleHBsaWNpdGx5IGJ5IGNsaWVudFwiKTtcblxuICAgICAgICBpZiAocGluZ0ludGVydmFsICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xlYXJpbmcgcGluZyBpbnRlcnZhbFwiKTtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGNvbmZpZ3VyYXRpb24uc2VuZENsb3NlTWVzc2FnZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VuZGluZyBjbG9zZSBtZXNzYWdlXCIpXG4gICAgICAgICAgICB0aGlzLnNlbmQoJ2Nsb3NlU2Vzc2lvbicsIG51bGwsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyBjbG9zZSBtZXNzYWdlOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcblx0XHRcdHdzLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIHdzLmZvcmNlQ2xvc2UobWlsbGlzKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlY29ubmVjdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpzb25ScGNDbGllbnQ7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gID0gcmVxdWlyZSgnLi93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cblxuZXhwb3J0cy5XZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb247IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxMy0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIEJyb3dzZXJXZWJTb2NrZXQgPSBnbG9iYWwuV2ViU29ja2V0IHx8IGdsb2JhbC5Nb3pXZWJTb2NrZXQ7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqIEdldCBlaXRoZXIgdGhlIGBXZWJTb2NrZXRgIG9yIGBNb3pXZWJTb2NrZXRgIGdsb2JhbHNcbiAqIGluIHRoZSBicm93c2VyIG9yIHRyeSB0byByZXNvbHZlIFdlYlNvY2tldC1jb21wYXRpYmxlXG4gKiBpbnRlcmZhY2UgZXhwb3NlZCBieSBgd3NgIGZvciBOb2RlLWxpa2UgZW52aXJvbm1lbnQuXG4gKi9cblxuLyp2YXIgV2ViU29ja2V0ID0gQnJvd3NlcldlYlNvY2tldDtcbmlmICghV2ViU29ja2V0ICYmIHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgV2ViU29ja2V0ID0gcmVxdWlyZSgnd3MnKTtcbiAgICB9IGNhdGNoIChlKSB7IH1cbn0qL1xuXG4vL3ZhciBTb2NrSlMgPSByZXF1aXJlKCdzb2NranMtY2xpZW50Jyk7XG5cbnZhciBNQVhfUkVUUklFUyA9IDIwMDA7IC8vIEZvcmV2ZXIuLi5cbnZhciBSRVRSWV9USU1FX01TID0gMzAwMDsgLy8gRklYTUU6IEltcGxlbWVudCBleHBvbmVudGlhbCB3YWl0IHRpbWVzLi4uXG5cbnZhciBDT05ORUNUSU5HID0gMDtcbnZhciBPUEVOID0gMTtcbnZhciBDTE9TSU5HID0gMjtcbnZhciBDTE9TRUQgPSAzO1xuXG4vKlxuY29uZmlnID0ge1xuXHRcdHVyaSA6IHdzVXJpLFxuXHRcdHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG5cdFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuXHRcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuXHRcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuXHRcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNC0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKVxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIFVBUGFyc2VyID0gcmVxdWlyZSgndWEtcGFyc2VyLWpzJylcbnZhciB1dWlkID0gcmVxdWlyZSgndXVpZCcpXG52YXIgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKVxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyXG52YXIgcmVjdXJzaXZlID0gcmVxdWlyZSgnbWVyZ2UnKS5yZWN1cnNpdmUuYmluZCh1bmRlZmluZWQsIHRydWUpXG52YXIgc2RwVHJhbnNsYXRvciA9IHJlcXVpcmUoJ3NkcC10cmFuc2xhdG9yJylcbnZhciBsb2dnZXIgPSB3aW5kb3cuTG9nZ2VyIHx8IGNvbnNvbGVcblxuLy8gdmFyIGdVTSA9IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhIHx8IGZ1bmN0aW9uIChjb25zdHJhaW50cykge1xuLy8gICByZXR1cm4gbmV3IFByb21pc2UobmF2aWdhdG9yLmdldFVzZXJNZWRpYShjb25zdHJhaW50cywgZnVuY3Rpb24gKHN0cmVhbSkge1xuLy8gICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4vLyAgICAgc3RhcnQoKVxuLy8gICB9KS5lcm9yKGNhbGxiYWNrKSk7XG4vLyB9XG5cbi8qdHJ5IHtcbiAgcmVxdWlyZSgna3VyZW50by1icm93c2VyLWV4dGVuc2lvbnMnKVxufSBjYXRjaCAoZXJyb3IpIHtcbiAgaWYgKHR5cGVvZiBnZXRTY3JlZW5Db25zdHJhaW50cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBsb2dnZXIud2Fybignc2NyZWVuIHNoYXJpbmcgaXMgbm90IGF2YWlsYWJsZScpXG5cbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyA9IGZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKHNlbmRTb3VyY2UsIGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoXCJUaGlzIGxpYnJhcnkgaXMgbm90IGVuYWJsZWQgZm9yIHNjcmVlbiBzaGFyaW5nXCIpKVxuICAgIH1cbiAgfVxufSovXG5cbnZhciBNRURJQV9DT05TVFJBSU5UUyA9IHtcbiAgYXVkaW86IHRydWUsXG4gIHZpZGVvOiB7XG4gICAgd2lkdGg6IDY0MCxcbiAgICBmcmFtZXJhdGU6IDE1XG4gIH1cbn1cblxuLy8gU29tZWhvdywgdGhlIFVBUGFyc2VyIGNvbnN0cnVjdG9yIGdldHMgYW4gZW1wdHkgd2luZG93IG9iamVjdC5cbi8vIFdlIG5lZWQgdG8gcGFzcyB0aGUgdXNlciBhZ2VudCBzdHJpbmcgaW4gb3JkZXIgdG8gZ2V0IGluZm9ybWF0aW9uXG52YXIgdWEgPSAod2luZG93ICYmIHdpbmRvdy5uYXZpZ2F0b3IpID8gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQgOiAnJ1xudmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcih1YSlcbnZhciBicm93c2VyID0gcGFyc2VyLmdldEJyb3dzZXIoKVxuXG52YXIgdXNlUGxhbkIgPSBmYWxzZVxuaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gIGxvZ2dlci5kZWJ1Zyhicm93c2VyLm5hbWUgKyBcIjogdXNpbmcgU0RQIFBsYW5CXCIpXG4gIHVzZVBsYW5CID0gdHJ1ZVxufVxuXG5mdW5jdGlvbiBub29wKGVycm9yKSB7XG4gIGlmIChlcnJvcikgbG9nZ2VyLmVycm9yKGVycm9yKVxufVxuXG5mdW5jdGlvbiB0cmFja1N0b3AodHJhY2spIHtcbiAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbn1cblxuZnVuY3Rpb24gc3RyZWFtU3RvcChzdHJlYW0pIHtcbiAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2godHJhY2tTdG9wKVxufVxuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBTZXNzaW9uRGVzY3JpcHRpb24gb2JqZWN0LlxuICovXG52YXIgZHVtcFNEUCA9IGZ1bmN0aW9uIChkZXNjcmlwdGlvbikge1xuICBpZiAodHlwZW9mIGRlc2NyaXB0aW9uID09PSAndW5kZWZpbmVkJyB8fCBkZXNjcmlwdGlvbiA9PT0gbnVsbCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgcmV0dXJuICd0eXBlOiAnICsgZGVzY3JpcHRpb24udHlwZSArICdcXHJcXG4nICsgZGVzY3JpcHRpb24uc2RwXG59XG5cbmZ1bmN0aW9uIGJ1ZmZlcml6ZUNhbmRpZGF0ZXMocGMsIG9uZXJyb3IpIHtcbiAgdmFyIGNhbmRpZGF0ZXNRdWV1ZSA9IFtdXG5cbiAgcGMuYWRkRXZlbnRMaXN0ZW5lcignc2lnbmFsaW5nc3RhdGVjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlLmxlbmd0aCkge1xuICAgICAgICB2YXIgZW50cnkgPSBjYW5kaWRhdGVzUXVldWUuc2hpZnQoKVxuICAgICAgICBwYy5hZGRJY2VDYW5kaWRhdGUoZW50cnkuY2FuZGlkYXRlLCBlbnRyeS5jYWxsYmFjaywgZW50cnkuY2FsbGJhY2spXG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4gIHJldHVybiBmdW5jdGlvbiAoY2FuZGlkYXRlLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgb25lcnJvclxuXG4gICAgc3dpdGNoIChwYy5zaWduYWxpbmdTdGF0ZSkge1xuICAgIGNhc2UgJ2Nsb3NlZCc6XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoJ1BlZXJDb25uZWN0aW9uIG9iamVjdCBpcyBjbG9zZWQnKSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdzdGFibGUnOlxuICAgICAgaWYgKHBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgIHBjLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIGNhbGxiYWNrLCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgY2FuZGlkYXRlc1F1ZXVlLnB1c2goe1xuICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZSxcbiAgICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG4vKiBTaW11bGNhc3QgdXRpbGl0aWVzICovXG5cbmZ1bmN0aW9uIHJlbW92ZUZJREZyb21PZmZlcihzZHApIHtcbiAgdmFyIG4gPSBzZHAuaW5kZXhPZihcImE9c3NyYy1ncm91cDpGSURcIik7XG5cbiAgaWYgKG4gPiAwKSB7XG4gICAgcmV0dXJuIHNkcC5zbGljZSgwLCBuKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc2RwO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFNpbXVsY2FzdEluZm8odmlkZW9TdHJlYW0pIHtcbiAgdmFyIHZpZGVvVHJhY2tzID0gdmlkZW9TdHJlYW0uZ2V0VmlkZW9UcmFja3MoKTtcbiAgaWYgKCF2aWRlb1RyYWNrcy5sZW5ndGgpIHtcbiAgICBsb2dnZXIud2FybignTm8gdmlkZW8gdHJhY2tzIGF2YWlsYWJsZSBpbiB0aGUgdmlkZW8gc3RyZWFtJylcbiAgICByZXR1cm4gJydcbiAgfVxuICB2YXIgbGluZXMgPSBbXG4gICAgJ2E9eC1nb29nbGUtZmxhZzpjb25mZXJlbmNlJyxcbiAgICAnYT1zc3JjLWdyb3VwOlNJTSAxIDIgMycsXG4gICAgJ2E9c3NyYzoxIGNuYW1lOmxvY2FsVmlkZW8nLFxuICAgICdhPXNzcmM6MSBtc2lkOicgKyB2aWRlb1N0cmVhbS5pZCArICcgJyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MSBtc2xhYmVsOicgKyB2aWRlb1N0cmVhbS5pZCxcbiAgICAnYT1zc3JjOjEgbGFiZWw6JyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MiBjbmFtZTpsb2NhbFZpZGVvJyxcbiAgICAnYT1zc3JjOjIgbXNpZDonICsgdmlkZW9TdHJlYW0uaWQgKyAnICcgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjIgbXNsYWJlbDonICsgdmlkZW9TdHJlYW0uaWQsXG4gICAgJ2E9c3NyYzoyIGxhYmVsOicgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjMgY25hbWU6bG9jYWxWaWRlbycsXG4gICAgJ2E9c3NyYzozIG1zaWQ6JyArIHZpZGVvU3RyZWFtLmlkICsgJyAnICsgdmlkZW9UcmFja3NbMF0uaWQsXG4gICAgJ2E9c3NyYzozIG1zbGFiZWw6JyArIHZpZGVvU3RyZWFtLmlkLFxuICAgICdhPXNzcmM6MyBsYWJlbDonICsgdmlkZW9UcmFja3NbMF0uaWRcbiAgXTtcblxuICBsaW5lcy5wdXNoKCcnKTtcblxuICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG59XG5cbi8qKlxuICogV3JhcHBlciBvYmplY3Qgb2YgYW4gUlRDUGVlckNvbm5lY3Rpb24uIFRoaXMgb2JqZWN0IGlzIGFpbWVkIHRvIHNpbXBsaWZ5IHRoZVxuICogZGV2ZWxvcG1lbnQgb2YgV2ViUlRDLWJhc2VkIGFwcGxpY2F0aW9ucy5cbiAqXG4gKiBAY29uc3RydWN0b3IgbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1vZGUgTW9kZSBpbiB3aGljaCB0aGUgUGVlckNvbm5lY3Rpb24gd2lsbCBiZSBjb25maWd1cmVkLlxuICogIFZhbGlkIHZhbHVlcyBhcmU6ICdyZWN2JywgJ3NlbmQnLCBhbmQgJ3NlbmRSZWN2J1xuICogQHBhcmFtIGxvY2FsVmlkZW8gVmlkZW8gdGFnIGZvciB0aGUgbG9jYWwgc3RyZWFtXG4gKiBAcGFyYW0gcmVtb3RlVmlkZW8gVmlkZW8gdGFnIGZvciB0aGUgcmVtb3RlIHN0cmVhbVxuICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gdmlkZW9TdHJlYW0gU3RyZWFtIHRvIGJlIHVzZWQgYXMgcHJpbWFyeSBzb3VyY2VcbiAqICAodHlwaWNhbGx5IHZpZGVvIGFuZCBhdWRpbywgb3Igb25seSB2aWRlbyBpZiBjb21iaW5lZCB3aXRoIGF1ZGlvU3RyZWFtKSBmb3JcbiAqICBsb2NhbFZpZGVvIGFuZCB0byBiZSBhZGRlZCBhcyBzdHJlYW0gdG8gdGhlIFJUQ1BlZXJDb25uZWN0aW9uXG4gKiBAcGFyYW0ge01lZGlhU3RyZWFtfSBhdWRpb1N0cmVhbSBTdHJlYW0gdG8gYmUgdXNlZCBhcyBzZWNvbmQgc291cmNlXG4gKiAgKHR5cGljYWxseSBmb3IgYXVkaW8pIGZvciBsb2NhbFZpZGVvIGFuZCB0byBiZSBhZGRlZCBhcyBzdHJlYW0gdG8gdGhlXG4gKiAgUlRDUGVlckNvbm5lY3Rpb25cbiAqL1xuZnVuY3Rpb24gV2ViUnRjUGVlcihtb2RlLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlcikpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXIobW9kZSwgb3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyLnN1cGVyXy5jYWxsKHRoaXMpXG5cbiAgaWYgKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIGNhbGxiYWNrID0gb3B0aW9uc1xuICAgIG9wdGlvbnMgPSB1bmRlZmluZWRcbiAgfVxuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gIGNhbGxiYWNrID0gKGNhbGxiYWNrIHx8IG5vb3ApLmJpbmQodGhpcylcblxuICB2YXIgc2VsZiA9IHRoaXNcbiAgdmFyIGxvY2FsVmlkZW8gPSBvcHRpb25zLmxvY2FsVmlkZW9cbiAgdmFyIHJlbW90ZVZpZGVvID0gb3B0aW9ucy5yZW1vdGVWaWRlb1xuICB2YXIgdmlkZW9TdHJlYW0gPSBvcHRpb25zLnZpZGVvU3RyZWFtXG4gIHZhciBhdWRpb1N0cmVhbSA9IG9wdGlvbnMuYXVkaW9TdHJlYW1cbiAgdmFyIG1lZGlhQ29uc3RyYWludHMgPSBvcHRpb25zLm1lZGlhQ29uc3RyYWludHNcblxuICB2YXIgY29ubmVjdGlvbkNvbnN0cmFpbnRzID0gb3B0aW9ucy5jb25uZWN0aW9uQ29uc3RyYWludHNcbiAgdmFyIHBjID0gb3B0aW9ucy5wZWVyQ29ubmVjdGlvblxuICB2YXIgc2VuZFNvdXJjZSA9IG9wdGlvbnMuc2VuZFNvdXJjZSB8fCAnd2ViY2FtJ1xuXG4gIC8qdmFyIGRhdGFDaGFubmVsQ29uZmlnID0gb3B0aW9ucy5kYXRhQ2hhbm5lbENvbmZpZ1xuICB2YXIgdXNlRGF0YUNoYW5uZWxzID0gb3B0aW9ucy5kYXRhQ2hhbm5lbHMgfHwgZmFsc2VcbiAgdmFyIGRhdGFDaGFubmVsKi9cblxuICB2YXIgZ3VpZCA9IHV1aWQudjQoKVxuICB2YXIgY29uZmlndXJhdGlvbiA9IHJlY3Vyc2l2ZSh7XG4gICAgICBpY2VTZXJ2ZXJzOiAoISFvcHRpb25zLmljZVNlcnZlcnMgJiYgb3B0aW9ucy5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDApID8gb3B0aW9ucy5pY2VTZXJ2ZXJzIDogZnJlZWljZSgpXG4gICAgfSxcbiAgICBvcHRpb25zLmNvbmZpZ3VyYXRpb24pXG5cbiAgdmFyIG9uaWNlY2FuZGlkYXRlID0gb3B0aW9ucy5vbmljZWNhbmRpZGF0ZVxuICBpZiAob25pY2VjYW5kaWRhdGUpIHRoaXMub24oJ2ljZWNhbmRpZGF0ZScsIG9uaWNlY2FuZGlkYXRlKVxuXG4gIHZhciBvbmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBvcHRpb25zLm9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZVxuICBpZiAob25jYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgdGhpcy5vbignY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScsIG9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSlcbiAgfVxuXG4gIHZhciBzaW11bGNhc3QgPSBvcHRpb25zLnNpbXVsY2FzdFxuICB2YXIgbXVsdGlzdHJlYW0gPSBvcHRpb25zLm11bHRpc3RyZWFtXG4gIHZhciBpbnRlcm9wID0gbmV3IHNkcFRyYW5zbGF0b3IuSW50ZXJvcCgpXG4gIHZhciBjYW5kaWRhdGVzUXVldWVPdXQgPSBbXVxuICB2YXIgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGhpcywge1xuICAgICdwZWVyQ29ubmVjdGlvbic6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcGNcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2lkJzoge1xuICAgICAgdmFsdWU6IG9wdGlvbnMuaWQgfHwgZ3VpZCxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZVxuICAgIH0sXG5cbiAgICAncmVtb3RlVmlkZW8nOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHJlbW90ZVZpZGVvXG4gICAgICB9XG4gICAgfSxcblxuICAgICdsb2NhbFZpZGVvJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBsb2NhbFZpZGVvXG4gICAgICB9XG4gICAgfSxcblxuICAgIC8qJ2RhdGFDaGFubmVsJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkYXRhQ2hhbm5lbFxuICAgICAgfVxuICAgIH0sKi9cblxuICAgIC8qKlxuICAgICAqIEBtZW1iZXIgeyhleHRlcm5hbDpJbWFnZURhdGF8dW5kZWZpbmVkKX0gY3VycmVudEZyYW1lXG4gICAgICovXG4gICAgJ2N1cnJlbnRGcmFtZSc6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBbVG9Eb10gRmluZCBzb2x1dGlvbiB3aGVuIHdlIGhhdmUgYSByZW1vdGUgc3RyZWFtIGJ1dCB3ZSBkaWRuJ3Qgc2V0XG4gICAgICAgIC8vIGEgcmVtb3RlVmlkZW8gdGFnXG4gICAgICAgIGlmICghcmVtb3RlVmlkZW8pIHJldHVybjtcblxuICAgICAgICBpZiAocmVtb3RlVmlkZW8ucmVhZHlTdGF0ZSA8IHJlbW90ZVZpZGVvLkhBVkVfQ1VSUkVOVF9EQVRBKVxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gdmlkZW8gc3RyZWFtIGRhdGEgYXZhaWxhYmxlJylcblxuICAgICAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcbiAgICAgICAgY2FudmFzLndpZHRoID0gcmVtb3RlVmlkZW8udmlkZW9XaWR0aFxuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gcmVtb3RlVmlkZW8udmlkZW9IZWlnaHRcblxuICAgICAgICBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKS5kcmF3SW1hZ2UocmVtb3RlVmlkZW8sIDAsIDApXG5cbiAgICAgICAgcmV0dXJuIGNhbnZhc1xuICAgICAgfVxuICAgIH1cbiAgfSlcblxuICAvLyBJbml0IFBlZXJDb25uZWN0aW9uXG4gIGlmICghcGMpIHtcbiAgICBwYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbihjb25maWd1cmF0aW9uKTtcbiAgICAvKmlmICh1c2VEYXRhQ2hhbm5lbHMgJiYgIWRhdGFDaGFubmVsKSB7XG4gICAgICB2YXIgZGNJZCA9ICdXZWJSdGNQZWVyLScgKyBzZWxmLmlkXG4gICAgICB2YXIgZGNPcHRpb25zID0gdW5kZWZpbmVkXG4gICAgICBpZiAoZGF0YUNoYW5uZWxDb25maWcpIHtcbiAgICAgICAgZGNJZCA9IGRhdGFDaGFubmVsQ29uZmlnLmlkIHx8IGRjSWRcbiAgICAgICAgZGNPcHRpb25zID0gZGF0YUNoYW5uZWxDb25maWcub3B0aW9uc1xuICAgICAgfVxuICAgICAgZGF0YUNoYW5uZWwgPSBwYy5jcmVhdGVEYXRhQ2hhbm5lbChkY0lkLCBkY09wdGlvbnMpO1xuICAgICAgaWYgKGRhdGFDaGFubmVsQ29uZmlnKSB7XG4gICAgICAgIGRhdGFDaGFubmVsLm9ub3BlbiA9IGRhdGFDaGFubmVsQ29uZmlnLm9ub3BlbjtcbiAgICAgICAgZGF0YUNoYW5uZWwub25jbG9zZSA9IGRhdGFDaGFubmVsQ29uZmlnLm9uY2xvc2U7XG4gICAgICAgIGRhdGFDaGFubmVsLm9ubWVzc2FnZSA9IGRhdGFDaGFubmVsQ29uZmlnLm9ubWVzc2FnZTtcbiAgICAgICAgZGF0YUNoYW5uZWwub25idWZmZXJlZGFtb3VudGxvdyA9IGRhdGFDaGFubmVsQ29uZmlnLm9uYnVmZmVyZWRhbW91bnRsb3c7XG4gICAgICAgIGRhdGFDaGFubmVsLm9uZXJyb3IgPSBkYXRhQ2hhbm5lbENvbmZpZy5vbmVycm9yIHx8IG5vb3A7XG4gICAgICB9XG4gICAgfSovXG4gIH1cblxuICBwYy5hZGRFdmVudExpc3RlbmVyKCdpY2VjYW5kaWRhdGUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgY2FuZGlkYXRlID0gZXZlbnQuY2FuZGlkYXRlXG5cbiAgICBpZiAoRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQoc2VsZiwgJ2ljZWNhbmRpZGF0ZScpIHx8XG4gICAgICBFdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudChcbiAgICAgICAgc2VsZiwgJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSkge1xuICAgICAgaWYgKGNhbmRpZGF0ZSkge1xuICAgICAgICB2YXIgY2FuZFxuXG4gICAgICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgICAgIGNhbmQgPSBpbnRlcm9wLmNhbmRpZGF0ZVRvVW5pZmllZFBsYW4oY2FuZGlkYXRlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbmQgPSBjYW5kaWRhdGVcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYuZW1pdCgnaWNlY2FuZGlkYXRlJywgY2FuZClcbiAgICAgICAgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG4gICAgICB9IGVsc2UgaWYgKCFjYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgICAgIHNlbGYuZW1pdCgnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpXG4gICAgICAgIGNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgLy8gTm90IGxpc3RlbmluZyB0byAnaWNlY2FuZGlkYXRlJyBvciAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScgZXZlbnRzLCBxdWV1ZVxuICAgICAgLy8gdGhlIGNhbmRpZGF0ZSB1bnRpbCBvbmUgb2YgdGhlbSBpcyBsaXN0ZW5lZFxuICAgICAgY2FuZGlkYXRlc1F1ZXVlT3V0LnB1c2goY2FuZGlkYXRlKVxuXG4gICAgICBpZiAoIWNhbmRpZGF0ZSkgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWVcbiAgICB9XG4gIH0pXG5cbiAgcGMub25hZGRzdHJlYW0gPSBvcHRpb25zLm9uYWRkc3RyZWFtXG4gIHBjLm9ubmVnb3RpYXRpb25uZWVkZWQgPSBvcHRpb25zLm9ubmVnb3RpYXRpb25uZWVkZWRcbiAgdGhpcy5vbignbmV3TGlzdGVuZXInLCBmdW5jdGlvbiAoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgaWYgKGV2ZW50ID09PSAnaWNlY2FuZGlkYXRlJyB8fCBldmVudCA9PT0gJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlT3V0Lmxlbmd0aCkge1xuICAgICAgICB2YXIgY2FuZGlkYXRlID0gY2FuZGlkYXRlc1F1ZXVlT3V0LnNoaWZ0KClcblxuICAgICAgICBpZiAoIWNhbmRpZGF0ZSA9PT0gKGV2ZW50ID09PSAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpKSB7XG4gICAgICAgICAgbGlzdGVuZXIoY2FuZGlkYXRlKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4gIHZhciBhZGRJY2VDYW5kaWRhdGUgPSBidWZmZXJpemVDYW5kaWRhdGVzKHBjKVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYW4gSUNFIGNhbmRpZGF0ZSBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUuYWRkSWNlQ2FuZGlkYXRlXG4gICAqXG4gICAqIEBwYXJhbSBpY2VDYW5kaWRhdGUgLSBMaXRlcmFsIG9iamVjdCB3aXRoIHRoZSBJQ0UgY2FuZGlkYXRlIGRlc2NyaXB0aW9uXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtIENhbGxlZCB3aGVuIHRoZSBJQ0UgY2FuZGlkYXRlIGhhcyBiZWVuIGFkZGVkLlxuICAgKi9cbiAgdGhpcy5hZGRJY2VDYW5kaWRhdGUgPSBmdW5jdGlvbiAoaWNlQ2FuZGlkYXRlLCBjYWxsYmFjaykge1xuICAgIHZhciBjYW5kaWRhdGVcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgY2FuZGlkYXRlID0gaW50ZXJvcC5jYW5kaWRhdGVUb1BsYW5CKGljZUNhbmRpZGF0ZSlcbiAgICB9IGVsc2Uge1xuICAgICAgY2FuZGlkYXRlID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpXG4gICAgfVxuXG4gICAgbG9nZ2VyLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSlcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSwgY2FsbGJhY2spXG4gIH1cblxuICB0aGlzLmdlbmVyYXRlT2ZmZXIgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrLmJpbmQodGhpcylcblxuICAgIHZhciBvZmZlckF1ZGlvID0gdHJ1ZVxuICAgIHZhciBvZmZlclZpZGVvID0gdHJ1ZVxuICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgIGlmIChtZWRpYUNvbnN0cmFpbnRzKSB7XG4gICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvID09PSAnYm9vbGVhbicpID9cbiAgICAgICAgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA6IHRydWVcbiAgICAgIG9mZmVyVmlkZW8gPSAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZVxuICAgIH1cblxuICAgIHZhciBicm93c2VyRGVwZW5kYW50Q29uc3RyYWludHMgPSB7XG4gICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiAobW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgIG9mZmVyVG9SZWNlaXZlVmlkZW86IChtb2RlICE9PSAnc2VuZG9ubHknICYmIG9mZmVyVmlkZW8pXG4gICAgfVxuXG4gICAgLy9GSVhNRTogY2xhcmlmeSBwb3NzaWJsZSBjb25zdHJhaW50cyBwYXNzZWQgdG8gY3JlYXRlT2ZmZXIoKVxuICAgIC8qdmFyIGNvbnN0cmFpbnRzID0gcmVjdXJzaXZlKGJyb3dzZXJEZXBlbmRhbnRDb25zdHJhaW50cyxcbiAgICAgIGNvbm5lY3Rpb25Db25zdHJhaW50cykqL1xuXG4gICAgdmFyIGNvbnN0cmFpbnRzID0gYnJvd3NlckRlcGVuZGFudENvbnN0cmFpbnRzO1xuXG4gICAgbG9nZ2VyLmRlYnVnKCdjb25zdHJhaW50czogJyArIEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSlcblxuICAgIHBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKGZ1bmN0aW9uIChvZmZlcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpXG4gICAgICBvZmZlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KG9mZmVyKVxuICAgICAgcmV0dXJuIHBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgbG9jYWxEZXNjcmlwdGlvbiA9IHBjLmxvY2FsRGVzY3JpcHRpb25cbiAgICAgIGxvZ2dlci5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApXG4gICAgICBpZiAobXVsdGlzdHJlYW0gJiYgdXNlUGxhbkIpIHtcbiAgICAgICAgbG9jYWxEZXNjcmlwdGlvbiA9IGludGVyb3AudG9VbmlmaWVkUGxhbihsb2NhbERlc2NyaXB0aW9uKVxuICAgICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpvcmlnUGxhbkItPlVuaWZpZWRQbGFuJywgZHVtcFNEUChcbiAgICAgICAgICBsb2NhbERlc2NyaXB0aW9uKSlcbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwLCBzZWxmLnByb2Nlc3NBbnN3ZXIuYmluZChcbiAgICAgICAgc2VsZikpXG4gICAgfSkuY2F0Y2goY2FsbGJhY2spXG4gIH1cblxuICB0aGlzLmdldExvY2FsU2Vzc2lvbkRlc2NyaXB0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHBjLmxvY2FsRGVzY3JpcHRpb25cbiAgfVxuXG4gIHRoaXMuZ2V0UmVtb3RlU2Vzc2lvbkRlc2NyaXB0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHBjLnJlbW90ZURlc2NyaXB0aW9uXG4gIH1cblxuICBmdW5jdGlvbiBzZXRSZW1vdGVWaWRlbygpIHtcbiAgICBpZiAocmVtb3RlVmlkZW8pIHtcbiAgICAgIHJlbW90ZVZpZGVvLnBhdXNlKClcblxuICAgICAgdmFyIHN0cmVhbSA9IHBjLmdldFJlbW90ZVN0cmVhbXMoKVswXVxuICAgICAgcmVtb3RlVmlkZW8uc3JjT2JqZWN0ID0gc3RyZWFtXG4gICAgICBsb2dnZXIuZGVidWcoJ1JlbW90ZSBzdHJlYW06Jywgc3RyZWFtKVxuXG4gICAgICByZW1vdGVWaWRlby5sb2FkKClcbiAgICB9XG4gIH1cblxuICB0aGlzLnNob3dMb2NhbFZpZGVvID0gZnVuY3Rpb24gKCkge1xuICAgIGxvY2FsVmlkZW8uc3JjT2JqZWN0ID0gdmlkZW9TdHJlYW1cbiAgICBsb2NhbFZpZGVvLm11dGVkID0gdHJ1ZVxuICB9XG5cbiAgLyp0aGlzLnNlbmQgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIGlmIChkYXRhQ2hhbm5lbCAmJiBkYXRhQ2hhbm5lbC5yZWFkeVN0YXRlID09PSAnb3BlbicpIHtcbiAgICAgIGRhdGFDaGFubmVsLnNlbmQoZGF0YSlcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICdUcnlpbmcgdG8gc2VuZCBkYXRhIG92ZXIgYSBub24tZXhpc3Rpbmcgb3IgY2xvc2VkIGRhdGEgY2hhbm5lbCcpXG4gICAgfVxuICB9Ki9cblxuICAvKipcbiAgICogQ2FsbGJhY2sgZnVuY3Rpb24gaW52b2tlZCB3aGVuIGEgU0RQIGFuc3dlciBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUucHJvY2Vzc0Fuc3dlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwQW5zd2VyIC0gRGVzY3JpcHRpb24gb2Ygc2RwQW5zd2VyXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtXG4gICAqICAgICAgICAgICAgSW52b2tlZCBhZnRlciB0aGUgU0RQIGFuc3dlciBpcyBwcm9jZXNzZWQsIG9yIHRoZXJlIGlzIGFuIGVycm9yLlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzQW5zd2VyID0gZnVuY3Rpb24gKHNkcEFuc3dlciwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG5cbiAgICB2YXIgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICB0eXBlOiAnYW5zd2VyJyxcbiAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CQW5zd2VyID0gaW50ZXJvcC50b1BsYW5CKGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnYXNud2VyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJBbnN3ZXIpKVxuICAgICAgYW5zd2VyID0gcGxhbkJBbnN3ZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJylcblxuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjaygnUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJylcbiAgICB9XG5cbiAgICBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2V0UmVtb3RlVmlkZW8oKVxuXG4gICAgICAgIGNhbGxiYWNrKClcbiAgICAgIH0sXG4gICAgICBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgb2ZmZXIgaXMgcmVjZWl2ZWQuIERldmVsb3BlcnMgYXJlXG4gICAqIGV4cGVjdGVkIHRvIGludm9rZSB0aGlzIGZ1bmN0aW9uIGluIG9yZGVyIHRvIGNvbXBsZXRlIHRoZSBTRFAgbmVnb3RpYXRpb24uXG4gICAqXG4gICAqIEBmdW5jdGlvbiBtb2R1bGU6a3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIucHJvdG90eXBlLnByb2Nlc3NPZmZlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwT2ZmZXIgLSBEZXNjcmlwdGlvbiBvZiBzZHBPZmZlclxuICAgKiBAcGFyYW0gY2FsbGJhY2sgLSBDYWxsZWQgd2hlbiB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIGhhcyBiZWVuIHNldFxuICAgKiAgc3VjY2Vzc2Z1bGx5LlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzT2ZmZXIgPSBmdW5jdGlvbiAoc2RwT2ZmZXIsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjay5iaW5kKHRoaXMpXG5cbiAgICB2YXIgb2ZmZXIgPSBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICBzZHA6IHNkcE9mZmVyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CT2ZmZXIgPSBpbnRlcm9wLnRvUGxhbkIob2ZmZXIpXG4gICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJPZmZlcikpXG4gICAgICBvZmZlciA9IHBsYW5CT2ZmZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKVxuXG4gICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKVxuICAgIH1cblxuICAgIHBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBzZXRSZW1vdGVWaWRlbygpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcGMuY3JlYXRlQW5zd2VyKClcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChhbnN3ZXIpIHtcbiAgICAgIGFuc3dlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJylcbiAgICAgIHJldHVybiBwYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcilcbiAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBsb2NhbERlc2NyaXB0aW9uID0gcGMubG9jYWxEZXNjcmlwdGlvblxuICAgICAgaWYgKG11bHRpc3RyZWFtICYmIHVzZVBsYW5CKSB7XG4gICAgICAgIGxvY2FsRGVzY3JpcHRpb24gPSBpbnRlcm9wLnRvVW5pZmllZFBsYW4obG9jYWxEZXNjcmlwdGlvbilcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdhbnN3ZXI6Om9yaWdQbGFuQi0+VW5pZmllZFBsYW4nLCBkdW1wU0RQKFxuICAgICAgICAgIGxvY2FsRGVzY3JpcHRpb24pKVxuICAgICAgfVxuICAgICAgbG9nZ2VyLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcClcbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwKVxuICAgIH0pLmNhdGNoKGNhbGxiYWNrKVxuICB9XG5cbiAgZnVuY3Rpb24gbWFuZ2xlU2RwVG9BZGRTaW11bGNhc3QoYW5zd2VyKSB7XG4gICAgaWYgKHNpbXVsY2FzdCkge1xuICAgICAgaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnQWRkaW5nIG11bHRpY2FzdCBpbmZvJylcbiAgICAgICAgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgJ3R5cGUnOiBhbnN3ZXIudHlwZSxcbiAgICAgICAgICAnc2RwJzogcmVtb3ZlRklERnJvbU9mZmVyKGFuc3dlci5zZHApICsgZ2V0U2ltdWxjYXN0SW5mbyhcbiAgICAgICAgICAgIHZpZGVvU3RyZWFtKVxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1NpbXVsY2FzdCBpcyBvbmx5IGF2YWlsYWJsZSBpbiBDaHJvbWUgYnJvd3Nlci4nKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhbnN3ZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdCB0YWtpbmcgaW50byBhY2NvdW50IHRoZVxuICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICogY2FsbGJhY2sgaXMgZXhwZWN0ZWQgdG8gc2VuZCB0aGUgU0RQIG9mZmVyLCBpbiBvcmRlciB0byBvYnRhaW4gYW4gU0RQXG4gICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICovXG4gIGZ1bmN0aW9uIHN0YXJ0KCkge1xuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIGNhbGxiYWNrKFxuICAgICAgICAnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnXG4gICAgICApXG4gICAgfVxuXG4gICAgaWYgKHZpZGVvU3RyZWFtICYmIGxvY2FsVmlkZW8pIHtcbiAgICAgIHNlbGYuc2hvd0xvY2FsVmlkZW8oKVxuICAgIH1cblxuICAgIGlmICh2aWRlb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKHZpZGVvU3RyZWFtKVxuICAgIH1cblxuICAgIGlmIChhdWRpb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKGF1ZGlvU3RyZWFtKVxuICAgIH1cblxuICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgdmFyIGJyb3dzZXIgPSBwYXJzZXIuZ2V0QnJvd3NlcigpXG4gICAgaWYgKG1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgIChicm93c2VyLm5hbWUgPT09ICdDaHJvbWUnIHx8IGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9taXVtJykgJiZcbiAgICAgIGJyb3dzZXIubWFqb3IgPT09IDM5KSB7XG4gICAgICBtb2RlID0gJ3NlbmRyZWN2J1xuICAgIH1cblxuICAgIGNhbGxiYWNrKClcbiAgfVxuXG4gIGlmIChtb2RlICE9PSAncmVjdm9ubHknICYmICF2aWRlb1N0cmVhbSAmJiAhYXVkaW9TdHJlYW0pIHtcbiAgICBmdW5jdGlvbiBnZXRNZWRpYShjb25zdHJhaW50cykge1xuICAgICAgaWYgKGNvbnN0cmFpbnRzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3RyYWludHMgPSBNRURJQV9DT05TVFJBSU5UU1xuICAgICAgfVxuXG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cykudGhlbihmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4gICAgICAgIHN0YXJ0KClcbiAgICAgIH0pLmNhdGNoKGNhbGxiYWNrKTtcbiAgICB9XG4gICAgaWYgKHNlbmRTb3VyY2UgPT09ICd3ZWJjYW0nKSB7XG4gICAgICBnZXRNZWRpYShtZWRpYUNvbnN0cmFpbnRzKVxuICAgIH0gZWxzZSB7XG4gICAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhzZW5kU291cmNlLCBmdW5jdGlvbiAoZXJyb3IsIGNvbnN0cmFpbnRzXykge1xuICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycm9yKVxuXG4gICAgICAgIGNvbnN0cmFpbnRzID0gW21lZGlhQ29uc3RyYWludHNdXG4gICAgICAgIGNvbnN0cmFpbnRzLnVuc2hpZnQoY29uc3RyYWludHNfKVxuICAgICAgICBnZXRNZWRpYShyZWN1cnNpdmUuYXBwbHkodW5kZWZpbmVkLCBjb25zdHJhaW50cykpXG4gICAgICB9LCBndWlkKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBzZXRUaW1lb3V0KHN0YXJ0LCAwKVxuICB9XG5cbiAgdGhpcy5vbignX2Rpc3Bvc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGxvY2FsVmlkZW8pIHtcbiAgICAgIGxvY2FsVmlkZW8ucGF1c2UoKVxuICAgICAgbG9jYWxWaWRlby5zcmNPYmplY3QgPSBudWxsXG4gICAgICBsb2NhbFZpZGVvLmxvYWQoKVxuICAgICAgLy9Vbm11dGUgbG9jYWwgdmlkZW8gaW4gY2FzZSB0aGUgdmlkZW8gdGFnIGlzIGxhdGVyIHVzZWQgZm9yIHJlbW90ZSB2aWRlb1xuICAgICAgbG9jYWxWaWRlby5tdXRlZCA9IGZhbHNlXG4gICAgfVxuICAgIGlmIChyZW1vdGVWaWRlbykge1xuICAgICAgcmVtb3RlVmlkZW8ucGF1c2UoKVxuICAgICAgcmVtb3RlVmlkZW8uc3JjT2JqZWN0ID0gbnVsbFxuICAgICAgcmVtb3RlVmlkZW8ubG9hZCgpXG4gICAgfVxuICAgIHNlbGYucmVtb3ZlQWxsTGlzdGVuZXJzKClcblxuICAgIGlmICh3aW5kb3cuY2FuY2VsQ2hvb3NlRGVza3RvcE1lZGlhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHdpbmRvdy5jYW5jZWxDaG9vc2VEZXNrdG9wTWVkaWEoZ3VpZClcbiAgICB9XG4gIH0pXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyLCBFdmVudEVtaXR0ZXIpXG5cbmZ1bmN0aW9uIGNyZWF0ZUVuYWJsZURlc2NyaXB0b3IodHlwZSkge1xuICB2YXIgbWV0aG9kID0gJ2dldCcgKyB0eXBlICsgJ1RyYWNrcydcblxuICByZXR1cm4ge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBbVG9Eb10gU2hvdWxkIHJldHVybiB1bmRlZmluZWQgaWYgbm90IGFsbCB0cmFja3MgaGF2ZSB0aGUgc2FtZSB2YWx1ZT9cblxuICAgICAgaWYgKCF0aGlzLnBlZXJDb25uZWN0aW9uKSByZXR1cm5cblxuICAgICAgdmFyIHN0cmVhbXMgPSB0aGlzLnBlZXJDb25uZWN0aW9uLmdldExvY2FsU3RyZWFtcygpXG4gICAgICBpZiAoIXN0cmVhbXMubGVuZ3RoKSByZXR1cm5cblxuICAgICAgZm9yICh2YXIgaSA9IDAsIHN0cmVhbTsgc3RyZWFtID0gc3RyZWFtc1tpXTsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFja3MgPSBzdHJlYW1bbWV0aG9kXSgpXG4gICAgICAgIGZvciAodmFyIGogPSAwLCB0cmFjazsgdHJhY2sgPSB0cmFja3Nbal07IGorKylcbiAgICAgICAgICBpZiAoIXRyYWNrLmVuYWJsZWQpIHJldHVybiBmYWxzZVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgIGZ1bmN0aW9uIHRyYWNrU2V0RW5hYmxlKHRyYWNrKSB7XG4gICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZVxuICAgICAgfVxuXG4gICAgICB0aGlzLnBlZXJDb25uZWN0aW9uLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goZnVuY3Rpb24gKHN0cmVhbSkge1xuICAgICAgICBzdHJlYW1bbWV0aG9kXSgpLmZvckVhY2godHJhY2tTZXRFbmFibGUpXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydGllcyhXZWJSdGNQZWVyLnByb3RvdHlwZSwge1xuICAnZW5hYmxlZCc6IHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuYXVkaW9FbmFibGVkICYmIHRoaXMudmlkZW9FbmFibGVkXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgdGhpcy5hdWRpb0VuYWJsZWQgPSB0aGlzLnZpZGVvRW5hYmxlZCA9IHZhbHVlXG4gICAgfVxuICB9LFxuICAnYXVkaW9FbmFibGVkJzogY3JlYXRlRW5hYmxlRGVzY3JpcHRvcignQXVkaW8nKSxcbiAgJ3ZpZGVvRW5hYmxlZCc6IGNyZWF0ZUVuYWJsZURlc2NyaXB0b3IoJ1ZpZGVvJylcbn0pXG5cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmdldExvY2FsU3RyZWFtID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gIGlmICh0aGlzLnBlZXJDb25uZWN0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMucGVlckNvbm5lY3Rpb24uZ2V0TG9jYWxTdHJlYW1zKClbaW5kZXggfHwgMF1cbiAgfVxufVxuXG5XZWJSdGNQZWVyLnByb3RvdHlwZS5nZXRSZW1vdGVTdHJlYW0gPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgaWYgKHRoaXMucGVlckNvbm5lY3Rpb24pIHtcbiAgICByZXR1cm4gdGhpcy5wZWVyQ29ubmVjdGlvbi5nZXRSZW1vdGVTdHJlYW1zKClbaW5kZXggfHwgMF1cbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUaGlzIG1ldGhvZCBmcmVlcyB0aGUgcmVzb3VyY2VzIHVzZWQgYnkgV2ViUnRjUGVlci5cbiAqXG4gKiBAZnVuY3Rpb24gbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyLnByb3RvdHlwZS5kaXNwb3NlXG4gKi9cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmRpc3Bvc2UgPSBmdW5jdGlvbiAoKSB7XG4gIGxvZ2dlci5kZWJ1ZygnRGlzcG9zaW5nIFdlYlJ0Y1BlZXInKVxuXG4gIHZhciBwYyA9IHRoaXMucGVlckNvbm5lY3Rpb25cbiAgLy92YXIgZGMgPSB0aGlzLmRhdGFDaGFubmVsXG4gIHRyeSB7XG4gICAgLyppZiAoZGMpIHtcbiAgICAgIGlmIChkYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHJldHVyblxuXG4gICAgICBkYy5jbG9zZSgpXG4gICAgfSovXG5cbiAgICBpZiAocGMpIHtcbiAgICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHJldHVyblxuXG4gICAgICBwYy5nZXRMb2NhbFN0cmVhbXMoKS5mb3JFYWNoKHN0cmVhbVN0b3ApXG5cbiAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAvLyBpZih2aWRlb1N0cmVhbSkgcGMucmVtb3ZlU3RyZWFtKHZpZGVvU3RyZWFtKTtcbiAgICAgIC8vIGlmKGF1ZGlvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0oYXVkaW9TdHJlYW0pO1xuXG4gICAgICBwYy5jbG9zZSgpXG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIud2FybignRXhjZXB0aW9uIGRpc3Bvc2luZyB3ZWJydGMgcGVlciAnICsgZXJyKVxuICB9XG5cbiAgdGhpcy5lbWl0KCdfZGlzcG9zZScpXG59XG5cbi8vXG4vLyBTcGVjaWFsaXplZCBjaGlsZCBjbGFzc2VzXG4vL1xuXG5mdW5jdGlvbiBXZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgY2FsbGJhY2spIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFdlYlJ0Y1BlZXJSZWN2b25seSkpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zLCBjYWxsYmFjaylcbiAgfVxuXG4gIFdlYlJ0Y1BlZXJSZWN2b25seS5zdXBlcl8uY2FsbCh0aGlzLCAncmVjdm9ubHknLCBvcHRpb25zLCBjYWxsYmFjaylcbn1cbmluaGVyaXRzKFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlcilcblxuZnVuY3Rpb24gV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBXZWJSdGNQZWVyU2VuZG9ubHkpKSB7XG4gICAgcmV0dXJuIG5ldyBXZWJSdGNQZWVyU2VuZG9ubHkob3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyU2VuZG9ubHkuc3VwZXJfLmNhbGwodGhpcywgJ3NlbmRvbmx5Jywgb3B0aW9ucywgY2FsbGJhY2spXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXIpXG5cbmZ1bmN0aW9uIFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlclNlbmRyZWN2KSkge1xuICAgIHJldHVybiBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGNhbGxiYWNrKVxuICB9XG5cbiAgV2ViUnRjUGVlclNlbmRyZWN2LnN1cGVyXy5jYWxsKHRoaXMsICdzZW5kcmVjdicsIG9wdGlvbnMsIGNhbGxiYWNrKVxufVxuaW5oZXJpdHMoV2ViUnRjUGVlclNlbmRyZWN2LCBXZWJSdGNQZWVyKVxuXG5mdW5jdGlvbiBoYXJrVXRpbHMoc3RyZWFtLCBvcHRpb25zKSB7XG4gIHJldHVybiBoYXJrKHN0cmVhbSwgb3B0aW9ucyk7XG59XG5cbmV4cG9ydHMuYnVmZmVyaXplQ2FuZGlkYXRlcyA9IGJ1ZmZlcml6ZUNhbmRpZGF0ZXNcblxuZXhwb3J0cy5XZWJSdGNQZWVyUmVjdm9ubHkgPSBXZWJSdGNQZWVyUmVjdm9ubHlcbmV4cG9ydHMuV2ViUnRjUGVlclNlbmRvbmx5ID0gV2ViUnRjUGVlclNlbmRvbmx5XG5leHBvcnRzLldlYlJ0Y1BlZXJTZW5kcmVjdiA9IFdlYlJ0Y1BlZXJTZW5kcmVjdlxuZXhwb3J0cy5oYXJrID0gaGFya1V0aWxzXG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBUaGlzIG1vZHVsZSBjb250YWlucyBhIHNldCBvZiByZXVzYWJsZSBjb21wb25lbnRzIHRoYXQgaGF2ZSBiZWVuIGZvdW5kIHVzZWZ1bFxuICogZHVyaW5nIHRoZSBkZXZlbG9wbWVudCBvZiB0aGUgV2ViUlRDIGFwcGxpY2F0aW9ucyB3aXRoIEt1cmVudG8uXG4gKiBcbiAqIEBtb2R1bGUga3VyZW50b1V0aWxzXG4gKiBcbiAqIEBjb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICogQGxpY2Vuc2UgQUx2MlxuICovXG5cbnZhciBXZWJSdGNQZWVyID0gcmVxdWlyZSgnLi9XZWJSdGNQZWVyJyk7XG5cbmV4cG9ydHMuV2ViUnRjUGVlciA9IFdlYlJ0Y1BlZXI7XG4iLCIvLyBMYXN0IHRpbWUgdXBkYXRlZCBvbiBEZWNlbWJlciAxMywgMjAxN1xuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYoc291cmNlSWQgPT0gJ2ZpcmVmb3gnKSB7XG4gICAgICAgIG5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzLCBvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2UgbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMsIG9uU3VjY2Vzcywgb25GYWlsdXJlKTtcbn0pO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhlcnJvciwgc291cmNlSWQpIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmIChzb3VyY2VJZCkge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMudmlkZW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2NyZWVuX2NvbnN0cmFpbnRzO1xufVxuXG52YXIgaWZyYW1lO1xuXG5mdW5jdGlvbiBwb3N0R2V0U291cmNlSWRNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldFNvdXJjZUlkTWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGNhcHR1cmVTb3VyY2VJZDogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmZ1bmN0aW9uIGxvYWRJRnJhbWUobG9hZENhbGxiYWNrKSB7XG4gICAgaWYgKGlmcmFtZSkge1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO1xuICAgIGlmcmFtZS5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmcmFtZS5pc0xvYWRlZCA9IHRydWU7XG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgIH07XG4gICAgaWZyYW1lLnNyYyA9ICdodHRwczovL3d3dy53ZWJydGMtZXhwZXJpbWVudC5jb20vZ2V0U291cmNlSWQvJztcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbn07XG5cbmZ1bmN0aW9uIHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzOiB0cnVlXG4gICAgfSwgJyonKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5JZCA9IGdldFNjcmVlbklkOyIsIi8vIGdsb2JhbCB2YXJpYWJsZXNcbnZhciBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xudmFyIHNjcmVlbkNhbGxiYWNrO1xudmFyIGlzRmlyZWZveCA9IHR5cGVvZiB3aW5kb3cuSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnO1xudmFyIGlzT3BlcmEgPSAhIXdpbmRvdy5vcGVyYSB8fCBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJyBPUFIvJykgPj0gMDtcbnZhciBpc0Nocm9tZSA9ICEhd2luZG93LmNocm9tZSAmJiAhaXNPcGVyYTtcblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBpZiAoZXZlbnQub3JpZ2luICE9IHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBvbk1lc3NhZ2VDYWxsYmFjayhldmVudC5kYXRhKTtcbn0pO1xuXG4vLyBhbmQgdGhlIGZ1bmN0aW9uIHRoYXQgaGFuZGxlcyByZWNlaXZlZCBtZXNzYWdlc1xuZnVuY3Rpb24gb25NZXNzYWdlQ2FsbGJhY2soZGF0YSkge1xuICAgIC8vIFwiY2FuY2VsXCIgYnV0dG9uIGlzIGNsaWNrZWRcbiAgICBpZiAoZGF0YSA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJykge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InO1xuICAgICAgICBpZiAoc2NyZWVuQ2FsbGJhY2spXG4gICAgICAgICAgICByZXR1cm4gc2NyZWVuQ2FsbGJhY2soJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gbm90aWZpZWQgaGlzIHByZXNlbmNlXG4gICAgaWYgKGRhdGEgPT0gJ3J0Y211bHRpY29ubmVjdGlvbi1leHRlbnNpb24tbG9hZGVkJykge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdkZXNrdG9wJztcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIHNoYXJlZCB0ZW1wIHNvdXJjZUlkXG4gICAgaWYgKGRhdGEuc291cmNlSWQgJiYgc2NyZWVuQ2FsbGJhY2spIHtcbiAgICAgICAgc2NyZWVuQ2FsbGJhY2soc291cmNlSWQgPSBkYXRhLnNvdXJjZUlkKTtcbiAgICB9XG59XG5cbi8vIHRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGNoZWNrIGlmIGNocm9tZSBleHRlbnNpb24gaXMgaW5zdGFsbGVkICYgZW5hYmxlZC5cbmZ1bmN0aW9uIGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlKGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGZhbHNlKTtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKVxuICAgICAgICByZXR1cm4gY2FsbGJhY2soJ2lzRmlyZWZveCcpO1xuICAgIC8vIGFzayBleHRlbnNpb24gaWYgaXQgaXMgYXZhaWxhYmxlXG4gICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICBjYWxsYmFjaygndW5hdmFpbGFibGUnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBjYWxsYmFjaygnYXZhaWxhYmxlJyk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnYWpoaWZkZGlta2FwZ2NpZmdjb2RtbWZkbGtuYWhmZmsnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhleHRlbnNpb25pZCA9PSBleHRlbnNpb25pZCA/ICdpbnN0YWxsZWQtZW5hYmxlZCcgOiAnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIH0sIDIwMDApO1xuICAgIH07XG4gICAgaW1hZ2Uub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2FsbGJhY2soJ25vdC1pbnN0YWxsZWQnKTtcbiAgICB9O1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaykge1xuICAgIHNvdXJjZUlkID0gJyc7XG4gICAgdmFyIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyA9IHtcbiAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICBtZWRpYVNvdXJjZTogJ3dpbmRvdydcbiAgICB9O1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMpO1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IGRlZmluZXMgZ2V0VXNlck1lZGlhIGNvbnN0cmFpbnRzXG4gICAgLy8gdGhhdCB3aWxsIGJlIHVzZWQgdG8gY2FwdHVyZSBjb250ZW50IG9mIHNjcmVlblxuICAgIHZhciBzY3JlZW5fY29uc3RyYWludHMgPSB7XG4gICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGNocm9tZU1lZGlhU291cmNlLFxuICAgICAgICAgICAgbWF4V2lkdGg6IHNjcmVlbi53aWR0aCA+IDE5MjAgPyBzY3JlZW4ud2lkdGggOiAxOTIwLFxuICAgICAgICAgICAgbWF4SGVpZ2h0OiBzY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHNjcmVlbi5oZWlnaHQgOiAxMDgwXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbmFsOiBbXVxuICAgIH07XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgdmVyaWZpZXMgY2hyb21lIGV4dGVuc2lvbiBhdmFpbGFiaWxpdHlcbiAgICAvLyBpZiBpbnN0YWxsZWQgYW5kIGF2YWlsYWJsZSB0aGVuIGl0IHdpbGwgaW52b2tlIGV4dGVuc2lvbiBBUElcbiAgICAvLyBvdGhlcndpc2UgaXQgd2lsbCBmYWxsYmFjayB0byBjb21tYW5kLWxpbmUgYmFzZWQgc2NyZWVuIGNhcHR1cmluZyBBUElcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnICYmICFzb3VyY2VJZCkge1xuICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG4gICAgLy8gbm93IGludm9raW5nIG5hdGl2ZSBnZXRVc2VyTWVkaWEgQVBJXG4gICAgY2FsbGJhY2sobnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50cyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzO1xuZXhwb3J0cy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSA9IGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG5leHBvcnRzLmdldFNvdXJjZUlkID0gZ2V0U291cmNlSWQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vLyB0c2xpbnQ6ZGlzYWJsZTpuby1zdHJpbmctbGl0ZXJhbFxuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0ICogYXMgYWRhcHRlciBmcm9tICd3ZWJydGMtYWRhcHRlcic7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5leHBvcnQgY2xhc3MgV2ViUnRjU3RhdHMge1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0VuYWJsZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzSW50ZXJ2YWxJZDogTm9kZUpTLlRpbWVyO1xuICAgIHByaXZhdGUgc3RhdHNJbnRlcnZhbCA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBpbmJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvdXRib3VuZDoge1xuICAgICAgICAgICAgYXVkaW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogMCxcbiAgICAgICAgICAgICAgICBuYWNrQ291bnQ6IDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7IH1cblxuICAgIHB1YmxpYyBpc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2VsYXN0ZXN0LWluc3RydW1lbnRhdGlvbicpO1xuXG4gICAgICAgIGlmIChlbGFzdGVzdEluc3RydW1lbnRhdGlvbikge1xuICAgICAgICAgICAgLy8gRWxhc1Rlc3QgaW5zdHJ1bWVudGF0aW9uIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnN0cnVtZW50YXRpb24gPSBKU09OLnBhcnNlKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHNJbnRlcnZhbCA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaW50ZXJ2YWw7ICAvLyBJbnRlcnZhbCBpbiBzZWNvbmRzXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignbG9jYWxTdG9yYWdlIGl0ZW06ICcgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1dlYlJ0YyBzdGF0cyBub3QgZW5hYmxlZCcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wV2ViUnRjU3RhdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHNlbmRQb3N0ID0gKGpzb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGh0dHA6IFhNTEh0dHBSZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICBjb25zdCB1cmw6IHN0cmluZyA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaHR0cEVuZHBvaW50O1xuICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgdXJsLCB0cnVlKTtcblxuICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKCdDb250ZW50LXR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuXG4gICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHsgLy8gQ2FsbCBhIGZ1bmN0aW9uIHdoZW4gdGhlIHN0YXRlIGNoYW5nZXMuXG4gICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCAmJiBodHRwLnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdXZWJSdGMgc3RhdHMgc3VjY2Vzc2Z1bGx5IHNlbnQgdG8gJyArIHVybCArICcgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaHR0cC5zZW5kKGpzb24pO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGYgPSAoc3RhdHMpID0+IHtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBzdGF0cy5mb3JFYWNoKChzdGF0KSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGpzb24gPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoKHN0YXQudHlwZSA9PT0gJ2luYm91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IG91dGJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5uYWNrQ291bnQgIT09IG51bGwgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5yZW1vdGVJZC5zdGFydHNXaXRoKCdpbmJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgaml0ID0gc3RhdC5qaXR0ZXIgKiAxMDAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IChzdGF0LmJ5dGVzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogaml0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6ICdtcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snbmFja0NvdW50J10gPSAoc3RhdC5uYWNrQ291bnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ25hY2tDb3VudCddID0gJ3BhY2tldHMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQubmFja0NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCA9IHN0YXQucGFja2V0c1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKHN0YXQudHlwZSA9PT0gJ291dGJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBpbmJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ291dGJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX291dGJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IChzdGF0LnBhY2tldHNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQgPSBzdGF0LmZyYW1lc0VuY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQgPSBzdGF0LnBhY2tldHNTZW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhzdGF0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogc3RhdC5nb29nSml0dGVyQnVmZmVyTXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lmdvb2dOYWNrc1NlbnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lmdvb2dOYWNrc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCdieXRlc1NlbnQnIGluIHN0YXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdXRib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5nZXRTdGF0c0Fnbm9zdGljKHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCksIGYsIChlcnJvcikgPT4geyBjb25zb2xlLmxvZyhlcnJvcik7IH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2goKHJlcG9ydCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RhbmRhcmRTdGF0cyA9IHtcbiAgICAgICAgICAgICAgICBpZDogcmVwb3J0LmlkLFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogcmVwb3J0LnRpbWVzdGFtcCxcbiAgICAgICAgICAgICAgICB0eXBlOiByZXBvcnQudHlwZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcG9ydC5uYW1lcygpLmZvckVhY2goKG5hbWUpID0+IHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFN0YXRzW25hbWVdID0gcmVwb3J0LnN0YXQobmFtZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHN0YW5kYXJkUmVwb3J0W3N0YW5kYXJkU3RhdHMuaWRdID0gc3RhbmRhcmRTdGF0cztcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHN0YW5kYXJkUmVwb3J0O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0U3RhdHNBZ25vc3RpYyhwYywgc3VjY2Vzc0NiLCBmYWlsdXJlQ2IpIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIGdldFN0YXRzIHRha2VzIGFyZ3MgaW4gZGlmZmVyZW50IG9yZGVyIGluIENocm9tZSBhbmQgRmlyZWZveFxuICAgICAgICAgICAgcmV0dXJuIHBjLmdldFN0YXRzKG51bGwsIChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcG9ydCA9IHRoaXMuc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYihyZXBvcnQpO1xuICAgICAgICAgICAgfSwgZmFpbHVyZUNiKTtcbiAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIEluIENocm9tZSwgdGhlIGZpcnN0IHR3byBhcmd1bWVudHMgYXJlIHJldmVyc2VkXG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBudWxsLCBmYWlsdXJlQ2IpO1xuICAgICAgICB9XG4gICAgfVxuXG59Il19 diff --git a/openvidu-insecure-js/web/openvidu-browser-2.2.0.js b/openvidu-insecure-js/web/openvidu-browser-2.2.0.js new file mode 100644 index 00000000..e57248f3 --- /dev/null +++ b/openvidu-insecure-js/web/openvidu-browser-2.2.0.js @@ -0,0 +1,7371 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Unhandled "error" event. (' + er + ')'); + err.context = er; + throw err; + } + return false; + } + + handler = events[type]; + + if (!handler) + return false; + + var isFn = typeof handler === 'function'; + len = arguments.length; + switch (len) { + // fast cases + case 1: + emitNone(handler, isFn, this); + break; + case 2: + emitOne(handler, isFn, this, arguments[1]); + break; + case 3: + emitTwo(handler, isFn, this, arguments[1], arguments[2]); + break; + case 4: + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + emitMany(handler, isFn, this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = target._events; + if (!events) { + events = target._events = objectCreate(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (!existing) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + } else { + // If we've already got an array, just append. + if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + } + + // Check for listener leak + if (!existing.warned) { + m = $getMaxListeners(target); + if (m && m > 0 && existing.length > m) { + existing.warned = true; + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' "' + String(type) + '" listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit.'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + if (typeof console === 'object' && console.warn) { + console.warn('%s: %s', w.name, w.message); + } + } + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + switch (arguments.length) { + case 0: + return this.listener.call(this.target); + case 1: + return this.listener.call(this.target, arguments[0]); + case 2: + return this.listener.call(this.target, arguments[0], arguments[1]); + case 3: + return this.listener.call(this.target, arguments[0], arguments[1], + arguments[2]); + default: + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) + args[i] = arguments[i]; + this.listener.apply(this.target, args); + } + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = bind.call(onceWrapper, state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = this._events; + if (!events) + return this; + + list = events[type]; + if (!list) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else + spliceOne(list, position); + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (!events) + return this; + + // not listening for removeListener, no need to emit + if (!events.removeListener) { + if (arguments.length === 0) { + this._events = objectCreate(null); + this._eventsCount = 0; + } else if (events[type]) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = objectKeys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = objectCreate(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (!events) + return []; + + var evlistener = events[type]; + if (!evlistener) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function objectCreatePolyfill(proto) { + var F = function() {}; + F.prototype = proto; + return new F; +} +function objectKeysPolyfill(obj) { + var keys = []; + for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { + keys.push(k); + } + return k; +} +function functionBindPolyfill(context) { + var fn = this; + return function () { + return fn.apply(context, arguments); + }; +} + +},{}],2:[function(require,module,exports){ +/* jshint node: true */ +'use strict'; + +var normalice = require('normalice'); + +/** + # freeice + + The `freeice` module is a simple way of getting random STUN or TURN server + for your WebRTC application. The list of servers (just STUN at this stage) + were sourced from this [gist](https://gist.github.com/zziuni/3741933). + + ## Example Use + + The following demonstrates how you can use `freeice` with + [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): + + <<< examples/quickconnect.js + + As the `freeice` module generates ice servers in a list compliant with the + WebRTC spec you will be able to use it with raw `RTCPeerConnection` + constructors and other WebRTC libraries. + + ## Hey, don't use my STUN/TURN server! + + If for some reason your free STUN or TURN server ends up in the + list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or + [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) + that is used in this module, you can feel + free to open an issue on this repository and those servers will be removed + within 24 hours (or sooner). This is the quickest and probably the most + polite way to have something removed (and provides us some visibility + if someone opens a pull request requesting that a server is added). + + ## Please add my server! + + If you have a server that you wish to add to the list, that's awesome! I'm + sure I speak on behalf of a whole pile of WebRTC developers who say thanks. + To get it into the list, feel free to either open a pull request or if you + find that process a bit daunting then just create an issue requesting + the addition of the server (make sure you provide all the details, and if + you have a Terms of Service then including that in the PR/issue would be + awesome). + + ## I know of a free server, can I add it? + + Sure, if you do your homework and make sure it is ok to use (I'm currently + in the process of reviewing the terms of those STUN servers included from + the original list). If it's ok to go, then please see the previous entry + for how to add it. + + ## Current List of Servers + + * current as at the time of last `README.md` file generation + + ### STUN + + <<< stun.json + + ### TURN + + <<< turn.json + +**/ + +var freeice = module.exports = function(opts) { + // if a list of servers has been provided, then use it instead of defaults + var servers = { + stun: (opts || {}).stun || require('./stun.json'), + turn: (opts || {}).turn || require('./turn.json') + }; + + var stunCount = (opts || {}).stunCount || 2; + var turnCount = (opts || {}).turnCount || 0; + var selected; + + function getServers(type, count) { + var out = []; + var input = [].concat(servers[type]); + var idx; + + while (input.length && out.length < count) { + idx = (Math.random() * input.length) | 0; + out = out.concat(input.splice(idx, 1)); + } + + return out.map(function(url) { + //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up + if ((typeof url !== 'string') && (! (url instanceof String))) { + return url; + } else { + return normalice(type + ':' + url); + } + }); + } + + // add stun servers + selected = [].concat(getServers('stun', stunCount)); + + if (turnCount) { + selected = selected.concat(getServers('turn', turnCount)); + } + + return selected; +}; + +},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){ +module.exports=[ + "stun.l.google.com:19302", + "stun1.l.google.com:19302", + "stun2.l.google.com:19302", + "stun3.l.google.com:19302", + "stun4.l.google.com:19302", + "stun.ekiga.net", + "stun.ideasip.com", + "stun.schlund.de", + "stun.stunprotocol.org:3478", + "stun.voiparound.com", + "stun.voipbuster.com", + "stun.voipstunt.com", + "stun.voxgratia.org", + "stun.services.mozilla.com" +] + +},{}],4:[function(require,module,exports){ +module.exports=[] + +},{}],5:[function(require,module,exports){ +var WildEmitter = require('wildemitter'); + +function getMaxVolume (analyser, fftBins) { + var maxVolume = -Infinity; + analyser.getFloatFrequencyData(fftBins); + + for(var i=4, ii=fftBins.length; i < ii; i++) { + if (fftBins[i] > maxVolume && fftBins[i] < 0) { + maxVolume = fftBins[i]; + } + }; + + return maxVolume; +} + + +var audioContextType; +if (typeof window !== 'undefined') { + audioContextType = window.AudioContext || window.webkitAudioContext; +} +// use a single audio context due to hardware limits +var audioContext = null; +module.exports = function(stream, options) { + var harker = new WildEmitter(); + + + // make it not break in non-supported browsers + if (!audioContextType) return harker; + + //Config + var options = options || {}, + smoothing = (options.smoothing || 0.1), + interval = (options.interval || 50), + threshold = options.threshold, + play = options.play, + history = options.history || 10, + running = true; + + //Setup Audio Context + if (!audioContext) { + audioContext = new audioContextType(); + } + var sourceNode, fftBins, analyser; + + analyser = audioContext.createAnalyser(); + analyser.fftSize = 512; + analyser.smoothingTimeConstant = smoothing; + fftBins = new Float32Array(analyser.frequencyBinCount); + + if (stream.jquery) stream = stream[0]; + if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { + //Audio Tag + sourceNode = audioContext.createMediaElementSource(stream); + if (typeof play === 'undefined') play = true; + threshold = threshold || -50; + } else { + //WebRTC Stream + sourceNode = audioContext.createMediaStreamSource(stream); + threshold = threshold || -50; + } + + sourceNode.connect(analyser); + if (play) analyser.connect(audioContext.destination); + + harker.speaking = false; + + harker.suspend = function() { + audioContext.suspend(); + } + harker.resume = function() { + audioContext.resume(); + } + Object.defineProperty(harker, 'state', { get: function() { + return audioContext.state; + }}); + audioContext.onstatechange = function() { + harker.emit('state_change', audioContext.state); + } + + harker.setThreshold = function(t) { + threshold = t; + }; + + harker.setInterval = function(i) { + interval = i; + }; + + harker.stop = function() { + running = false; + harker.emit('volume_change', -100, threshold); + if (harker.speaking) { + harker.speaking = false; + harker.emit('stopped_speaking'); + } + analyser.disconnect(); + sourceNode.disconnect(); + }; + harker.speakingHistory = []; + for (var i = 0; i < history; i++) { + harker.speakingHistory.push(0); + } + + // Poll the analyser node to determine if speaking + // and emit events if changed + var looper = function() { + setTimeout(function() { + + //check if stop has been called + if(!running) { + return; + } + + var currentVolume = getMaxVolume(analyser, fftBins); + + harker.emit('volume_change', currentVolume, threshold); + + var history = 0; + if (currentVolume > threshold && !harker.speaking) { + // trigger quickly, short history + for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { + history += harker.speakingHistory[i]; + } + if (history >= 2) { + harker.speaking = true; + harker.emit('speaking'); + } + } else if (currentVolume < threshold && harker.speaking) { + for (var i = 0; i < harker.speakingHistory.length; i++) { + history += harker.speakingHistory[i]; + } + if (history == 0) { + harker.speaking = false; + harker.emit('stopped_speaking'); + } + } + harker.speakingHistory.shift(); + harker.speakingHistory.push(0 + (currentVolume > threshold)); + + looper(); + }, interval); + }; + looper(); + + + return harker; +} + +},{"wildemitter":14}],6:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],7:[function(require,module,exports){ +/** + # normalice + + Normalize an ice server configuration object (or plain old string) into a format + that is usable in all browsers supporting WebRTC. Primarily this module is designed + to help with the transition of the `url` attribute of the configuration object to + the `urls` attribute. + + ## Example Usage + + <<< examples/simple.js + +**/ + +var protocols = [ + 'stun:', + 'turn:' +]; + +module.exports = function(input) { + var url = (input || {}).url || input; + var protocol; + var parts; + var output = {}; + + // if we don't have a string url, then allow the input to passthrough + if (typeof url != 'string' && (! (url instanceof String))) { + return input; + } + + // trim the url string, and convert to an array + url = url.trim(); + + // if the protocol is not known, then passthrough + protocol = protocols[protocols.indexOf(url.slice(0, 5))]; + if (! protocol) { + return input; + } + + // now let's attack the remaining url parts + url = url.slice(5); + parts = url.split('@'); + + output.username = input.username; + output.credential = input.credential; + // if we have an authentication part, then set the credentials + if (parts.length > 1) { + url = parts[1]; + parts = parts[0].split(':'); + + // add the output credential and username + output.username = parts[0]; + output.credential = (input || {}).credential || parts[1] || ''; + } + + output.url = protocol + url; + output.urls = [ output.url ]; + + return output; +}; + +},{}],8:[function(require,module,exports){ +(function (global){ +/*! + * Platform.js + * Copyright 2014-2018 Benjamin Tan + * Copyright 2011-2013 John-David Dalton + * Available under MIT license + */ +;(function() { + 'use strict'; + + /** Used to determine if values are of the language type `Object`. */ + var objectTypes = { + 'function': true, + 'object': true + }; + + /** Used as a reference to the global object. */ + var root = (objectTypes[typeof window] && window) || this; + + /** Backup possible global object. */ + var oldRoot = root; + + /** Detect free variable `exports`. */ + var freeExports = objectTypes[typeof exports] && exports; + + /** Detect free variable `module`. */ + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + + /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ + var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; + if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { + root = freeGlobal; + } + + /** + * Used as the maximum length of an array-like object. + * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) + * for more details. + */ + var maxSafeInteger = Math.pow(2, 53) - 1; + + /** Regular expression to detect Opera. */ + var reOpera = /\bOpera/; + + /** Possible global object. */ + var thisBinding = this; + + /** Used for native method references. */ + var objectProto = Object.prototype; + + /** Used to check for own properties of an object. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to resolve the internal `[[Class]]` of values. */ + var toString = objectProto.toString; + + /*--------------------------------------------------------------------------*/ + + /** + * Capitalizes a string value. + * + * @private + * @param {string} string The string to capitalize. + * @returns {string} The capitalized string. + */ + function capitalize(string) { + string = String(string); + return string.charAt(0).toUpperCase() + string.slice(1); + } + + /** + * A utility function to clean up the OS name. + * + * @private + * @param {string} os The OS name to clean up. + * @param {string} [pattern] A `RegExp` pattern matching the OS name. + * @param {string} [label] A label for the OS. + */ + function cleanupOS(os, pattern, label) { + // Platform tokens are defined at: + // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + var data = { + '10.0': '10', + '6.4': '10 Technical Preview', + '6.3': '8.1', + '6.2': '8', + '6.1': 'Server 2008 R2 / 7', + '6.0': 'Server 2008 / Vista', + '5.2': 'Server 2003 / XP 64-bit', + '5.1': 'XP', + '5.01': '2000 SP1', + '5.0': '2000', + '4.0': 'NT', + '4.90': 'ME' + }; + // Detect Windows version from platform tokens. + if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && + (data = data[/[\d.]+$/.exec(os)])) { + os = 'Windows ' + data; + } + // Correct character case and cleanup string. + os = String(os); + + if (pattern && label) { + os = os.replace(RegExp(pattern, 'i'), label); + } + + os = format( + os.replace(/ ce$/i, ' CE') + .replace(/\bhpw/i, 'web') + .replace(/\bMacintosh\b/, 'Mac OS') + .replace(/_PowerPC\b/i, ' OS') + .replace(/\b(OS X) [^ \d]+/i, '$1') + .replace(/\bMac (OS X)\b/, '$1') + .replace(/\/(\d)/, ' $1') + .replace(/_/g, '.') + .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') + .replace(/\bx86\.64\b/gi, 'x86_64') + .replace(/\b(Windows Phone) OS\b/, '$1') + .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') + .split(' on ')[0] + ); + + return os; + } + + /** + * An iteration utility for arrays and objects. + * + * @private + * @param {Array|Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + */ + function each(object, callback) { + var index = -1, + length = object ? object.length : 0; + + if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { + while (++index < length) { + callback(object[index], index, object); + } + } else { + forOwn(object, callback); + } + } + + /** + * Trim and conditionally capitalize string values. + * + * @private + * @param {string} string The string to format. + * @returns {string} The formatted string. + */ + function format(string) { + string = trim(string); + return /^(?:webOS|i(?:OS|P))/.test(string) + ? string + : capitalize(string); + } + + /** + * Iterates over an object's own properties, executing the `callback` for each. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function executed per own property. + */ + function forOwn(object, callback) { + for (var key in object) { + if (hasOwnProperty.call(object, key)) { + callback(object[key], key, object); + } + } + } + + /** + * Gets the internal `[[Class]]` of a value. + * + * @private + * @param {*} value The value. + * @returns {string} The `[[Class]]`. + */ + function getClassOf(value) { + return value == null + ? capitalize(value) + : toString.call(value).slice(8, -1); + } + + /** + * Host objects can return type values that are different from their actual + * data type. The objects we are concerned with usually return non-primitive + * types of "object", "function", or "unknown". + * + * @private + * @param {*} object The owner of the property. + * @param {string} property The property to check. + * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. + */ + function isHostType(object, property) { + var type = object != null ? typeof object[property] : 'number'; + return !/^(?:boolean|number|string|undefined)$/.test(type) && + (type == 'object' ? !!object[property] : true); + } + + /** + * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. + * + * @private + * @param {string} string The string to qualify. + * @returns {string} The qualified string. + */ + function qualify(string) { + return String(string).replace(/([ -])(?!$)/g, '$1?'); + } + + /** + * A bare-bones `Array#reduce` like utility function. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {*} The accumulated result. + */ + function reduce(array, callback) { + var accumulator = null; + each(array, function(value, index) { + accumulator = callback(accumulator, value, index, array); + }); + return accumulator; + } + + /** + * Removes leading and trailing whitespace from a string. + * + * @private + * @param {string} string The string to trim. + * @returns {string} The trimmed string. + */ + function trim(string) { + return String(string).replace(/^ +| +$/g, ''); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a new platform object. + * + * @memberOf platform + * @param {Object|string} [ua=navigator.userAgent] The user agent string or + * context object. + * @returns {Object} A platform object. + */ + function parse(ua) { + + /** The environment context object. */ + var context = root; + + /** Used to flag when a custom context is provided. */ + var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; + + // Juggle arguments. + if (isCustomContext) { + context = ua; + ua = null; + } + + /** Browser navigator object. */ + var nav = context.navigator || {}; + + /** Browser user agent string. */ + var userAgent = nav.userAgent || ''; + + ua || (ua = userAgent); + + /** Used to flag when `thisBinding` is the [ModuleScope]. */ + var isModuleScope = isCustomContext || thisBinding == oldRoot; + + /** Used to detect if browser is like Chrome. */ + var likeChrome = isCustomContext + ? !!nav.likeChrome + : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); + + /** Internal `[[Class]]` value shortcuts. */ + var objectClass = 'Object', + airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', + enviroClass = isCustomContext ? objectClass : 'Environment', + javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), + phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; + + /** Detect Java environments. */ + var java = /\bJava/.test(javaClass) && context.java; + + /** Detect Rhino. */ + var rhino = java && getClassOf(context.environment) == enviroClass; + + /** A character to represent alpha. */ + var alpha = java ? 'a' : '\u03b1'; + + /** A character to represent beta. */ + var beta = java ? 'b' : '\u03b2'; + + /** Browser document object. */ + var doc = context.document || {}; + + /** + * Detect Opera browser (Presto-based). + * http://www.howtocreate.co.uk/operaStuff/operaObject.html + * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini + */ + var opera = context.operamini || context.opera; + + /** Opera `[[Class]]`. */ + var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) + ? operaClass + : (opera = null); + + /*------------------------------------------------------------------------*/ + + /** Temporary variable used over the script's lifetime. */ + var data; + + /** The CPU architecture. */ + var arch = ua; + + /** Platform description array. */ + var description = []; + + /** Platform alpha/beta indicator. */ + var prerelease = null; + + /** A flag to indicate that environment features should be used to resolve the platform. */ + var useFeatures = ua == userAgent; + + /** The browser/environment version. */ + var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); + + /** A flag to indicate if the OS ends with "/ Version" */ + var isSpecialCasedOS; + + /* Detectable layout engines (order is important). */ + var layout = getLayout([ + { 'label': 'EdgeHTML', 'pattern': 'Edge' }, + 'Trident', + { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, + 'iCab', + 'Presto', + 'NetFront', + 'Tasman', + 'KHTML', + 'Gecko' + ]); + + /* Detectable browser names (order is important). */ + var name = getName([ + 'Adobe AIR', + 'Arora', + 'Avant Browser', + 'Breach', + 'Camino', + 'Electron', + 'Epiphany', + 'Fennec', + 'Flock', + 'Galeon', + 'GreenBrowser', + 'iCab', + 'Iceweasel', + 'K-Meleon', + 'Konqueror', + 'Lunascape', + 'Maxthon', + { 'label': 'Microsoft Edge', 'pattern': 'Edge' }, + 'Midori', + 'Nook Browser', + 'PaleMoon', + 'PhantomJS', + 'Raven', + 'Rekonq', + 'RockMelt', + { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' }, + 'SeaMonkey', + { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Sleipnir', + 'SlimBrowser', + { 'label': 'SRWare Iron', 'pattern': 'Iron' }, + 'Sunrise', + 'Swiftfox', + 'Waterfox', + 'WebPositive', + 'Opera Mini', + { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, + 'Opera', + { 'label': 'Opera', 'pattern': 'OPR' }, + 'Chrome', + { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, + { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, + { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' }, + { 'label': 'IE', 'pattern': 'IEMobile' }, + { 'label': 'IE', 'pattern': 'MSIE' }, + 'Safari' + ]); + + /* Detectable products (order is important). */ + var product = getProduct([ + { 'label': 'BlackBerry', 'pattern': 'BB10' }, + 'BlackBerry', + { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, + { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, + { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, + { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, + { 'label': 'Galaxy S5', 'pattern': 'SM-G900' }, + { 'label': 'Galaxy S6', 'pattern': 'SM-G920' }, + { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' }, + { 'label': 'Galaxy S7', 'pattern': 'SM-G930' }, + { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' }, + 'Google TV', + 'Lumia', + 'iPad', + 'iPod', + 'iPhone', + 'Kindle', + { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Nexus', + 'Nook', + 'PlayBook', + 'PlayStation Vita', + 'PlayStation', + 'TouchPad', + 'Transformer', + { 'label': 'Wii U', 'pattern': 'WiiU' }, + 'Wii', + 'Xbox One', + { 'label': 'Xbox 360', 'pattern': 'Xbox' }, + 'Xoom' + ]); + + /* Detectable manufacturers. */ + var manufacturer = getManufacturer({ + 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, + 'Archos': {}, + 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, + 'Asus': { 'Transformer': 1 }, + 'Barnes & Noble': { 'Nook': 1 }, + 'BlackBerry': { 'PlayBook': 1 }, + 'Google': { 'Google TV': 1, 'Nexus': 1 }, + 'HP': { 'TouchPad': 1 }, + 'HTC': {}, + 'LG': {}, + 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, + 'Motorola': { 'Xoom': 1 }, + 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, + 'Nokia': { 'Lumia': 1 }, + 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, + 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 } + }); + + /* Detectable operating systems (order is important). */ + var os = getOS([ + 'Windows Phone', + 'Android', + 'CentOS', + { 'label': 'Chrome OS', 'pattern': 'CrOS' }, + 'Debian', + 'Fedora', + 'FreeBSD', + 'Gentoo', + 'Haiku', + 'Kubuntu', + 'Linux Mint', + 'OpenBSD', + 'Red Hat', + 'SuSE', + 'Ubuntu', + 'Xubuntu', + 'Cygwin', + 'Symbian OS', + 'hpwOS', + 'webOS ', + 'webOS', + 'Tablet OS', + 'Tizen', + 'Linux', + 'Mac OS X', + 'Macintosh', + 'Mac', + 'Windows 98;', + 'Windows ' + ]); + + /*------------------------------------------------------------------------*/ + + /** + * Picks the layout engine from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected layout engine. + */ + function getLayout(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the manufacturer from an array of guesses. + * + * @private + * @param {Array} guesses An object of guesses. + * @returns {null|string} The detected manufacturer. + */ + function getManufacturer(guesses) { + return reduce(guesses, function(result, value, key) { + // Lookup the manufacturer by product or scan the UA for the manufacturer. + return result || ( + value[product] || + value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || + RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) + ) && key; + }); + } + + /** + * Picks the browser name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected browser name. + */ + function getName(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the OS name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected OS name. + */ + function getOS(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) + )) { + result = cleanupOS(result, pattern, guess.label || guess); + } + return result; + }); + } + + /** + * Picks the product name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected product name. + */ + function getProduct(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || + RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) || + RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) + )) { + // Split by forward slash and append product version if needed. + if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { + result[0] += ' ' + result[1]; + } + // Correct character case and cleanup string. + guess = guess.label || guess; + result = format(result[0] + .replace(RegExp(pattern, 'i'), guess) + .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') + .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); + } + return result; + }); + } + + /** + * Resolves the version using an array of UA patterns. + * + * @private + * @param {Array} patterns An array of UA patterns. + * @returns {null|string} The detected version. + */ + function getVersion(patterns) { + return reduce(patterns, function(result, pattern) { + return result || (RegExp(pattern + + '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; + }); + } + + /** + * Returns `platform.description` when the platform object is coerced to a string. + * + * @name toString + * @memberOf platform + * @returns {string} Returns `platform.description` if available, else an empty string. + */ + function toStringPlatform() { + return this.description || ''; + } + + /*------------------------------------------------------------------------*/ + + // Convert layout to an array so we can add extra details. + layout && (layout = [layout]); + + // Detect product names that contain their manufacturer's name. + if (manufacturer && !product) { + product = getProduct([manufacturer]); + } + // Clean up Google TV. + if ((data = /\bGoogle TV\b/.exec(product))) { + product = data[0]; + } + // Detect simulators. + if (/\bSimulator\b/i.test(ua)) { + product = (product ? product + ' ' : '') + 'Simulator'; + } + // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. + if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { + description.push('running in Turbo/Uncompressed mode'); + } + // Detect IE Mobile 11. + if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) { + data = parse(ua.replace(/like iPhone OS/, '')); + manufacturer = data.manufacturer; + product = data.product; + } + // Detect iOS. + else if (/^iP/.test(product)) { + name || (name = 'Safari'); + os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) + ? ' ' + data[1].replace(/_/g, '.') + : ''); + } + // Detect Kubuntu. + else if (name == 'Konqueror' && !/buntu/i.test(os)) { + os = 'Kubuntu'; + } + // Detect Android browsers. + else if ((manufacturer && manufacturer != 'Google' && + ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) || + (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) { + name = 'Android Browser'; + os = /\bAndroid\b/.test(os) ? os : 'Android'; + } + // Detect Silk desktop/accelerated modes. + else if (name == 'Silk') { + if (!/\bMobi/i.test(ua)) { + os = 'Android'; + description.unshift('desktop mode'); + } + if (/Accelerated *= *true/i.test(ua)) { + description.unshift('accelerated'); + } + } + // Detect PaleMoon identifying as Firefox. + else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { + description.push('identifying as Firefox ' + data[1]); + } + // Detect Firefox OS and products running Firefox. + else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { + os || (os = 'Firefox OS'); + product || (product = data[1]); + } + // Detect false positives for Firefox/Safari. + else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { + // Escape the `/` for Firefox 1. + if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { + // Clear name of false positives. + name = null; + } + // Reassign a generic name. + if ((data = product || manufacturer || os) && + (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { + name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; + } + } + // Add Chrome version to description for Electron. + else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) { + description.push('Chromium ' + data); + } + // Detect non-Opera (Presto-based) versions (order is important). + if (!version) { + version = getVersion([ + '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))', + 'Version', + qualify(name), + '(?:Firefox|Minefield|NetFront)' + ]); + } + // Detect stubborn layout engines. + if ((data = + layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || + /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || + /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || + !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || + layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' + )) { + layout = [data]; + } + // Detect Windows Phone 7 desktop mode. + if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { + name += ' Mobile'; + os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); + description.unshift('desktop mode'); + } + // Detect Windows Phone 8.x desktop mode. + else if (/\bWPDesktop\b/i.test(ua)) { + name = 'IE Mobile'; + os = 'Windows Phone 8.x'; + description.unshift('desktop mode'); + version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); + } + // Detect IE 11 identifying as other browsers. + else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { + if (name) { + description.push('identifying as ' + name + (version ? ' ' + version : '')); + } + name = 'IE'; + version = data[1]; + } + // Leverage environment features. + if (useFeatures) { + // Detect server-side environments. + // Rhino has a global function while others have a global object. + if (isHostType(context, 'global')) { + if (java) { + data = java.lang.System; + arch = data.getProperty('os.arch'); + os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); + } + if (rhino) { + try { + version = context.require('ringo/engine').version.join('.'); + name = 'RingoJS'; + } catch(e) { + if ((data = context.system) && data.global.system == context.system) { + name = 'Narwhal'; + os || (os = data[0].os || null); + } + } + if (!name) { + name = 'Rhino'; + } + } + else if ( + typeof context.process == 'object' && !context.process.browser && + (data = context.process) + ) { + if (typeof data.versions == 'object') { + if (typeof data.versions.electron == 'string') { + description.push('Node ' + data.versions.node); + name = 'Electron'; + version = data.versions.electron; + } else if (typeof data.versions.nw == 'string') { + description.push('Chromium ' + version, 'Node ' + data.versions.node); + name = 'NW.js'; + version = data.versions.nw; + } + } + if (!name) { + name = 'Node.js'; + arch = data.arch; + os = data.platform; + version = /[\d.]+/.exec(data.version); + version = version ? version[0] : null; + } + } + } + // Detect Adobe AIR. + else if (getClassOf((data = context.runtime)) == airRuntimeClass) { + name = 'Adobe AIR'; + os = data.flash.system.Capabilities.os; + } + // Detect PhantomJS. + else if (getClassOf((data = context.phantom)) == phantomClass) { + name = 'PhantomJS'; + version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); + } + // Detect IE compatibility modes. + else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { + // We're in compatibility mode when the Trident version + 4 doesn't + // equal the document mode. + version = [version, doc.documentMode]; + if ((data = +data[1] + 4) != version[1]) { + description.push('IE ' + version[1] + ' mode'); + layout && (layout[1] = ''); + version[1] = data; + } + version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; + } + // Detect IE 11 masking as other browsers. + else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) { + description.push('masking as ' + name + ' ' + version); + name = 'IE'; + version = '11.0'; + layout = ['Trident']; + os = 'Windows'; + } + os = os && format(os); + } + // Detect prerelease phases. + if (version && (data = + /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || + /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || + /\bMinefield\b/i.test(ua) && 'a' + )) { + prerelease = /b/i.test(data) ? 'beta' : 'alpha'; + version = version.replace(RegExp(data + '\\+?$'), '') + + (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); + } + // Detect Firefox Mobile. + if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) { + name = 'Firefox Mobile'; + } + // Obscure Maxthon's unreliable version. + else if (name == 'Maxthon' && version) { + version = version.replace(/\.[\d.]+/, '.x'); + } + // Detect Xbox 360 and Xbox One. + else if (/\bXbox\b/i.test(product)) { + if (product == 'Xbox 360') { + os = null; + } + if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { + description.unshift('mobile mode'); + } + } + // Add mobile postfix. + else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && + (os == 'Windows CE' || /Mobi/i.test(ua))) { + name += ' Mobile'; + } + // Detect IE platform preview. + else if (name == 'IE' && useFeatures) { + try { + if (context.external === null) { + description.unshift('platform preview'); + } + } catch(e) { + description.unshift('embedded'); + } + } + // Detect BlackBerry OS version. + // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp + else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = + (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || + version + )) { + data = [data, /BB10/.test(ua)]; + os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; + version = null; + } + // Detect Opera identifying/masking itself as another browser. + // http://www.opera.com/support/kb/view/843/ + else if (this != forOwn && product != 'Wii' && ( + (useFeatures && opera) || + (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || + (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || + (name == 'IE' && ( + (os && !/^Win/.test(os) && version > 5.5) || + /\bWindows XP\b/.test(os) && version > 8 || + version == 8 && !/\bTrident\b/.test(ua) + )) + ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { + // When "identifying", the UA contains both Opera and the other browser's name. + data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); + if (reOpera.test(name)) { + if (/\bIE\b/.test(data) && os == 'Mac OS') { + os = null; + } + data = 'identify' + data; + } + // When "masking", the UA contains only the other browser's name. + else { + data = 'mask' + data; + if (operaClass) { + name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); + } else { + name = 'Opera'; + } + if (/\bIE\b/.test(data)) { + os = null; + } + if (!useFeatures) { + version = null; + } + } + layout = ['Presto']; + description.push(data); + } + // Detect WebKit Nightly and approximate Chrome/Safari versions. + if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { + // Correct build number for numeric comparison. + // (e.g. "532.5" becomes "532.05") + data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; + // Nightly builds are postfixed with a "+". + if (name == 'Safari' && data[1].slice(-1) == '+') { + name = 'WebKit Nightly'; + prerelease = 'alpha'; + version = data[1].slice(0, -1); + } + // Clear incorrect browser versions. + else if (version == data[1] || + version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { + version = null; + } + // Use the full Chrome version when available. + data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]; + // Detect Blink layout engine. + if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { + layout = ['Blink']; + } + // Detect JavaScriptCore. + // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi + if (!useFeatures || (!likeChrome && !data[1])) { + layout && (layout[1] = 'like Safari'); + data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8'); + } else { + layout && (layout[1] = 'like Chrome'); + data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); + } + // Add the postfix of ".x" or "+" for approximate versions. + layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); + // Obscure version for some Safari 1-2 releases. + if (name == 'Safari' && (!version || parseInt(version) > 45)) { + version = data; + } + } + // Detect Opera desktop modes. + if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { + name += ' '; + description.unshift('desktop mode'); + if (data == 'zvav') { + name += 'Mini'; + version = null; + } else { + name += 'Mobile'; + } + os = os.replace(RegExp(' *' + data + '$'), ''); + } + // Detect Chrome desktop mode. + else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { + description.unshift('desktop mode'); + name = 'Chrome Mobile'; + version = null; + + if (/\bOS X\b/.test(os)) { + manufacturer = 'Apple'; + os = 'iOS 4.3+'; + } else { + os = null; + } + } + // Strip incorrect OS versions. + if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && + ua.indexOf('/' + data + '-') > -1) { + os = trim(os.replace(data, '')); + } + // Add layout engine. + if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( + /Browser|Lunascape|Maxthon/.test(name) || + name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || + /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) { + // Don't add layout details to description if they are falsey. + (data = layout[layout.length - 1]) && description.push(data); + } + // Combine contextual information. + if (description.length) { + description = ['(' + description.join('; ') + ')']; + } + // Append manufacturer to description. + if (manufacturer && product && product.indexOf(manufacturer) < 0) { + description.push('on ' + manufacturer); + } + // Append product to description. + if (product) { + description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); + } + // Parse the OS into an object. + if (os) { + data = / ([\d.+]+)$/.exec(os); + isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; + os = { + 'architecture': 32, + 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, + 'version': data ? data[1] : null, + 'toString': function() { + var version = this.version; + return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); + } + }; + } + // Add browser/OS architecture. + if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { + if (os) { + os.architecture = 64; + os.family = os.family.replace(RegExp(' *' + data), ''); + } + if ( + name && (/\bWOW64\b/i.test(ua) || + (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) + ) { + description.unshift('32-bit'); + } + } + // Chrome 39 and above on OS X is always 64-bit. + else if ( + os && /^OS X/.test(os.family) && + name == 'Chrome' && parseFloat(version) >= 39 + ) { + os.architecture = 64; + } + + ua || (ua = null); + + /*------------------------------------------------------------------------*/ + + /** + * The platform object. + * + * @name platform + * @type Object + */ + var platform = {}; + + /** + * The platform description. + * + * @memberOf platform + * @type string|null + */ + platform.description = ua; + + /** + * The name of the browser's layout engine. + * + * The list of common layout engines include: + * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit" + * + * @memberOf platform + * @type string|null + */ + platform.layout = layout && layout[0]; + + /** + * The name of the product's manufacturer. + * + * The list of manufacturers include: + * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry", + * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo", + * "Nokia", "Samsung" and "Sony" + * + * @memberOf platform + * @type string|null + */ + platform.manufacturer = manufacturer; + + /** + * The name of the browser/environment. + * + * The list of common browser names include: + * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE", + * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk", + * "Opera Mini" and "Opera" + * + * Mobile versions of some browsers have "Mobile" appended to their name: + * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile" + * + * @memberOf platform + * @type string|null + */ + platform.name = name; + + /** + * The alpha/beta release indicator. + * + * @memberOf platform + * @type string|null + */ + platform.prerelease = prerelease; + + /** + * The name of the product hosting the browser. + * + * The list of common products include: + * + * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle", + * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer" + * + * @memberOf platform + * @type string|null + */ + platform.product = product; + + /** + * The browser's user agent string. + * + * @memberOf platform + * @type string|null + */ + platform.ua = ua; + + /** + * The browser/environment version. + * + * @memberOf platform + * @type string|null + */ + platform.version = name && version; + + /** + * The name of the operating system. + * + * @memberOf platform + * @type Object + */ + platform.os = os || { + + /** + * The CPU architecture the OS is built for. + * + * @memberOf platform.os + * @type number|null + */ + 'architecture': null, + + /** + * The family of the OS. + * + * Common values include: + * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", + * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", + * "Android", "iOS" and "Windows Phone" + * + * @memberOf platform.os + * @type string|null + */ + 'family': null, + + /** + * The version of the OS. + * + * @memberOf platform.os + * @type string|null + */ + 'version': null, + + /** + * Returns the OS string. + * + * @memberOf platform.os + * @returns {string} The OS string. + */ + 'toString': function() { return 'null'; } + }; + + platform.parse = parse; + platform.toString = toStringPlatform; + + if (platform.version) { + description.unshift(version); + } + if (platform.name) { + description.unshift(name); + } + if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { + description.push(product ? '(' + os + ')' : 'on ' + os); + } + if (description.length) { + platform.description = description.join(' '); + } + return platform; + } + + /*--------------------------------------------------------------------------*/ + + // Export platform. + var platform = parse(); + + // Some AMD build optimizers, like r.js, check for condition patterns like the following: + if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // Expose platform on the global object to prevent errors when platform is + // loaded by a script tag in the presence of an AMD loader. + // See http://requirejs.org/docs/errors.html#mismatch for more details. + root.platform = platform; + + // Define as an anonymous module so platform can be aliased through path mapping. + define(function() { + return platform; + }); + } + // Check for `exports` after `define` in case a build optimizer adds an `exports` object. + else if (freeExports && freeModule) { + // Export for CommonJS support. + forOwn(platform, function(value, key) { + freeExports[key] = value; + }); + } + else { + // Export to the global object. + root.platform = platform; + } +}.call(this)); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],9:[function(require,module,exports){ +var v1 = require('./v1'); +var v4 = require('./v4'); + +var uuid = v4; +uuid.v1 = v1; +uuid.v4 = v4; + +module.exports = uuid; + +},{"./v1":12,"./v4":13}],10:[function(require,module,exports){ +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +var byteToHex = []; +for (var i = 0; i < 256; ++i) { + byteToHex[i] = (i + 0x100).toString(16).substr(1); +} + +function bytesToUuid(buf, offset) { + var i = offset || 0; + var bth = byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; +} + +module.exports = bytesToUuid; + +},{}],11:[function(require,module,exports){ +// Unique ID creation requires a high quality random # generator. In the +// browser this is a little complicated due to unknown quality of Math.random() +// and inconsistent support for the `crypto` API. We do the best we can via +// feature-detection + +// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. +var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) || + (typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto)); +if (getRandomValues) { + // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto + var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef + + module.exports = function whatwgRNG() { + getRandomValues(rnds8); + return rnds8; + }; +} else { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var rnds = new Array(16); + + module.exports = function mathRNG() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return rnds; + }; +} + +},{}],12:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html + +var _nodeId; +var _clockseq; + +// Previous uuid creation time +var _lastMSecs = 0; +var _lastNSecs = 0; + +// See https://github.com/broofa/node-uuid for API details +function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + var node = options.node || _nodeId; + var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; + + // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + if (node == null || clockseq == null) { + var seedBytes = rng(); + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [ + seedBytes[0] | 0x01, + seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] + ]; + } + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + for (var n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf ? buf : bytesToUuid(b); +} + +module.exports = v1; + +},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +function v4(options, buf, offset) { + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options === 'binary' ? new Array(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ++ii) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || bytesToUuid(rnds); +} + +module.exports = v4; + +},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){ +/* +WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based +on @visionmedia's Emitter from UI Kit. + +Why? I wanted it standalone. + +I also wanted support for wildcard emitters like this: + +emitter.on('*', function (eventName, other, event, payloads) { + +}); + +emitter.on('somenamespace*', function (eventName, payloads) { + +}); + +Please note that callbacks triggered by wildcard registered events also get +the event name as the first argument. +*/ + +module.exports = WildEmitter; + +function WildEmitter() { } + +WildEmitter.mixin = function (constructor) { + var prototype = constructor.prototype || constructor; + + prototype.isWildEmitter= true; + + // Listen on the given `event` with `fn`. Store a group name if present. + prototype.on = function (event, groupName, fn) { + this.callbacks = this.callbacks || {}; + var hasGroup = (arguments.length === 3), + group = hasGroup ? arguments[1] : undefined, + func = hasGroup ? arguments[2] : arguments[1]; + func._groupName = group; + (this.callbacks[event] = this.callbacks[event] || []).push(func); + return this; + }; + + // Adds an `event` listener that will be invoked a single + // time then automatically removed. + prototype.once = function (event, groupName, fn) { + var self = this, + hasGroup = (arguments.length === 3), + group = hasGroup ? arguments[1] : undefined, + func = hasGroup ? arguments[2] : arguments[1]; + function on() { + self.off(event, on); + func.apply(this, arguments); + } + this.on(event, group, on); + return this; + }; + + // Unbinds an entire group + prototype.releaseGroup = function (groupName) { + this.callbacks = this.callbacks || {}; + var item, i, len, handlers; + for (item in this.callbacks) { + handlers = this.callbacks[item]; + for (i = 0, len = handlers.length; i < len; i++) { + if (handlers[i]._groupName === groupName) { + //console.log('removing'); + // remove it and shorten the array we're looping through + handlers.splice(i, 1); + i--; + len--; + } + } + } + return this; + }; + + // Remove the given callback for `event` or all + // registered callbacks. + prototype.off = function (event, fn) { + this.callbacks = this.callbacks || {}; + var callbacks = this.callbacks[event], + i; + + if (!callbacks) return this; + + // remove all handlers + if (arguments.length === 1) { + delete this.callbacks[event]; + return this; + } + + // remove specific handler + i = callbacks.indexOf(fn); + callbacks.splice(i, 1); + if (callbacks.length === 0) { + delete this.callbacks[event]; + } + return this; + }; + + /// Emit `event` with the given args. + // also calls any `*` handlers + prototype.emit = function (event) { + this.callbacks = this.callbacks || {}; + var args = [].slice.call(arguments, 1), + callbacks = this.callbacks[event], + specialCallbacks = this.getWildcardCallbacks(event), + i, + len, + item, + listeners; + + if (callbacks) { + listeners = callbacks.slice(); + for (i = 0, len = listeners.length; i < len; ++i) { + if (!listeners[i]) { + break; + } + listeners[i].apply(this, args); + } + } + + if (specialCallbacks) { + len = specialCallbacks.length; + listeners = specialCallbacks.slice(); + for (i = 0, len = listeners.length; i < len; ++i) { + if (!listeners[i]) { + break; + } + listeners[i].apply(this, [event].concat(args)); + } + } + + return this; + }; + + // Helper for for finding special wildcard event handlers that match the event + prototype.getWildcardCallbacks = function (eventName) { + this.callbacks = this.callbacks || {}; + var item, + split, + result = []; + + for (item in this.callbacks) { + split = item.split('*'); + if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { + result = result.concat(this.callbacks[item]); + } + } + return result; + }; + +}; + +WildEmitter.mixin(WildEmitter); + +},{}],15:[function(require,module,exports){ +/*! + * EventEmitter v5.2.4 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - http://oli.me.uk/ + * @preserve + */ + +;(function (exports) { + 'use strict'; + + /** + * Class for managing events. + * Can be extended to provide event functionality in other classes. + * + * @class EventEmitter Manages event registering and emitting. + */ + function EventEmitter() {} + + // Shortcuts to improve speed and size + var proto = EventEmitter.prototype; + var originalGlobalValue = exports.EventEmitter; + + /** + * Finds the index of the listener for the event in its storage array. + * + * @param {Function[]} listeners Array of listeners to search through. + * @param {Function} listener Method to look for. + * @return {Number} Index of the specified listener, -1 if not found + * @api private + */ + function indexOfListener(listeners, listener) { + var i = listeners.length; + while (i--) { + if (listeners[i].listener === listener) { + return i; + } + } + + return -1; + } + + /** + * Alias a method while keeping the context correct, to allow for overwriting of target method. + * + * @param {String} name The name of the target method. + * @return {Function} The aliased method + * @api private + */ + function alias(name) { + return function aliasClosure() { + return this[name].apply(this, arguments); + }; + } + + /** + * Returns the listener array for the specified event. + * Will initialise the event object and listener arrays if required. + * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. + * Each property in the object response is an array of listener functions. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Function[]|Object} All listener functions for the event. + */ + proto.getListeners = function getListeners(evt) { + var events = this._getEvents(); + var response; + var key; + + // Return a concatenated array of all matching events if + // the selector is a regular expression. + if (evt instanceof RegExp) { + response = {}; + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + response[key] = events[key]; + } + } + } + else { + response = events[evt] || (events[evt] = []); + } + + return response; + }; + + /** + * Takes a list of listener objects and flattens it into a list of listener functions. + * + * @param {Object[]} listeners Raw listener objects. + * @return {Function[]} Just the listener functions. + */ + proto.flattenListeners = function flattenListeners(listeners) { + var flatListeners = []; + var i; + + for (i = 0; i < listeners.length; i += 1) { + flatListeners.push(listeners[i].listener); + } + + return flatListeners; + }; + + /** + * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Object} All listener functions for an event in an object. + */ + proto.getListenersAsObject = function getListenersAsObject(evt) { + var listeners = this.getListeners(evt); + var response; + + if (listeners instanceof Array) { + response = {}; + response[evt] = listeners; + } + + return response || listeners; + }; + + function isValidListener (listener) { + if (typeof listener === 'function' || listener instanceof RegExp) { + return true + } else if (listener && typeof listener === 'object') { + return isValidListener(listener.listener) + } else { + return false + } + } + + /** + * Adds a listener function to the specified event. + * The listener will not be added if it is a duplicate. + * If the listener returns true then it will be removed after it is called. + * If you pass a regular expression as the event name then the listener will be added to all events that match it. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListener = function addListener(evt, listener) { + if (!isValidListener(listener)) { + throw new TypeError('listener must be a function'); + } + + var listeners = this.getListenersAsObject(evt); + var listenerIsWrapped = typeof listener === 'object'; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { + listeners[key].push(listenerIsWrapped ? listener : { + listener: listener, + once: false + }); + } + } + + return this; + }; + + /** + * Alias of addListener + */ + proto.on = alias('addListener'); + + /** + * Semi-alias of addListener. It will add a listener that will be + * automatically removed after its first execution. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addOnceListener = function addOnceListener(evt, listener) { + return this.addListener(evt, { + listener: listener, + once: true + }); + }; + + /** + * Alias of addOnceListener. + */ + proto.once = alias('addOnceListener'); + + /** + * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. + * You need to tell it what event names should be matched by a regex. + * + * @param {String} evt Name of the event to create. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvent = function defineEvent(evt) { + this.getListeners(evt); + return this; + }; + + /** + * Uses defineEvent to define multiple events. + * + * @param {String[]} evts An array of event names to define. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvents = function defineEvents(evts) { + for (var i = 0; i < evts.length; i += 1) { + this.defineEvent(evts[i]); + } + return this; + }; + + /** + * Removes a listener function from the specified event. + * When passed a regular expression as the event name, it will remove the listener from all events that match it. + * + * @param {String|RegExp} evt Name of the event to remove the listener from. + * @param {Function} listener Method to remove from the event. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListener = function removeListener(evt, listener) { + var listeners = this.getListenersAsObject(evt); + var index; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key)) { + index = indexOfListener(listeners[key], listener); + + if (index !== -1) { + listeners[key].splice(index, 1); + } + } + } + + return this; + }; + + /** + * Alias of removeListener + */ + proto.off = alias('removeListener'); + + /** + * Adds listeners in bulk using the manipulateListeners method. + * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. + * You can also pass it a regular expression to add the array of listeners to all events that match it. + * Yeah, this function does quite a bit. That's probably a bad thing. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListeners = function addListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(false, evt, listeners); + }; + + /** + * Removes listeners in bulk using the manipulateListeners method. + * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be removed. + * You can also pass it a regular expression to remove the listeners from all events that match it. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListeners = function removeListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(true, evt, listeners); + }; + + /** + * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. + * The first argument will determine if the listeners are removed (true) or added (false). + * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be added/removed. + * You can also pass it a regular expression to manipulate the listeners of all events that match it. + * + * @param {Boolean} remove True if you want to remove listeners, false if you want to add. + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add/remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { + var i; + var value; + var single = remove ? this.removeListener : this.addListener; + var multiple = remove ? this.removeListeners : this.addListeners; + + // If evt is an object then pass each of its properties to this method + if (typeof evt === 'object' && !(evt instanceof RegExp)) { + for (i in evt) { + if (evt.hasOwnProperty(i) && (value = evt[i])) { + // Pass the single listener straight through to the singular method + if (typeof value === 'function') { + single.call(this, i, value); + } + else { + // Otherwise pass back to the multiple function + multiple.call(this, i, value); + } + } + } + } + else { + // So evt must be a string + // And listeners must be an array of listeners + // Loop over it and pass each one to the multiple method + i = listeners.length; + while (i--) { + single.call(this, evt, listeners[i]); + } + } + + return this; + }; + + /** + * Removes all listeners from a specified event. + * If you do not specify an event then all listeners will be removed. + * That means every event will be emptied. + * You can also pass a regex to remove all events that match it. + * + * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeEvent = function removeEvent(evt) { + var type = typeof evt; + var events = this._getEvents(); + var key; + + // Remove different things depending on the state of evt + if (type === 'string') { + // Remove all listeners for the specified event + delete events[evt]; + } + else if (evt instanceof RegExp) { + // Remove all events matching the regex. + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + delete events[key]; + } + } + } + else { + // Remove all listeners in all events + delete this._events; + } + + return this; + }; + + /** + * Alias of removeEvent. + * + * Added to mirror the node API. + */ + proto.removeAllListeners = alias('removeEvent'); + + /** + * Emits an event of your choice. + * When emitted, every listener attached to that event will be executed. + * If you pass the optional argument array then those arguments will be passed to every listener upon execution. + * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. + * So they will not arrive within the array on the other side, they will be separate. + * You can also pass a regular expression to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {Array} [args] Optional array of arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emitEvent = function emitEvent(evt, args) { + var listenersMap = this.getListenersAsObject(evt); + var listeners; + var listener; + var i; + var key; + var response; + + for (key in listenersMap) { + if (listenersMap.hasOwnProperty(key)) { + listeners = listenersMap[key].slice(0); + + for (i = 0; i < listeners.length; i++) { + // If the listener returns true then it shall be removed from the event + // The function is executed either with a basic call or an apply if there is an args array + listener = listeners[i]; + + if (listener.once === true) { + this.removeListener(evt, listener.listener); + } + + response = listener.listener.apply(this, args || []); + + if (response === this._getOnceReturnValue()) { + this.removeListener(evt, listener.listener); + } + } + } + } + + return this; + }; + + /** + * Alias of emitEvent + */ + proto.trigger = alias('emitEvent'); + + /** + * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. + * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {...*} Optional additional arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emit = function emit(evt) { + var args = Array.prototype.slice.call(arguments, 1); + return this.emitEvent(evt, args); + }; + + /** + * Sets the current value to check against when executing listeners. If a + * listeners return value matches the one set here then it will be removed + * after execution. This value defaults to true. + * + * @param {*} value The new value to check for when executing listeners. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.setOnceReturnValue = function setOnceReturnValue(value) { + this._onceReturnValue = value; + return this; + }; + + /** + * Fetches the current value to check against when executing listeners. If + * the listeners return value matches this one then it should be removed + * automatically. It will return true by default. + * + * @return {*|Boolean} The current value to check for or the default, true. + * @api private + */ + proto._getOnceReturnValue = function _getOnceReturnValue() { + if (this.hasOwnProperty('_onceReturnValue')) { + return this._onceReturnValue; + } + else { + return true; + } + }; + + /** + * Fetches the events object and creates one if required. + * + * @return {Object} The events storage object. + * @api private + */ + proto._getEvents = function _getEvents() { + return this._events || (this._events = {}); + }; + + /** + * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. + * + * @return {Function} Non conflicting EventEmitter class. + */ + EventEmitter.noConflict = function noConflict() { + exports.EventEmitter = originalGlobalValue; + return EventEmitter; + }; + + // Expose the class either via AMD, CommonJS or the global object + if (typeof define === 'function' && define.amd) { + define(function () { + return EventEmitter; + }); + } + else if (typeof module === 'object' && module.exports){ + module.exports = EventEmitter; + } + else { + exports.EventEmitter = EventEmitter; + } +}(this || {})); + +},{}],16:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenVidu_1 = require("./OpenVidu/OpenVidu"); +if (window) { + window['OpenVidu'] = OpenVidu_1.OpenVidu; +} + +},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Stream_1 = require("./Stream"); +var Connection = (function () { + function Connection(session, opts) { + this.session = session; + this.disposed = false; + var msg = "'Connection' created "; + if (!!opts) { + msg += "(remote) with 'connectionId' [" + opts.id + ']'; + } + else { + msg += '(local)'; + } + console.info(msg); + this.options = opts; + if (!!opts) { + this.connectionId = opts.id; + if (opts.metadata) { + this.data = opts.metadata; + } + if (opts.streams) { + this.initRemoteStreams(opts.streams); + } + } + this.creationTime = new Date().getTime(); + } + Connection.prototype.sendIceCandidate = function (candidate) { + console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate)); + this.session.openvidu.sendRequest('onIceCandidate', { + endpointName: this.connectionId, + candidate: candidate.candidate, + sdpMid: candidate.sdpMid, + sdpMLineIndex: candidate.sdpMLineIndex + }, function (error, response) { + if (error) { + console.error('Error sending ICE candidate: ' + + JSON.stringify(error)); + } + }); + }; + Connection.prototype.initRemoteStreams = function (options) { + var _this = this; + options.forEach(function (opts) { + var streamOptions = { + id: opts.id, + connection: _this, + frameRate: opts.frameRate, + recvAudio: opts.audioActive, + recvVideo: opts.videoActive, + typeOfVideo: opts.typeOfVideo + }; + var stream = new Stream_1.Stream(_this.session, streamOptions); + _this.addStream(stream); + }); + console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); + }; + Connection.prototype.addStream = function (stream) { + stream.connection = this; + this.stream = stream; + }; + Connection.prototype.removeStream = function (streamId) { + delete this.stream; + }; + Connection.prototype.dispose = function () { + if (!!this.stream) { + delete this.stream; + } + this.disposed = true; + }; + return Connection; +}()); +exports.Connection = Connection; + +},{"./Stream":22}],18:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState"); +var LocalRecorder = (function () { + function LocalRecorder(stream) { + this.stream = stream; + this.chunks = []; + this.count = 0; + this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; + this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; + this.state = LocalRecorderState_1.LocalRecorderState.READY; + } + LocalRecorder.prototype.record = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (typeof MediaRecorder === 'undefined') { + console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); + throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); + } + if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) { + throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); + } + console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'"); + if (typeof MediaRecorder.isTypeSupported === 'function') { + var options = void 0; + if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { + options = { mimeType: 'video/webm;codecs=vp9' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { + options = { mimeType: 'video/webm;codecs=h264' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { + options = { mimeType: 'video/webm;codecs=vp8' }; + } + console.log('Using mimeType ' + options.mimeType); + _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options); + } + else { + console.warn('isTypeSupported is not supported, using default codecs for browser'); + _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream()); + } + _this.mediaRecorder.start(10); + } + catch (err) { + reject(err); + } + _this.mediaRecorder.ondataavailable = function (e) { + _this.chunks.push(e.data); + }; + _this.mediaRecorder.onerror = function (e) { + console.error('MediaRecorder error: ', e); + }; + _this.mediaRecorder.onstart = function () { + console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + }; + _this.mediaRecorder.onpause = function () { + console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onresume = function () { + console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onwarning = function (e) { + console.log('MediaRecorder warning: ' + e); + }; + _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; + resolve(); + }); + }; + LocalRecorder.prototype.stop = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before')); + } + _this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + resolve(); + }; + _this.mediaRecorder.stop(); + } + catch (e) { + reject(e); + } + }); + }; + LocalRecorder.prototype.pause = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) { + reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before')); + } + _this.mediaRecorder.pause(); + _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED; + } + catch (error) { + reject(error); + } + }); + }; + LocalRecorder.prototype.resume = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) { + throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before')); + } + _this.mediaRecorder.resume(); + _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; + } + catch (error) { + reject(error); + } + }); + }; + LocalRecorder.prototype.preview = function (parentElement) { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + this.videoPreview = document.createElement('video'); + this.videoPreview.id = this.id; + this.videoPreview.autoplay = true; + if (typeof parentElement === 'string') { + this.htmlParentElementId = parentElement; + var parentElementDom = document.getElementById(parentElement); + if (parentElementDom) { + this.videoPreview = parentElementDom.appendChild(this.videoPreview); + } + } + else { + this.htmlParentElementId = parentElement.id; + this.videoPreview = parentElement.appendChild(this.videoPreview); + } + this.videoPreview.src = this.videoPreviewSrc; + return this.videoPreview; + }; + LocalRecorder.prototype.clean = function () { + var _this = this; + var f = function () { + delete _this.blob; + _this.chunks = []; + _this.count = 0; + delete _this.mediaRecorder; + _this.state = LocalRecorderState_1.LocalRecorderState.READY; + }; + if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) { + this.stop().then(function () { return f(); }).catch(function () { return f(); }); + } + else { + f(); + } + }; + LocalRecorder.prototype.download = function () { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var a = document.createElement('a'); + a.style.display = 'none'; + document.body.appendChild(a); + var url = window.URL.createObjectURL(this.blob); + a.href = url; + a.download = this.id + '.webm'; + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + } + }; + LocalRecorder.prototype.getBlob = function () { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); + } + else { + return this.blob; + } + }; + LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var http_1 = new XMLHttpRequest(); + http_1.open('POST', endpoint, true); + if (typeof headers === 'object') { + for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { + var key = _a[_i]; + http_1.setRequestHeader(key, headers[key]); + } + } + http_1.onreadystatechange = function () { + if (http_1.readyState === 4) { + if (http_1.status.toString().charAt(0) === '2') { + resolve(http_1.responseText); + } + else { + reject(http_1.status); + } + } + }; + http_1.send(_this.blob); + } + }); + }; + LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var http_2 = new XMLHttpRequest(); + http_2.open('POST', endpoint, true); + if (typeof headers === 'object') { + for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { + var key = _a[_i]; + http_2.setRequestHeader(key, headers[key]); + } + } + var sendable = new FormData(); + sendable.append('file', _this.blob, _this.id + '.webm'); + http_2.onreadystatechange = function () { + if (http_2.readyState === 4) { + if (http_2.status.toString().charAt(0) === '2') { + resolve(http_2.responseText); + } + else { + reject(http_2.status); + } + } + }; + http_2.send(sendable); + } + }); + }; + LocalRecorder.prototype.onStopDefault = function () { + console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')'); + this.blob = new Blob(this.chunks, { type: 'video/webm' }); + this.chunks = []; + this.videoPreviewSrc = window.URL.createObjectURL(this.blob); + this.state = LocalRecorderState_1.LocalRecorderState.FINISHED; + }; + return LocalRecorder; +}()); +exports.LocalRecorder = LocalRecorder; + +},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorder_1 = require("./LocalRecorder"); +var Publisher_1 = require("./Publisher"); +var Session_1 = require("./Session"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); +var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); +var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); +var platform = require("platform"); +var OpenVidu = (function () { + function OpenVidu() { + this.secret = ''; + this.recorder = false; + this.advancedConfiguration = {}; + console.info("'OpenVidu' initialized"); + } + OpenVidu.prototype.initSession = function () { + this.session = new Session_1.Session(this); + return this.session; + }; + OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) { + var properties; + if (!!param2 && (typeof param2 !== 'function')) { + properties = param2; + properties = { + audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, + frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), + insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, + mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, + publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, + publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, + resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), + videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined + }; + } + else { + properties = { + insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, + mirror: true, + publishAudio: true, + publishVideo: true, + resolution: '640x480' + }; + } + var publisher = new Publisher_1.Publisher(targetElement, properties, this); + var completionHandler; + if (!!param2 && (typeof param2 === 'function')) { + completionHandler = param2; + } + else if (!!param3) { + completionHandler = param3; + } + publisher.initialize() + .then(function () { + if (completionHandler !== undefined) { + completionHandler(undefined); + } + publisher.emitEvent('accessAllowed', []); + }).catch(function (error) { + if (completionHandler !== undefined) { + completionHandler(error); + } + publisher.emitEvent('accessDenied', []); + }); + return publisher; + }; + OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { + var _this = this; + return new Promise(function (resolve, reject) { + var publisher; + var callback = function (error) { + if (!!error) { + reject(error); + } + else { + resolve(publisher); + } + }; + if (!!properties) { + publisher = _this.initPublisher(targetElement, properties, callback); + } + else { + publisher = _this.initPublisher(targetElement, callback); + } + }); + }; + OpenVidu.prototype.initLocalRecorder = function (stream) { + return new LocalRecorder_1.LocalRecorder(stream); + }; + OpenVidu.prototype.checkSystemRequirements = function () { + var browser = platform.name; + var version = platform.version; + if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') && + (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') && + (browser !== 'Opera') && (browser !== 'Opera Mobile') && + (browser !== 'Safari')) { + return 0; + } + else { + return 1; + } + }; + OpenVidu.prototype.getDevices = function () { + return new Promise(function (resolve, reject) { + navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { + var devices = []; + deviceInfos.forEach(function (deviceInfo) { + if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { + devices.push({ + kind: deviceInfo.kind, + deviceId: deviceInfo.deviceId, + label: deviceInfo.label + }); + } + }); + resolve(devices); + }).catch(function (error) { + console.error('Error getting devices', error); + reject(error); + }); + }); + }; + OpenVidu.prototype.getUserMedia = function (options) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.generateMediaConstraints(options) + .then(function (constraints) { + navigator.mediaDevices.getUserMedia(constraints) + .then(function (mediaStream) { + resolve(mediaStream); + }) + .catch(function (error) { + var errorName; + var errorMessage = error.toString(); + if (!(options.videoSource === 'screen')) { + errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; + } + reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + OpenVidu.prototype.enableProdMode = function () { + console.log = function () { }; + console.debug = function () { }; + console.info = function () { }; + console.warn = function () { }; + }; + OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { + this.advancedConfiguration = configuration; + }; + OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { + var _this = this; + return new Promise(function (resolve, reject) { + var audio, video; + if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) { + audio = false; + } + else if (publisherProperties.audioSource === undefined) { + audio = true; + } + else { + audio = publisherProperties.audioSource; + } + if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) { + video = false; + } + else { + video = { + height: { + ideal: 480 + }, + width: { + ideal: 640 + } + }; + } + var mediaConstraints = { + audio: audio, + video: video + }; + if (typeof mediaConstraints.audio === 'string') { + mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } }; + } + if (mediaConstraints.video) { + if (!!publisherProperties.resolution) { + var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); + var width = Number(widthAndHeight[0]); + var height = Number(widthAndHeight[1]); + mediaConstraints.video.width.ideal = width; + mediaConstraints.video.height.ideal = height; + } + if (!!publisherProperties.frameRate) { + mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate }; + } + if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') { + if (publisherProperties.videoSource === 'screen') { + if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) { + var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); + console.error(error); + reject(error); + } + else { + if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) { + screenSharing.getScreenConstraints(function (error, screenConstraints) { + if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') { + if (error === 'permission-denied' || error === 'PermissionDeniedError') { + var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); + console.error(error_1); + reject(error_1); + } + else { + var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); + screenSharing.getChromeExtensionStatus(extensionId, function (status) { + if (status === 'installed-disabled') { + var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); + console.error(error_2); + reject(error_2); + } + if (status === 'not-installed') { + var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); + console.error(error_3); + reject(error_3); + } + }); + } + } + else { + mediaConstraints.video = screenConstraints; + resolve(mediaConstraints); + } + }); + } + else { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + if (!!error) { + if (error === 'not-installed') { + var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension : + 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold'; + var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl); + console.error(error_4); + reject(error_4); + } + else if (error === 'installed-disabled') { + var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); + console.error(error_5); + reject(error_5); + } + else if (error === 'permission-denied') { + var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); + console.error(error_6); + reject(error_6); + } + } + else { + mediaConstraints.video = screenConstraints.video; + resolve(mediaConstraints); + } + }); + } + publisherProperties.videoSource = 'screen'; + } + } + else { + mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource }; + resolve(mediaConstraints); + } + } + else { + resolve(mediaConstraints); + } + } + else { + resolve(mediaConstraints); + } + }); + }; + OpenVidu.prototype.startWs = function (onConnectSucces) { + var config = { + heartbeat: 5000, + sendCloseMessage: false, + ws: { + uri: this.wsUri, + useSockJS: false, + onconnected: onConnectSucces, + ondisconnect: this.disconnectCallback.bind(this), + onreconnecting: this.reconnectingCallback.bind(this), + onreconnected: this.reconnectedCallback.bind(this) + }, + rpc: { + requestTimeout: 10000, + participantJoined: this.session.onParticipantJoined.bind(this.session), + participantPublished: this.session.onParticipantPublished.bind(this.session), + participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), + participantLeft: this.session.onParticipantLeft.bind(this.session), + participantEvicted: this.session.onParticipantEvicted.bind(this.session), + recordingStarted: this.session.onRecordingStarted.bind(this.session), + recordingStopped: this.session.onRecordingStopped.bind(this.session), + sendMessage: this.session.onNewMessage.bind(this.session), + iceCandidate: this.session.recvIceCandidate.bind(this.session), + mediaError: this.session.onMediaError.bind(this.session) + } + }; + this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); + }; + OpenVidu.prototype.closeWs = function () { + this.jsonRpcClient.close(); + }; + OpenVidu.prototype.sendRequest = function (method, params, callback) { + if (params && params instanceof Function) { + callback = params; + params = {}; + } + console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); + this.jsonRpcClient.send(method, params, callback); + }; + OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) { + var is = (!!mediaSource && + mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' && + mediaSource.id !== undefined && typeof mediaSource.id === 'string' && + mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' && + mediaSource.label !== undefined && typeof mediaSource.label === 'string' && + mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' && + mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string'); + return is; + }; + OpenVidu.prototype.getWsUri = function () { + return this.wsUri; + }; + OpenVidu.prototype.getSecret = function () { + return this.secret; + }; + OpenVidu.prototype.getRecorder = function () { + return this.recorder; + }; + OpenVidu.prototype.disconnectCallback = function () { + console.warn('Websocket connection lost'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenVidu.prototype.reconnectingCallback = function () { + console.warn('Websocket connection lost (reconnecting)'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenVidu.prototype.reconnectedCallback = function () { + console.warn('Websocket reconnected'); + }; + OpenVidu.prototype.isRoomAvailable = function () { + if (this.session !== undefined && this.session instanceof Session_1.Session) { + return true; + } + else { + console.warn('Session instance not found'); + return false; + } + }; + return OpenVidu; +}()); +exports.OpenVidu = OpenVidu; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":42,"../OpenViduInternal/ScreenSharing/Screen-Capturing":47,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":46,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Session_1 = require("./Session"); +var Stream_1 = require("./Stream"); +var StreamManager_1 = require("./StreamManager"); +var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); +var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var Publisher = (function (_super) { + __extends(Publisher, _super); + function Publisher(targEl, properties, openvidu) { + var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this; + _this.openvidu = openvidu; + _this.accessAllowed = false; + _this.isSubscribedToRemote = false; + _this.accessDenied = false; + _this.properties = properties; + _this.stream.ee.on('local-stream-destroyed-by-disconnect', function (reason) { + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + }); + return _this; + } + Publisher.prototype.publishAudio = function (value) { + this.stream.getMediaStream().getAudioTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream'); + }; + Publisher.prototype.publishVideo = function (value) { + this.stream.getMediaStream().getVideoTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream'); + }; + Publisher.prototype.subscribeToRemote = function (value) { + value = (value !== undefined) ? value : true; + this.isSubscribedToRemote = value; + this.stream.subscribeToMyRemote(value); + }; + Publisher.prototype.on = function (type, handler) { + var _this = this; + _super.prototype.on.call(this, type, handler); + if (type === 'streamCreated') { + if (!!this.stream && this.stream.isLocalStreamPublished) { + this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); + } + else { + this.stream.ee.on('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); + }); + } + } + if (type === 'remoteVideoPlaying') { + if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); + } + } + if (type === 'accessAllowed') { + if (this.accessAllowed) { + this.ee.emitEvent('accessAllowed'); + } + } + if (type === 'accessDenied') { + if (this.accessDenied) { + this.ee.emitEvent('accessDenied'); + } + } + return this; + }; + Publisher.prototype.once = function (type, handler) { + var _this = this; + _super.prototype.once.call(this, type, handler); + if (type === 'streamCreated') { + if (!!this.stream && this.stream.isLocalStreamPublished) { + this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); + } + else { + this.stream.ee.once('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); + }); + } + } + if (type === 'remoteVideoPlaying') { + if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); + } + } + if (type === 'accessAllowed') { + if (this.accessAllowed) { + this.ee.emitEvent('accessAllowed'); + } + } + if (type === 'accessDenied') { + if (this.accessDenied) { + this.ee.emitEvent('accessDenied'); + } + } + return this; + }; + Publisher.prototype.initialize = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var errorCallback = function (openViduError) { + _this.accessDenied = true; + _this.accessAllowed = false; + reject(openViduError); + }; + var successCallback = function (mediaStream) { + _this.accessAllowed = true; + _this.accessDenied = false; + if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) { + mediaStream.removeTrack(mediaStream.getAudioTracks()[0]); + mediaStream.addTrack(_this.properties.audioSource); + } + if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) { + mediaStream.removeTrack(mediaStream.getVideoTracks()[0]); + mediaStream.addTrack(_this.properties.videoSource); + } + if (!!mediaStream.getAudioTracks()[0]) { + mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; + } + if (!!mediaStream.getVideoTracks()[0]) { + mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; + } + _this.stream.setMediaStream(mediaStream); + if (!_this.stream.displayMyRemote()) { + _this.stream.updateMediaStreamInVideos(); + } + _this.stream.isLocalStreamReadyToPublish = true; + _this.stream.ee.emitEvent('stream-ready-to-publish', []); + if (!!_this.firstVideoElement) { + _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode); + } + delete _this.firstVideoElement; + resolve(); + }; + _this.openvidu.generateMediaConstraints(_this.properties) + .then(function (constraints) { + var outboundStreamOptions = { + mediaConstraints: constraints, + publisherProperties: _this.properties + }; + _this.stream.setOutboundStreamOptions(outboundStreamOptions); + var constraintsAux = {}; + var timeForDialogEvent = 1250; + if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) { + var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio); + constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1; + constraintsAux.video = constraints.video; + var startTime_1 = Date.now(); + _this.setPermissionDialogTimer(timeForDialogEvent); + navigator.mediaDevices.getUserMedia(constraintsAux) + .then(function (mediaStream) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) { + constraintsAux.audio = definedAudioConstraint_1; + constraintsAux.video = false; + startTime_1 = Date.now(); + _this.setPermissionDialogTimer(timeForDialogEvent); + navigator.mediaDevices.getUserMedia(constraintsAux) + .then(function (audioOnlyStream) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); + successCallback(mediaStream); + }) + .catch(function (error) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + var errorName, errorMessage; + switch (error.name.toLowerCase()) { + case 'notfounderror': + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'notallowederror': + errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'overconstrainederror': + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + } + }); + } + else { + successCallback(mediaStream); + } + }) + .catch(function (error) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + var errorName, errorMessage; + switch (error.name.toLowerCase()) { + case 'notfounderror': + navigator.mediaDevices.getUserMedia({ + audio: false, + video: constraints.video + }) + .then(function (mediaStream) { + mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }).catch(function (e) { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + break; + case 'notallowederror': + errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'overconstrainederror': + navigator.mediaDevices.getUserMedia({ + audio: false, + video: constraints.video + }) + .then(function (mediaStream) { + mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }).catch(function (e) { + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; + errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + break; + } + }); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'")); + } + }) + .catch(function (error) { + errorCallback(error); + }); + }); + }; + Publisher.prototype.updateSession = function (session) { + this.session = session; + this.stream.session = session; + }; + Publisher.prototype.emitEvent = function (type, eventArray) { + this.ee.emitEvent(type, eventArray); + }; + Publisher.prototype.reestablishStreamPlayingEvent = function () { + if (this.ee.getListeners('streamPlaying').length > 0) { + this.addPlayEventToFirstVideo(); + } + }; + Publisher.prototype.setPermissionDialogTimer = function (waitTime) { + var _this = this; + this.permissionDialogTimeout = setTimeout(function () { + _this.ee.emitEvent('accessDialogOpened', []); + }, waitTime); + }; + Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) { + clearTimeout(this.permissionDialogTimeout); + if ((Date.now() - startTime) > waitTime) { + this.ee.emitEvent('accessDialogClosed', []); + } + }; + return Publisher; +}(StreamManager_1.StreamManager)); +exports.Publisher = Publisher; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/VideoElementEvent":36,"./Session":21,"./Stream":22,"./StreamManager":23}],21:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Connection_1 = require("./Connection"); +var Subscriber_1 = require("./Subscriber"); +var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent"); +var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent"); +var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); +var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent"); +var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var platform = require("platform"); +var EventEmitter = require("wolfy87-eventemitter"); +var Session = (function () { + function Session(openvidu) { + this.streamManagers = []; + this.remoteStreamsCreated = {}; + this.remoteConnections = {}; + this.speakingEventsEnabled = false; + this.ee = new EventEmitter(); + this.openvidu = openvidu; + } + Session.prototype.connect = function (token, metadata) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.processToken(token); + if (_this.openvidu.checkSystemRequirements()) { + _this.options = { + sessionId: _this.sessionId, + participantId: token, + metadata: !!metadata ? _this.stringClientMetadata(metadata) : '' + }; + _this.connectAux(token).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu')); + } + }); + }; + Session.prototype.disconnect = function () { + this.leave(false, 'disconnect'); + }; + Session.prototype.subscribe = function (stream, targetElement, param3, param4) { + var properties = {}; + if (!!param3 && typeof param3 !== 'function') { + properties = { + insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, + subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, + subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true + }; + } + else { + properties = { + insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, + subscribeToAudio: true, + subscribeToVideo: true + }; + } + var completionHandler; + if (!!param3 && (typeof param3 === 'function')) { + completionHandler = param3; + } + else if (!!param4) { + completionHandler = param4; + } + console.info('Subscribing to ' + stream.connection.connectionId); + stream.subscribe() + .then(function () { + console.info('Subscribed correctly to ' + stream.connection.connectionId); + if (completionHandler !== undefined) { + completionHandler(undefined); + } + }) + .catch(function (error) { + if (completionHandler !== undefined) { + completionHandler(error); + } + }); + var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties); + if (!!subscriber.targetElement) { + stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode); + } + return subscriber; + }; + Session.prototype.subscribeAsync = function (stream, targetElement, properties) { + var _this = this; + return new Promise(function (resolve, reject) { + var subscriber; + var callback = function (error) { + if (!!error) { + reject(error); + } + else { + resolve(subscriber); + } + }; + if (!!properties) { + subscriber = _this.subscribe(stream, targetElement, properties, callback); + } + else { + subscriber = _this.subscribe(stream, targetElement, callback); + } + }); + }; + Session.prototype.unsubscribe = function (subscriber) { + var connectionId = subscriber.stream.connection.connectionId; + console.info('Unsubscribing from ' + connectionId); + this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { + if (error) { + console.error('Error unsubscribing from ' + connectionId, error); + } + else { + console.info('Unsubscribed correctly from ' + connectionId); + } + subscriber.stream.disposeWebRtcPeer(); + subscriber.stream.disposeMediaStream(); + }); + subscriber.stream.streamManager.removeAllVideos(); + }; + Session.prototype.publish = function (publisher) { + var _this = this; + return new Promise(function (resolve, reject) { + publisher.session = _this; + publisher.stream.session = _this; + if (!publisher.stream.isLocalStreamPublished) { + _this.connection.addStream(publisher.stream); + publisher.stream.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + } + else { + publisher.initialize() + .then(function () { + _this.connection.addStream(publisher.stream); + publisher.reestablishStreamPlayingEvent(); + publisher.stream.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }).catch(function (error) { + reject(error); + }); + } + }); + }; + Session.prototype.unpublish = function (publisher) { + var stream = publisher.stream; + if (!stream.connection) { + console.error('The associated Connection object of this Publisher is null', stream); + return; + } + else if (stream.connection !== this.connection) { + console.error('The associated Connection object of this Publisher is not your local Connection.' + + "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); + return; + } + else { + console.info('Unpublishing local media (' + stream.connection.connectionId + ')'); + this.openvidu.sendRequest('unpublishVideo', function (error, response) { + if (error) { + console.error(error); + } + else { + console.info('Media unpublished correctly'); + } + }); + stream.disposeWebRtcPeer(); + delete stream.connection.stream; + var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish'); + publisher.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + } + }; + Session.prototype.signal = function (signal) { + var _this = this; + return new Promise(function (resolve, reject) { + var signalMessage = {}; + if (signal.to && signal.to.length > 0) { + var connectionIds_1 = []; + signal.to.forEach(function (connection) { + connectionIds_1.push(connection.connectionId); + }); + signalMessage['to'] = connectionIds_1; + } + else { + signalMessage['to'] = []; + } + signalMessage['data'] = signal.data ? signal.data : ''; + signalMessage['type'] = signal.type ? signal.type : ''; + _this.openvidu.sendRequest('sendMessage', { + message: JSON.stringify(signalMessage) + }, function (error, response) { + if (!!error) { + reject(error); + } + else { + resolve(); + } + }); + }); + }; + Session.prototype.on = function (type, handler) { + this.ee.on(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + type + "' triggered by 'Session'"); + } + handler(event); + }); + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = true; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !str.speechEvent && str.hasAudio) { + str.enableSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.once = function (type, handler) { + this.ee.once(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + type + "' triggered by 'Session'"); + } + handler(event); + }); + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = true; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !str.speechEvent && str.hasAudio) { + str.enableOnceSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.off = function (type, handler) { + if (!handler) { + this.ee.removeAllListeners(type); + } + else { + this.ee.off(type, handler); + } + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = false; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !!str.speechEvent) { + str.disableSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.onParticipantJoined = function (response) { + var _this = this; + this.getConnection(response.id, '') + .then(function (connection) { + console.warn('Connection ' + response.id + ' already exists in connections list'); + }) + .catch(function (openViduError) { + var connection = new Connection_1.Connection(_this, response); + _this.remoteConnections[response.id] = connection; + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); + }); + }; + Session.prototype.onParticipantLeft = function (msg) { + var _this = this; + this.getRemoteConnection(msg.name, 'Remote connection ' + msg.name + " unknown when 'onParticipantLeft'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (connection) { + if (!!connection.stream) { + var stream = connection.stream; + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + delete _this.remoteStreamsCreated[stream.streamId]; + } + delete _this.remoteConnections[connection.connectionId]; + _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onParticipantPublished = function (response) { + var _this = this; + var afterConnectionFound = function (connection) { + _this.remoteConnections[connection.connectionId] = connection; + if (!_this.remoteStreamsCreated[connection.stream.streamId]) { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]); + } + _this.remoteStreamsCreated[connection.stream.streamId] = true; + }; + var connection; + this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (con) { + connection = con; + response.metadata = con.data; + connection.options = response; + connection.initRemoteStreams(response.streams); + afterConnectionFound(connection); + }) + .catch(function (openViduError) { + connection = new Connection_1.Connection(_this, response); + afterConnectionFound(connection); + }); + }; + Session.prototype.onParticipantUnpublished = function (msg) { + var _this = this; + this.getRemoteConnection(msg.name, "Remote connection '" + msg.name + "' unknown when 'onParticipantUnpublished'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (connection) { + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + var streamId = connection.stream.streamId; + delete _this.remoteStreamsCreated[streamId]; + connection.removeStream(streamId); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onParticipantEvicted = function (msg) { + }; + Session.prototype.onNewMessage = function (msg) { + var _this = this; + console.info('New signal: ' + JSON.stringify(msg)); + this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: " + + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId) + .then(function (connection) { + _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); + _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.recvIceCandidate = function (msg) { + var candidate = { + candidate: msg.candidate, + sdpMid: msg.sdpMid, + sdpMLineIndex: msg.sdpMLineIndex, + toJSON: function () { + return { candidate: msg.candidate }; + } + }; + this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) + .then(function (connection) { + var stream = connection.stream; + stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) { + console.error('Error adding candidate for ' + stream.streamId + + ' stream of endpoint ' + msg.endpointName + ': ' + error); + }); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onSessionClosed = function (msg) { + console.info('Session closed: ' + JSON.stringify(msg)); + var s = msg.room; + if (s !== undefined) { + this.ee.emitEvent('session-closed', [{ + session: s + }]); + } + else { + console.warn('Session undefined on session closed', msg); + } + }; + Session.prototype.onLostConnection = function () { + console.warn('Lost connection in Session ' + this.sessionId); + if (!!this.sessionId && !this.connection.disposed) { + this.leave(true, 'networkDisconnect'); + } + }; + Session.prototype.onMediaError = function (params) { + console.error('Media error: ' + JSON.stringify(params)); + var err = params.error; + if (err) { + this.ee.emitEvent('error-media', [{ + error: err + }]); + } + else { + console.warn('Received undefined media error. Params:', params); + } + }; + Session.prototype.onRecordingStarted = function (response) { + this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]); + }; + Session.prototype.onRecordingStopped = function (response) { + this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]); + }; + Session.prototype.emitEvent = function (type, eventArray) { + this.ee.emitEvent(type, eventArray); + }; + Session.prototype.leave = function (forced, reason) { + var _this = this; + forced = !!forced; + console.info('Leaving Session (forced=' + forced + ')'); + if (!!this.connection) { + if (!this.connection.disposed && !forced) { + this.openvidu.sendRequest('leaveRoom', function (error, response) { + if (error) { + console.error(error); + } + _this.openvidu.closeWs(); + }); + } + else { + this.openvidu.closeWs(); + } + if (!!this.connection.stream) { + this.connection.stream.disposeWebRtcPeer(); + if (this.connection.stream.isLocalStreamPublished) { + this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); + } + } + if (!this.connection.disposed) { + var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason); + this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); + sessionDisconnectEvent.callDefaultBehaviour(); + } + } + else { + console.warn('You were not connected to the session ' + this.sessionId); + } + }; + Session.prototype.connectAux = function (token) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.openvidu.startWs(function (error) { + if (!!error) { + reject(error); + } + else { + var joinParams = { + token: (!!token) ? token : '', + session: _this.sessionId, + metadata: !!_this.options.metadata ? _this.options.metadata : '', + secret: _this.openvidu.getSecret(), + recorder: _this.openvidu.getRecorder(), + }; + _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { + if (!!error) { + reject(error); + } + else { + _this.connection = new Connection_1.Connection(_this); + _this.connection.connectionId = response.id; + _this.connection.data = response.metadata; + var events_1 = { + connections: new Array(), + streams: new Array() + }; + var existingParticipants = response.value; + existingParticipants.forEach(function (participant) { + var connection = new Connection_1.Connection(_this, participant); + _this.remoteConnections[connection.connectionId] = connection; + events_1.connections.push(connection); + if (!!connection.stream) { + _this.remoteStreamsCreated[connection.stream.streamId] = true; + events_1.streams.push(connection.stream); + } + }); + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]); + events_1.connections.forEach(function (connection) { + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); + }); + events_1.streams.forEach(function (stream) { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]); + }); + resolve(); + } + }); + } + }); + }); + }; + Session.prototype.stringClientMetadata = function (metadata) { + if (typeof metadata !== 'string') { + return JSON.stringify(metadata); + } + else { + return metadata; + } + }; + Session.prototype.getConnection = function (connectionId, errorMessage) { + var _this = this; + return new Promise(function (resolve, reject) { + var connection = _this.remoteConnections[connectionId]; + if (!!connection) { + resolve(connection); + } + else { + if (_this.connection.connectionId === connectionId) { + resolve(_this.connection); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); + } + } + }); + }; + Session.prototype.getRemoteConnection = function (connectionId, errorMessage) { + var _this = this; + return new Promise(function (resolve, reject) { + var connection = _this.remoteConnections[connectionId]; + if (!!connection) { + resolve(connection); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); + } + }); + }; + Session.prototype.processToken = function (token) { + var url = new URL(token); + this.sessionId = url.searchParams.get('sessionId'); + var secret = url.searchParams.get('secret'); + var recorder = url.searchParams.get('recorder'); + var turnUsername = url.searchParams.get('turnUsername'); + var turnCredential = url.searchParams.get('turnCredential'); + var role = url.searchParams.get('role'); + if (!!secret) { + this.openvidu.secret = secret; + } + if (!!recorder) { + this.openvidu.recorder = true; + } + if (!!turnUsername && !!turnCredential) { + var stunUrl = 'stun:' + url.hostname + ':3478'; + var turnUrl1 = 'turn:' + url.hostname + ':3478'; + var turnUrl2 = turnUrl1 + '?transport=tcp'; + this.openvidu.iceServers = [ + { urls: [stunUrl] }, + { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential } + ]; + console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']'); + } + if (!!role) { + this.openvidu.role = role; + } + this.openvidu.wsUri = 'wss://' + url.host + '/openvidu'; + }; + return Session; +}()); +exports.Session = Session; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer"); +var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats"); +var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent"); +var EventEmitter = require("wolfy87-eventemitter"); +var hark = require("hark"); +var Stream = (function () { + function Stream(session, options) { + var _this = this; + this.ee = new EventEmitter(); + this.isSubscribeToRemote = false; + this.isLocalStreamReadyToPublish = false; + this.isLocalStreamPublished = false; + this.session = session; + if (options.hasOwnProperty('id')) { + this.inboundStreamOpts = options; + this.streamId = this.inboundStreamOpts.id; + this.hasAudio = this.inboundStreamOpts.recvAudio; + this.hasVideo = this.inboundStreamOpts.recvVideo; + this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo; + this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; + } + else { + this.outboundStreamOpts = options; + if (this.isSendVideo()) { + if (this.isSendScreen()) { + this.typeOfVideo = 'SCREEN'; + } + else { + this.typeOfVideo = 'CAMERA'; + } + this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; + } + else { + delete this.typeOfVideo; + } + this.hasAudio = this.isSendAudio(); + this.hasVideo = this.isSendVideo(); + } + this.ee.on('mediastream-updated', function () { + _this.streamManager.updateMediaStream(_this.mediaStream); + console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']'); + }); + } + Stream.prototype.getMediaStream = function () { + return this.mediaStream; + }; + Stream.prototype.setMediaStream = function (mediaStream) { + this.mediaStream = mediaStream; + }; + Stream.prototype.updateMediaStreamInVideos = function () { + this.ee.emitEvent('mediastream-updated'); + }; + Stream.prototype.getWebRtcPeer = function () { + return this.webRtcPeer; + }; + Stream.prototype.getRTCPeerConnection = function () { + return this.webRtcPeer.pc; + }; + Stream.prototype.subscribeToMyRemote = function (value) { + this.isSubscribeToRemote = value; + }; + Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { + this.outboundStreamOpts = outboundStreamOpts; + }; + Stream.prototype.subscribe = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.initWebRtcPeerReceive() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + Stream.prototype.publish = function () { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.isLocalStreamReadyToPublish) { + _this.initWebRtcPeerSend() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + } + else { + _this.ee.once('stream-ready-to-publish', function () { + _this.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }); + } + }); + }; + Stream.prototype.disposeWebRtcPeer = function () { + if (this.webRtcPeer) { + this.webRtcPeer.dispose(); + } + if (this.speechEvent) { + this.speechEvent.stop(); + } + this.stopWebRtcStats(); + console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed'); + }; + Stream.prototype.disposeMediaStream = function () { + if (this.mediaStream) { + this.mediaStream.getAudioTracks().forEach(function (track) { + track.stop(); + }); + this.mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + delete this.mediaStream; + } + console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed'); + }; + Stream.prototype.displayMyRemote = function () { + return this.isSubscribeToRemote; + }; + Stream.prototype.isSendAudio = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.audioSource !== null && + this.outboundStreamOpts.publisherProperties.audioSource !== false); + }; + Stream.prototype.isSendVideo = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.videoSource !== null && + this.outboundStreamOpts.publisherProperties.videoSource !== false); + }; + Stream.prototype.isSendScreen = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.videoSource === 'screen'); + }; + Stream.prototype.setSpeechEventIfNotExists = function () { + if (!this.speechEvent) { + var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}; + harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50; + harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50; + this.speechEvent = hark(this.mediaStream, harkOptions); + } + }; + Stream.prototype.enableSpeakingEvents = function () { + var _this = this; + this.setSpeechEventIfNotExists(); + this.speechEvent.on('speaking', function () { + _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); + }); + this.speechEvent.on('stopped_speaking', function () { + _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); + }); + }; + Stream.prototype.enableOnceSpeakingEvents = function () { + var _this = this; + this.setSpeechEventIfNotExists(); + this.speechEvent.on('speaking', function () { + _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); + _this.disableSpeakingEvents(); + }); + this.speechEvent.on('stopped_speaking', function () { + _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); + _this.disableSpeakingEvents(); + }); + }; + Stream.prototype.disableSpeakingEvents = function () { + this.speechEvent.stop(); + this.speechEvent = undefined; + }; + Stream.prototype.isLocal = function () { + return (!this.inboundStreamOpts && !!this.outboundStreamOpts); + }; + Stream.prototype.getSelectedIceCandidate = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.webRtcStats.getSelectedIceCandidateInfo() + .then(function (report) { return resolve(report); }) + .catch(function (error) { return reject(error); }); + }); + }; + Stream.prototype.getRemoteIceCandidateList = function () { + return this.webRtcPeer.remoteCandidatesQueue; + }; + Stream.prototype.getLocalIceCandidateList = function () { + return this.webRtcPeer.localCandidatesQueue; + }; + Stream.prototype.initWebRtcPeerSend = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var userMediaConstraints = { + audio: _this.isSendAudio(), + video: _this.isSendVideo() + }; + var options = { + mediaStream: _this.mediaStream, + mediaConstraints: userMediaConstraints, + onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), + iceServers: _this.getIceServersConf(), + simulcast: false + }; + var successCallback = function (sdpOfferParam) { + console.debug('Sending SDP offer to publish as ' + + _this.streamId, sdpOfferParam); + _this.session.openvidu.sendRequest('publishVideo', { + sdpOffer: sdpOfferParam, + doLoopback: _this.displayMyRemote() || false, + audioActive: _this.isSendAudio(), + videoActive: _this.isSendVideo(), + typeOfVideo: ((_this.isSendVideo()) ? (_this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''), + frameRate: !!_this.frameRate ? _this.frameRate : -1 + }, function (error, response) { + if (error) { + reject('Error on publishVideo: ' + JSON.stringify(error)); + } + else { + _this.webRtcPeer.processAnswer(response.sdpAnswer) + .then(function () { + _this.streamId = response.id; + _this.isLocalStreamPublished = true; + if (_this.displayMyRemote()) { + _this.remotePeerSuccesfullyEstablished(); + } + _this.ee.emitEvent('stream-created-by-publisher'); + _this.initWebRtcStats(); + resolve(); + }) + .catch(function (error) { + reject(error); + }); + console.info("'Publisher' successfully published to session"); + } + }); + }; + if (_this.displayMyRemote()) { + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options); + } + else { + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options); + } + _this.webRtcPeer.generateOffer().then(function (offer) { + successCallback(offer); + }).catch(function (error) { + reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error))); + }); + }); + }; + Stream.prototype.initWebRtcPeerReceive = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var offerConstraints = { + audio: _this.inboundStreamOpts.recvAudio, + video: _this.inboundStreamOpts.recvVideo + }; + console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); + var options = { + onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), + mediaConstraints: offerConstraints, + iceServers: _this.getIceServersConf(), + simulcast: false + }; + var successCallback = function (sdpOfferParam) { + console.debug('Sending SDP offer to subscribe to ' + + _this.streamId, sdpOfferParam); + _this.session.openvidu.sendRequest('receiveVideoFrom', { + sender: _this.streamId, + sdpOffer: sdpOfferParam + }, function (error, response) { + if (error) { + reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error))); + } + else { + _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () { + _this.remotePeerSuccesfullyEstablished(); + _this.initWebRtcStats(); + resolve(); + }).catch(function (error) { + reject(error); + }); + } + }); + }; + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options); + _this.webRtcPeer.generateOffer() + .then(function (offer) { + successCallback(offer); + }) + .catch(function (error) { + reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error))); + }); + }); + }; + Stream.prototype.remotePeerSuccesfullyEstablished = function () { + this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0]; + console.debug('Peer remote stream', this.mediaStream); + if (!!this.mediaStream) { + this.ee.emitEvent('mediastream-updated'); + if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) { + this.enableSpeakingEvents(); + } + } + }; + Stream.prototype.initWebRtcStats = function () { + this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); + this.webRtcStats.initWebRtcStats(); + }; + Stream.prototype.stopWebRtcStats = function () { + if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { + this.webRtcStats.stopWebRtcStats(); + } + }; + Stream.prototype.getIceServersConf = function () { + var returnValue; + if (!!this.session.openvidu.advancedConfiguration.iceServers) { + returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ? + undefined : + this.session.openvidu.advancedConfiguration.iceServers; + } + else if (this.session.openvidu.iceServers) { + returnValue = this.session.openvidu.iceServers; + } + else { + returnValue = undefined; + } + return returnValue; + }; + return Stream; +}()); +exports.Stream = Stream; + +},{"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":48,"../OpenViduInternal/WebRtcStats/WebRtcStats":49,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); +var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var EventEmitter = require("wolfy87-eventemitter"); +var StreamManager = (function () { + function StreamManager(stream, targetElement) { + var _this = this; + this.videos = []; + this.lazyLaunchVideoElementCreatedEvent = false; + this.ee = new EventEmitter(); + this.stream = stream; + this.stream.streamManager = this; + this.remote = !this.stream.isLocal(); + if (!!targetElement) { + var targEl = void 0; + if (typeof targetElement === 'string') { + targEl = document.getElementById(targetElement); + } + else if (targetElement instanceof HTMLElement) { + targEl = targetElement; + } + if (!!targEl) { + this.firstVideoElement = { + targetElement: targEl, + video: document.createElement('video'), + id: '' + }; + this.targetElement = targEl; + this.element = targEl; + } + } + this.canPlayListener = function () { + if (_this.stream.isLocal()) { + if (!_this.stream.displayMyRemote()) { + console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); + } + else { + console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]); + } + } + else { + console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); + } + _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]); + }; + } + StreamManager.prototype.on = function (type, handler) { + this.ee.on(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered", event); + } + else { + console.info("Event '" + type + "' triggered"); + } + handler(event); + }); + if (type === 'videoElementCreated') { + if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); + this.lazyLaunchVideoElementCreatedEvent = false; + } + } + if (type === 'streamPlaying' || type === 'videoPlaying') { + if (this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); + this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); + } + } + return this; + }; + StreamManager.prototype.once = function (type, handler) { + this.ee.once(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered once", event); + } + else { + console.info("Event '" + type + "' triggered once"); + } + handler(event); + }); + if (type === 'videoElementCreated') { + if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); + } + } + if (type === 'streamPlaying' || type === 'videoPlaying') { + if (this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); + this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); + } + } + return this; + }; + StreamManager.prototype.off = function (type, handler) { + if (!handler) { + this.ee.removeAllListeners(type); + } + else { + this.ee.off(type, handler); + } + return this; + }; + StreamManager.prototype.addVideoElement = function (video) { + this.initializeVideoProperties(video); + for (var _i = 0, _a = this.videos; _i < _a.length; _i++) { + var v = _a[_i]; + if (v.video === video) { + return 0; + } + } + var returnNumber = 1; + this.initializeVideoProperties(video); + for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) { + var streamManager = _c[_b]; + if (streamManager.disassociateVideo(video)) { + returnNumber = -1; + break; + } + } + this.stream.session.streamManagers.forEach(function (streamManager) { + streamManager.disassociateVideo(video); + }); + this.pushNewStreamManagerVideo({ + video: video, + id: video.id + }); + console.info('New video element associated to ', this); + return returnNumber; + }; + StreamManager.prototype.createVideoElement = function (targetElement, insertMode) { + var targEl; + if (typeof targetElement === 'string') { + targEl = document.getElementById(targEl); + if (!targEl) { + throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); + } + } + else if (targetElement instanceof HTMLElement) { + targEl = targetElement; + } + else { + throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); + } + var video = document.createElement('video'); + this.initializeVideoProperties(video); + var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; + switch (insMode) { + case VideoInsertMode_1.VideoInsertMode.AFTER: + targEl.parentNode.insertBefore(video, targEl.nextSibling); + break; + case VideoInsertMode_1.VideoInsertMode.APPEND: + targEl.appendChild(video); + break; + case VideoInsertMode_1.VideoInsertMode.BEFORE: + targEl.parentNode.insertBefore(video, targEl); + break; + case VideoInsertMode_1.VideoInsertMode.PREPEND: + targEl.insertBefore(video, targEl.childNodes[0]); + break; + case VideoInsertMode_1.VideoInsertMode.REPLACE: + targEl.parentNode.replaceChild(video, targEl); + break; + default: + insMode = VideoInsertMode_1.VideoInsertMode.APPEND; + targEl.appendChild(video); + break; + } + var v = { + targetElement: targEl, + video: video, + insertMode: insMode, + id: video.id + }; + this.pushNewStreamManagerVideo(v); + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]); + this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement; + return video; + }; + StreamManager.prototype.initializeVideoProperties = function (video) { + video.srcObject = this.stream.getMediaStream(); + video.autoplay = true; + video.controls = false; + if (!video.id) { + video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId; + if (!this.id && !!this.targetElement) { + this.id = video.id; + } + } + if (!this.remote && !this.stream.displayMyRemote()) { + video.muted = true; + if (this.stream.outboundStreamOpts.publisherProperties.mirror) { + this.mirrorVideo(video); + } + } + }; + StreamManager.prototype.removeAllVideos = function () { + var _this = this; + for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) { + if (this.stream.session.streamManagers[i] === this) { + this.stream.session.streamManagers.splice(i, 1); + } + } + this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) { + streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener); + if (!!streamManagerVideo.targetElement) { + streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video); + _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]); + _this.videos.splice(videos.length - 1 - index, 1); + } + else { + streamManagerVideo.video.srcObject = null; + } + }); + }; + StreamManager.prototype.disassociateVideo = function (video) { + var disassociated = false; + for (var i = 0; i < this.videos.length; i++) { + if (this.videos[i].video === video) { + this.videos.splice(i, 1); + disassociated = true; + console.info('Video element disassociated from ', this); + break; + } + } + return disassociated; + }; + StreamManager.prototype.addPlayEventToFirstVideo = function () { + if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) { + this.videos[0].video.addEventListener('canplay', this.canPlayListener); + } + }; + StreamManager.prototype.updateMediaStream = function (mediaStream) { + this.videos.forEach(function (streamManagerVideo) { + streamManagerVideo.video.srcObject = mediaStream; + }); + }; + StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) { + this.videos.push(streamManagerVideo); + this.addPlayEventToFirstVideo(); + if (this.stream.session.streamManagers.indexOf(this) === -1) { + this.stream.session.streamManagers.push(this); + } + }; + StreamManager.prototype.mirrorVideo = function (video) { + video.style.transform = 'rotateY(180deg)'; + video.style.webkitTransform = 'rotateY(180deg)'; + }; + return StreamManager; +}()); +exports.StreamManager = StreamManager; + +},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":36,"wolfy87-eventemitter":15}],24:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var StreamManager_1 = require("./StreamManager"); +var Subscriber = (function (_super) { + __extends(Subscriber, _super); + function Subscriber(stream, targEl, properties) { + var _this = _super.call(this, stream, targEl) || this; + _this.element = _this.targetElement; + _this.stream = stream; + _this.properties = properties; + return _this; + } + Subscriber.prototype.subscribeToAudio = function (value) { + this.stream.getMediaStream().getAudioTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream'); + return this; + }; + Subscriber.prototype.subscribeToVideo = function (value) { + this.stream.getMediaStream().getVideoTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream'); + return this; + }; + return Subscriber; +}(StreamManager_1.StreamManager)); +exports.Subscriber = Subscriber; + +},{"./StreamManager":23}],25:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorderState; +(function (LocalRecorderState) { + LocalRecorderState["READY"] = "READY"; + LocalRecorderState["RECORDING"] = "RECORDING"; + LocalRecorderState["PAUSED"] = "PAUSED"; + LocalRecorderState["FINISHED"] = "FINISHED"; +})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {})); + +},{}],26:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduErrorName; +(function (OpenViduErrorName) { + OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; + OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED"; + OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; + OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; + OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; + OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED"; + OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; + OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; + OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; + OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; + OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; + OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED"; + OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; +})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); +var OpenViduError = (function () { + function OpenViduError(name, message) { + this.name = name; + this.message = message; + } + return OpenViduError; +}()); +exports.OpenViduError = OpenViduError; + +},{}],27:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var VideoInsertMode; +(function (VideoInsertMode) { + VideoInsertMode["AFTER"] = "AFTER"; + VideoInsertMode["APPEND"] = "APPEND"; + VideoInsertMode["BEFORE"] = "BEFORE"; + VideoInsertMode["PREPEND"] = "PREPEND"; + VideoInsertMode["REPLACE"] = "REPLACE"; +})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); + +},{}],28:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var ConnectionEvent = (function (_super) { + __extends(ConnectionEvent, _super); + function ConnectionEvent(cancelable, target, type, connection, reason) { + var _this = _super.call(this, cancelable, target, type) || this; + _this.connection = connection; + _this.reason = reason; + return _this; + } + ConnectionEvent.prototype.callDefaultBehaviour = function () { }; + return ConnectionEvent; +}(Event_1.Event)); +exports.ConnectionEvent = ConnectionEvent; + +},{"./Event":29}],29:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Event = (function () { + function Event(cancelable, target, type) { + this.hasBeenPrevented = false; + this.cancelable = cancelable; + this.target = target; + this.type = type; + } + Event.prototype.isDefaultPrevented = function () { + return this.hasBeenPrevented; + }; + Event.prototype.preventDefault = function () { + this.callDefaultBehaviour = function () { }; + this.hasBeenPrevented = true; + }; + return Event; +}()); +exports.Event = Event; + +},{}],30:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var PublisherSpeakingEvent = (function (_super) { + __extends(PublisherSpeakingEvent, _super); + function PublisherSpeakingEvent(target, type, connection, streamId) { + var _this = _super.call(this, false, target, type) || this; + _this.type = type; + _this.connection = connection; + _this.streamId = streamId; + return _this; + } + PublisherSpeakingEvent.prototype.callDefaultBehaviour = function () { }; + return PublisherSpeakingEvent; +}(Event_1.Event)); +exports.PublisherSpeakingEvent = PublisherSpeakingEvent; + +},{"./Event":29}],31:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var RecordingEvent = (function (_super) { + __extends(RecordingEvent, _super); + function RecordingEvent(target, type, id, name) { + var _this = _super.call(this, false, target, type) || this; + _this.id = id; + if (name !== id) { + _this.name = name; + } + return _this; + } + RecordingEvent.prototype.callDefaultBehaviour = function () { }; + return RecordingEvent; +}(Event_1.Event)); +exports.RecordingEvent = RecordingEvent; + +},{"./Event":29}],32:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var SessionDisconnectedEvent = (function (_super) { + __extends(SessionDisconnectedEvent, _super); + function SessionDisconnectedEvent(target, reason) { + var _this = _super.call(this, true, target, 'sessionDisconnected') || this; + _this.reason = reason; + return _this; + } + SessionDisconnectedEvent.prototype.callDefaultBehaviour = function () { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); + var session = this.target; + for (var connectionId in session.remoteConnections) { + if (!!session.remoteConnections[connectionId].stream) { + session.remoteConnections[connectionId].stream.disposeWebRtcPeer(); + session.remoteConnections[connectionId].stream.disposeMediaStream(); + if (session.remoteConnections[connectionId].stream.streamManager) { + session.remoteConnections[connectionId].stream.streamManager.removeAllVideos(); + } + delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId]; + session.remoteConnections[connectionId].dispose(); + } + delete session.remoteConnections[connectionId]; + } + }; + return SessionDisconnectedEvent; +}(Event_1.Event)); +exports.SessionDisconnectedEvent = SessionDisconnectedEvent; + +},{"./Event":29}],33:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var SignalEvent = (function (_super) { + __extends(SignalEvent, _super); + function SignalEvent(target, type, data, from) { + var _this = _super.call(this, false, target, type) || this; + _this.type = type; + _this.data = data; + _this.from = from; + return _this; + } + SignalEvent.prototype.callDefaultBehaviour = function () { }; + return SignalEvent; +}(Event_1.Event)); +exports.SignalEvent = SignalEvent; + +},{"./Event":29}],34:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var Publisher_1 = require("../../OpenVidu/Publisher"); +var Session_1 = require("../../OpenVidu/Session"); +var StreamEvent = (function (_super) { + __extends(StreamEvent, _super); + function StreamEvent(cancelable, target, type, stream, reason) { + var _this = _super.call(this, cancelable, target, type) || this; + _this.stream = stream; + _this.reason = reason; + return _this; + } + StreamEvent.prototype.callDefaultBehaviour = function () { + if (this.type === 'streamDestroyed') { + if (this.target instanceof Session_1.Session) { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); + this.stream.disposeWebRtcPeer(); + } + else if (this.target instanceof Publisher_1.Publisher) { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Publisher'"); + this.stream.isLocalStreamReadyToPublish = false; + } + this.stream.disposeMediaStream(); + if (this.stream.streamManager) + this.stream.streamManager.removeAllVideos(); + delete this.stream.session.remoteStreamsCreated[this.stream.streamId]; + var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId]; + if (!!remoteConnection && !!remoteConnection.options) { + var streamOptionsServer = remoteConnection.options.streams; + for (var i = streamOptionsServer.length - 1; i >= 0; --i) { + if (streamOptionsServer[i].id === this.stream.streamId) { + streamOptionsServer.splice(i, 1); + } + } + } + } + }; + return StreamEvent; +}(Event_1.Event)); +exports.StreamEvent = StreamEvent; + +},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var StreamManagerEvent = (function (_super) { + __extends(StreamManagerEvent, _super); + function StreamManagerEvent(target) { + return _super.call(this, false, target, 'streamPlaying') || this; + } + StreamManagerEvent.prototype.callDefaultBehaviour = function () { }; + return StreamManagerEvent; +}(Event_1.Event)); +exports.StreamManagerEvent = StreamManagerEvent; + +},{"./Event":29}],36:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var VideoElementEvent = (function (_super) { + __extends(VideoElementEvent, _super); + function VideoElementEvent(element, target, type) { + var _this = _super.call(this, false, target, type) || this; + _this.element = element; + return _this; + } + VideoElementEvent.prototype.callDefaultBehaviour = function () { }; + return VideoElementEvent; +}(Event_1.Event)); +exports.VideoElementEvent = VideoElementEvent; + +},{"./Event":29}],37:[function(require,module,exports){ +function Mapper() { + var sources = {}; + this.forEach = function (callback) { + for (var key in sources) { + var source = sources[key]; + for (var key2 in source) + callback(source[key2]); + } + ; + }; + this.get = function (id, source) { + var ids = sources[source]; + if (ids == undefined) + return undefined; + return ids[id]; + }; + this.remove = function (id, source) { + var ids = sources[source]; + if (ids == undefined) + return; + delete ids[id]; + for (var i in ids) { + return false; + } + delete sources[source]; + }; + this.set = function (value, id, source) { + if (value == undefined) + return this.remove(id, source); + var ids = sources[source]; + if (ids == undefined) + sources[source] = ids = {}; + ids[id] = value; + }; +} +; +Mapper.prototype.pop = function (id, source) { + var value = this.get(id, source); + if (value == undefined) + return undefined; + this.remove(id, source); + return value; +}; +module.exports = Mapper; + +},{}],38:[function(require,module,exports){ +var JsonRpcClient = require('./jsonrpcclient'); +exports.JsonRpcClient = JsonRpcClient; + +},{"./jsonrpcclient":39}],39:[function(require,module,exports){ +var RpcBuilder = require('../'); +var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); +Date.now = Date.now || function () { + return +new Date; +}; +var PING_INTERVAL = 5000; +var RECONNECTING = 'RECONNECTING'; +var CONNECTED = 'CONNECTED'; +var DISCONNECTED = 'DISCONNECTED'; +var Logger = console; +function JsonRpcClient(configuration) { + var self = this; + var wsConfig = configuration.ws; + var notReconnectIfNumLessThan = -1; + var pingNextNum = 0; + var enabledPings = true; + var pingPongStarted = false; + var pingInterval; + var status = DISCONNECTED; + var onreconnecting = wsConfig.onreconnecting; + var onreconnected = wsConfig.onreconnected; + var onconnected = wsConfig.onconnected; + var onerror = wsConfig.onerror; + configuration.rpc.pull = function (params, request) { + request.reply(null, "push"); + }; + wsConfig.onreconnecting = function () { + Logger.debug("--------- ONRECONNECTING -----------"); + if (status === RECONNECTING) { + Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it"); + return; + } + status = RECONNECTING; + if (onreconnecting) { + onreconnecting(); + } + }; + wsConfig.onreconnected = function () { + Logger.debug("--------- ONRECONNECTED -----------"); + if (status === CONNECTED) { + Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it"); + return; + } + status = CONNECTED; + enabledPings = true; + updateNotReconnectIfLessThan(); + usePing(); + if (onreconnected) { + onreconnected(); + } + }; + wsConfig.onconnected = function () { + Logger.debug("--------- ONCONNECTED -----------"); + if (status === CONNECTED) { + Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it"); + return; + } + status = CONNECTED; + enabledPings = true; + usePing(); + if (onconnected) { + onconnected(); + } + }; + wsConfig.onerror = function (error) { + Logger.debug("--------- ONERROR -----------"); + status = DISCONNECTED; + if (onerror) { + onerror(error); + } + }; + var ws = new WebSocketWithReconnection(wsConfig); + Logger.debug('Connecting websocket to URI: ' + wsConfig.uri); + var rpcBuilderOptions = { + request_timeout: configuration.rpc.requestTimeout, + ping_request_timeout: configuration.rpc.heartbeatRequestTimeout + }; + var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) { + Logger.debug('Received request: ' + JSON.stringify(request)); + try { + var func = configuration.rpc[request.method]; + if (func === undefined) { + Logger.error("Method " + request.method + " not registered in client"); + } + else { + func(request.params, request); + } + } + catch (err) { + Logger.error('Exception processing request: ' + JSON.stringify(request)); + Logger.error(err); + } + }); + this.send = function (method, params, callback) { + if (method !== 'ping') { + Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); + } + var requestTime = Date.now(); + rpc.encode(method, params, function (error, result) { + if (error) { + try { + Logger.error("ERROR:" + error.message + " in Request: method:" + + method + " params:" + JSON.stringify(params) + " request:" + + error.request); + if (error.data) { + Logger.error("ERROR DATA:" + JSON.stringify(error.data)); + } + } + catch (e) { } + error.requestTime = requestTime; + } + if (callback) { + if (result != undefined && result.value !== 'pong') { + Logger.debug('Response: ' + JSON.stringify(result)); + } + callback(error, result); + } + }); + }; + function updateNotReconnectIfLessThan() { + Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' + + notReconnectIfNumLessThan + ')'); + notReconnectIfNumLessThan = pingNextNum; + } + function sendPing() { + if (enabledPings) { + var params = null; + if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) { + params = { + interval: configuration.heartbeat || PING_INTERVAL + }; + } + pingNextNum++; + self.send('ping', params, (function (pingNum) { + return function (error, result) { + if (error) { + Logger.debug("Error in ping request #" + pingNum + " (" + + error.message + ")"); + if (pingNum > notReconnectIfNumLessThan) { + enabledPings = false; + updateNotReconnectIfLessThan(); + Logger.debug("Server did not respond to ping message #" + + pingNum + ". Reconnecting... "); + ws.reconnectWs(); + } + } + }; + })(pingNextNum)); + } + else { + Logger.debug("Trying to send ping, but ping is not enabled"); + } + } + function usePing() { + if (!pingPongStarted) { + Logger.debug("Starting ping (if configured)"); + pingPongStarted = true; + if (configuration.heartbeat != undefined) { + pingInterval = setInterval(sendPing, configuration.heartbeat); + sendPing(); + } + } + } + this.close = function () { + Logger.debug("Closing jsonRpcClient explicitly by client"); + if (pingInterval != undefined) { + Logger.debug("Clearing ping interval"); + clearInterval(pingInterval); + } + pingPongStarted = false; + enabledPings = false; + if (configuration.sendCloseMessage) { + Logger.debug("Sending close message"); + this.send('closeSession', null, function (error, result) { + if (error) { + Logger.error("Error sending close message: " + JSON.stringify(error)); + } + ws.close(); + }); + } + else { + ws.close(); + } + }; + this.forceClose = function (millis) { + ws.forceClose(millis); + }; + this.reconnect = function () { + ws.reconnectWs(); + }; +} +module.exports = JsonRpcClient; + +},{"../":42,"./transports/webSocketWithReconnection":41}],40:[function(require,module,exports){ +var WebSocketWithReconnection = require('./webSocketWithReconnection'); +exports.WebSocketWithReconnection = WebSocketWithReconnection; + +},{"./webSocketWithReconnection":41}],41:[function(require,module,exports){ +(function (global){ +"use strict"; +var BrowserWebSocket = global.WebSocket || global.MozWebSocket; +var Logger = console; +var MAX_RETRIES = 2000; +var RETRY_TIME_MS = 3000; +var CONNECTING = 0; +var OPEN = 1; +var CLOSING = 2; +var CLOSED = 3; +function WebSocketWithReconnection(config) { + var closing = false; + var registerMessageHandler; + var wsUri = config.uri; + var useSockJS = config.useSockJS; + var reconnecting = false; + var forcingDisconnection = false; + var ws; + if (useSockJS) { + ws = new SockJS(wsUri); + } + else { + ws = new WebSocket(wsUri); + } + ws.onopen = function () { + logConnected(ws, wsUri); + if (config.onconnected) { + config.onconnected(); + } + }; + ws.onerror = function (error) { + Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error); + if (config.onerror) { + config.onerror(error); + } + }; + function logConnected(ws, wsUri) { + try { + Logger.debug("WebSocket connected to " + wsUri); + } + catch (e) { + Logger.error(e); + } + } + var reconnectionOnClose = function () { + if (ws.readyState === CLOSED) { + if (closing) { + Logger.debug("Connection closed by user"); + } + else { + Logger.debug("Connection closed unexpectecly. Reconnecting..."); + reconnectToSameUri(MAX_RETRIES, 1); + } + } + else { + Logger.debug("Close callback from previous websocket. Ignoring it"); + } + }; + ws.onclose = reconnectionOnClose; + function reconnectToSameUri(maxRetries, numRetries) { + Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); + if (numRetries === 1) { + if (reconnecting) { + Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); + return; + } + else { + reconnecting = true; + } + if (config.onreconnecting) { + config.onreconnecting(); + } + } + if (forcingDisconnection) { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + else { + if (config.newWsUriOnReconnection) { + config.newWsUriOnReconnection(function (error, newWsUri) { + if (error) { + Logger.debug(error); + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + else { + reconnectToNewUri(maxRetries, numRetries, newWsUri); + } + }); + } + else { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + } + } + function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { + Logger.debug("Reconnection attempt #" + numRetries); + ws.close(); + wsUri = reconnectWsUri || wsUri; + var newWs; + if (useSockJS) { + newWs = new SockJS(wsUri); + } + else { + newWs = new WebSocket(wsUri); + } + newWs.onopen = function () { + Logger.debug("Reconnected after " + numRetries + " attempts..."); + logConnected(newWs, wsUri); + reconnecting = false; + registerMessageHandler(); + if (config.onreconnected()) { + config.onreconnected(); + } + newWs.onclose = reconnectionOnClose; + }; + var onErrorOrClose = function (error) { + Logger.warn("Reconnection error: ", error); + if (numRetries === maxRetries) { + if (config.ondisconnect) { + config.ondisconnect(); + } + } + else { + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + }; + newWs.onerror = onErrorOrClose; + ws = newWs; + } + this.close = function () { + closing = true; + ws.close(); + }; + this.forceClose = function (millis) { + Logger.debug("Testing: Force WebSocket close"); + if (millis) { + Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); + var goodWsUri = wsUri; + wsUri = "wss://21.234.12.34.4:443/"; + forcingDisconnection = true; + setTimeout(function () { + Logger.debug("Testing: Recover good wsUri " + goodWsUri); + wsUri = goodWsUri; + forcingDisconnection = false; + }, millis); + } + ws.close(); + }; + this.reconnectWs = function () { + Logger.debug("reconnectWs"); + reconnectToSameUri(MAX_RETRIES, 1, wsUri); + }; + this.send = function (message) { + ws.send(message); + }; + this.addEventListener = function (type, callback) { + registerMessageHandler = function () { + ws.addEventListener(type, callback); + }; + registerMessageHandler(); + }; +} +module.exports = WebSocketWithReconnection; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],42:[function(require,module,exports){ +var defineProperty_IE8 = false; +if (Object.defineProperty) { + try { + Object.defineProperty({}, "x", {}); + } + catch (e) { + defineProperty_IE8 = true; + } +} +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== 'function') { + throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); + }; + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + return fBound; + }; +} +var EventEmitter = require('events').EventEmitter; +var inherits = require('inherits'); +var packers = require('./packers'); +var Mapper = require('./Mapper'); +var BASE_TIMEOUT = 5000; +function unifyResponseMethods(responseMethods) { + if (!responseMethods) + return {}; + for (var key in responseMethods) { + var value = responseMethods[key]; + if (typeof value == 'string') + responseMethods[key] = + { + response: value + }; + } + ; + return responseMethods; +} +; +function unifyTransport(transport) { + if (!transport) + return; + if (transport instanceof Function) + return { send: transport }; + if (transport.send instanceof Function) + return transport; + if (transport.postMessage instanceof Function) { + transport.send = transport.postMessage; + return transport; + } + if (transport.write instanceof Function) { + transport.send = transport.write; + return transport; + } + if (transport.onmessage !== undefined) + return; + if (transport.pause instanceof Function) + return; + throw new SyntaxError("Transport is not a function nor a valid object"); +} +; +function RpcNotification(method, params) { + if (defineProperty_IE8) { + this.method = method; + this.params = params; + } + else { + Object.defineProperty(this, 'method', { value: method, enumerable: true }); + Object.defineProperty(this, 'params', { value: params, enumerable: true }); + } +} +; +function RpcBuilder(packer, options, transport, onRequest) { + var self = this; + if (!packer) + throw new SyntaxError('Packer is not defined'); + if (!packer.pack || !packer.unpack) + throw new SyntaxError('Packer is invalid'); + var responseMethods = unifyResponseMethods(packer.responseMethods); + if (options instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after onRequest"); + onRequest = options; + transport = undefined; + options = undefined; + } + ; + if (options && options.send instanceof Function) { + if (transport && !(transport instanceof Function)) + throw new SyntaxError("Only a function can be after transport"); + onRequest = transport; + transport = options; + options = undefined; + } + ; + if (transport instanceof Function) { + if (onRequest != undefined) + throw new SyntaxError("There can't be parameters after onRequest"); + onRequest = transport; + transport = undefined; + } + ; + if (transport && transport.send instanceof Function) + if (onRequest && !(onRequest instanceof Function)) + throw new SyntaxError("Only a function can be after transport"); + options = options || {}; + EventEmitter.call(this); + if (onRequest) + this.on('request', onRequest); + if (defineProperty_IE8) + this.peerID = options.peerID; + else + Object.defineProperty(this, 'peerID', { value: options.peerID }); + var max_retries = options.max_retries || 0; + function transportMessage(event) { + self.decode(event.data || event); + } + ; + this.getTransport = function () { + return transport; + }; + this.setTransport = function (value) { + if (transport) { + if (transport.removeEventListener) + transport.removeEventListener('message', transportMessage); + else if (transport.removeListener) + transport.removeListener('data', transportMessage); + } + ; + if (value) { + if (value.addEventListener) + value.addEventListener('message', transportMessage); + else if (value.addListener) + value.addListener('data', transportMessage); + } + ; + transport = unifyTransport(value); + }; + if (!defineProperty_IE8) + Object.defineProperty(this, 'transport', { + get: this.getTransport.bind(this), + set: this.setTransport.bind(this) + }); + this.setTransport(transport); + var request_timeout = options.request_timeout || BASE_TIMEOUT; + var ping_request_timeout = options.ping_request_timeout || request_timeout; + var response_timeout = options.response_timeout || BASE_TIMEOUT; + var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT; + var requestID = 0; + var requests = new Mapper(); + var responses = new Mapper(); + var processedResponses = new Mapper(); + var message2Key = {}; + function storeResponse(message, id, dest) { + var response = { + message: message, + timeout: setTimeout(function () { + responses.remove(id, dest); + }, response_timeout) + }; + responses.set(response, id, dest); + } + ; + function storeProcessedResponse(ack, from) { + var timeout = setTimeout(function () { + processedResponses.remove(ack, from); + }, duplicates_timeout); + processedResponses.set(timeout, ack, from); + } + ; + function RpcRequest(method, params, id, from, transport) { + RpcNotification.call(this, method, params); + this.getTransport = function () { + return transport; + }; + this.setTransport = function (value) { + transport = unifyTransport(value); + }; + if (!defineProperty_IE8) + Object.defineProperty(this, 'transport', { + get: this.getTransport.bind(this), + set: this.setTransport.bind(this) + }); + var response = responses.get(id, from); + if (!(transport || self.getTransport())) { + if (defineProperty_IE8) + this.duplicated = Boolean(response); + else + Object.defineProperty(this, 'duplicated', { + value: Boolean(response) + }); + } + var responseMethod = responseMethods[method]; + this.pack = packer.pack.bind(packer, this, id); + this.reply = function (error, result, transport) { + if (error instanceof Function || error && error.send instanceof Function) { + if (result != undefined) + throw new SyntaxError("There can't be parameters after callback"); + transport = error; + result = null; + error = undefined; + } + else if (result instanceof Function + || result && result.send instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after callback"); + transport = result; + result = null; + } + ; + transport = unifyTransport(transport); + if (response) + clearTimeout(response.timeout); + if (from != undefined) { + if (error) + error.dest = from; + if (result) + result.dest = from; + } + ; + var message; + if (error || result != undefined) { + if (self.peerID != undefined) { + if (error) + error.from = self.peerID; + else + result.from = self.peerID; + } + if (responseMethod) { + if (responseMethod.error == undefined && error) + message = + { + error: error + }; + else { + var method = error + ? responseMethod.error + : responseMethod.response; + message = + { + method: method, + params: error || result + }; + } + } + else + message = + { + error: error, + result: result + }; + message = packer.pack(message, id); + } + else if (response) + message = response.message; + else + message = packer.pack({ result: null }, id); + storeResponse(message, id, from); + transport = transport || this.getTransport() || self.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + } + ; + inherits(RpcRequest, RpcNotification); + function cancel(message) { + var key = message2Key[message]; + if (!key) + return; + delete message2Key[message]; + var request = requests.pop(key.id, key.dest); + if (!request) + return; + clearTimeout(request.timeout); + storeProcessedResponse(key.id, key.dest); + } + ; + this.cancel = function (message) { + if (message) + return cancel(message); + for (var message in message2Key) + cancel(message); + }; + this.close = function () { + var transport = this.getTransport(); + if (transport && transport.close) + transport.close(); + this.cancel(); + processedResponses.forEach(clearTimeout); + responses.forEach(function (response) { + clearTimeout(response.timeout); + }); + }; + this.encode = function (method, params, dest, transport, callback) { + if (params instanceof Function) { + if (dest != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = params; + transport = undefined; + dest = undefined; + params = undefined; + } + else if (dest instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = dest; + transport = undefined; + dest = undefined; + } + else if (transport instanceof Function) { + if (callback != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = transport; + transport = undefined; + } + ; + if (self.peerID != undefined) { + params = params || {}; + params.from = self.peerID; + } + ; + if (dest != undefined) { + params = params || {}; + params.dest = dest; + } + ; + var message = { + method: method, + params: params + }; + if (callback) { + var id = requestID++; + var retried = 0; + message = packer.pack(message, id); + function dispatchCallback(error, result) { + self.cancel(message); + callback(error, result); + } + ; + var request = { + message: message, + callback: dispatchCallback, + responseMethods: responseMethods[method] || {} + }; + var encode_transport = unifyTransport(transport); + function sendRequest(transport) { + var rt = (method === 'ping' ? ping_request_timeout : request_timeout); + request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++)); + message2Key[message] = { id: id, dest: dest }; + requests.set(request, id, dest); + transport = transport || encode_transport || self.getTransport(); + if (transport) + return transport.send(message); + return message; + } + ; + function retry(transport) { + transport = unifyTransport(transport); + console.warn(retried + ' retry for request message:', message); + var timeout = processedResponses.pop(id, dest); + clearTimeout(timeout); + return sendRequest(transport); + } + ; + function timeout() { + if (retried < max_retries) + return retry(transport); + var error = new Error('Request has timed out'); + error.request = message; + error.retry = retry; + dispatchCallback(error); + } + ; + return sendRequest(transport); + } + ; + message = packer.pack(message); + transport = transport || this.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + this.decode = function (message, transport) { + if (!message) + throw new TypeError("Message is not defined"); + try { + message = packer.unpack(message); + } + catch (e) { + return console.debug(e, message); + } + ; + var id = message.id; + var ack = message.ack; + var method = message.method; + var params = message.params || {}; + var from = params.from; + var dest = params.dest; + if (self.peerID != undefined && from == self.peerID) + return; + if (id == undefined && ack == undefined) { + var notification = new RpcNotification(method, params); + if (self.emit('request', notification)) + return; + return notification; + } + ; + function processRequest() { + transport = unifyTransport(transport) || self.getTransport(); + if (transport) { + var response = responses.get(id, from); + if (response) + return transport.send(response.message); + } + ; + var idAck = (id != undefined) ? id : ack; + var request = new RpcRequest(method, params, idAck, from, transport); + if (self.emit('request', request)) + return; + return request; + } + ; + function processResponse(request, error, result) { + request.callback(error, result); + } + ; + function duplicatedResponse(timeout) { + console.warn("Response already processed", message); + clearTimeout(timeout); + storeProcessedResponse(ack, from); + } + ; + if (method) { + if (dest == undefined || dest == self.peerID) { + var request = requests.get(ack, from); + if (request) { + var responseMethods = request.responseMethods; + if (method == responseMethods.error) + return processResponse(request, params); + if (method == responseMethods.response) + return processResponse(request, null, params); + return processRequest(); + } + var processed = processedResponses.get(ack, from); + if (processed) + return duplicatedResponse(processed); + } + return processRequest(); + } + ; + var error = message.error; + var result = message.result; + if (error && error.dest && error.dest != self.peerID) + return; + if (result && result.dest && result.dest != self.peerID) + return; + var request = requests.get(ack, from); + if (!request) { + var processed = processedResponses.get(ack, from); + if (processed) + return duplicatedResponse(processed); + return console.warn("No callback was defined for this message", message); + } + ; + processResponse(request, error, result); + }; +} +; +inherits(RpcBuilder, EventEmitter); +RpcBuilder.RpcNotification = RpcNotification; +module.exports = RpcBuilder; +var clients = require('./clients'); +var transports = require('./clients/transports'); +RpcBuilder.clients = clients; +RpcBuilder.clients.transports = transports; +RpcBuilder.packers = packers; + +},{"./Mapper":37,"./clients":38,"./clients/transports":40,"./packers":45,"events":1,"inherits":6}],43:[function(require,module,exports){ +function pack(message, id) { + var result = { + jsonrpc: "2.0" + }; + if (message.method) { + result.method = message.method; + if (message.params) + result.params = message.params; + if (id != undefined) + result.id = id; + } + else if (id != undefined) { + if (message.error) { + if (message.result !== undefined) + throw new TypeError("Both result and error are defined"); + result.error = message.error; + } + else if (message.result !== undefined) + result.result = message.result; + else + throw new TypeError("No result or error is defined"); + result.id = id; + } + ; + return JSON.stringify(result); +} +; +function unpack(message) { + var result = message; + if (typeof message === 'string' || message instanceof String) { + result = JSON.parse(message); + } + var version = result.jsonrpc; + if (version !== '2.0') + throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); + if (result.method == undefined) { + if (result.id == undefined) + throw new TypeError("Invalid message: " + message); + var result_defined = result.result !== undefined; + var error_defined = result.error !== undefined; + if (result_defined && error_defined) + throw new TypeError("Both result and error are defined: " + message); + if (!result_defined && !error_defined) + throw new TypeError("No result or error is defined: " + message); + result.ack = result.id; + delete result.id; + } + return result; +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],44:[function(require,module,exports){ +function pack(message) { + throw new TypeError("Not yet implemented"); +} +; +function unpack(message) { + throw new TypeError("Not yet implemented"); +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],45:[function(require,module,exports){ +var JsonRPC = require('./JsonRPC'); +var XmlRPC = require('./XmlRPC'); +exports.JsonRPC = JsonRPC; +exports.XmlRPC = XmlRPC; + +},{"./JsonRPC":43,"./XmlRPC":44}],46:[function(require,module,exports){ +window.getScreenId = function (callback, custom_parameter) { + if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) { + callback({ + video: true + }); + return; + } + if (!!navigator.mozGetUserMedia) { + callback(null, 'firefox', { + video: { + mozMediaSource: 'window', + mediaSource: 'window' + } + }); + return; + } + window.addEventListener('message', onIFrameCallback); + function onIFrameCallback(event) { + if (!event.data) + return; + if (event.data.chromeMediaSourceId) { + if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { + callback('permission-denied'); + } + else { + callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack)); + } + window.removeEventListener('message', onIFrameCallback); + } + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); + window.removeEventListener('message', onIFrameCallback); + } + } + if (!custom_parameter) { + setTimeout(postGetSourceIdMessage, 100); + } + else { + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); + } +}; +function getScreenConstraints(error, sourceId, canRequestAudioTrack) { + var screen_constraints = { + audio: false, + video: { + mandatory: { + chromeMediaSource: error ? 'screen' : 'desktop', + maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, + maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 + }, + optional: [] + } + }; + if (!!canRequestAudioTrack) { + screen_constraints.audio = { + mandatory: { + chromeMediaSource: error ? 'screen' : 'desktop', + }, + optional: [] + }; + } + if (sourceId) { + screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; + if (screen_constraints.audio && screen_constraints.audio.mandatory) { + screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId; + } + } + return screen_constraints; +} +function postGetSourceIdMessage(custom_parameter) { + if (!iframe) { + loadIFrame(function () { + postGetSourceIdMessage(custom_parameter); + }); + return; + } + if (!iframe.isLoaded) { + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); + return; + } + if (!custom_parameter) { + iframe.contentWindow.postMessage({ + captureSourceId: true + }, '*'); + } + else if (!!custom_parameter.forEach) { + iframe.contentWindow.postMessage({ + captureCustomSourceId: custom_parameter + }, '*'); + } + else { + iframe.contentWindow.postMessage({ + captureSourceIdWithAudio: true + }, '*'); + } +} +var iframe; +window.getScreenConstraints = function (callback) { + loadIFrame(function () { + getScreenId(function (error, sourceId, screen_constraints) { + if (!screen_constraints) { + screen_constraints = { + video: true + }; + } + callback(error, screen_constraints.video); + }); + }); +}; +function loadIFrame(loadCallback) { + if (iframe) { + loadCallback(); + return; + } + iframe = document.createElement('iframe'); + iframe.onload = function () { + iframe.isLoaded = true; + loadCallback(); + }; + iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/'; + iframe.style.display = 'none'; + (document.body || document.documentElement).appendChild(iframe); +} +window.getChromeExtensionStatus = function (callback) { + if (!!navigator.mozGetUserMedia) { + callback('installed-enabled'); + return; + } + window.addEventListener('message', onIFrameCallback); + function onIFrameCallback(event) { + if (!event.data) + return; + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus); + window.removeEventListener('message', onIFrameCallback); + } + } + setTimeout(postGetChromeExtensionStatusMessage, 100); +}; +function postGetChromeExtensionStatusMessage() { + if (!iframe) { + loadIFrame(postGetChromeExtensionStatusMessage); + return; + } + if (!iframe.isLoaded) { + setTimeout(postGetChromeExtensionStatusMessage, 100); + return; + } + iframe.contentWindow.postMessage({ + getChromeExtensionStatus: true + }, '*'); +} +exports.getScreenId = getScreenId; + +},{}],47:[function(require,module,exports){ +var chromeMediaSource = 'screen'; +var sourceId; +var screenCallback; +var isFirefox = typeof window.InstallTrigger !== 'undefined'; +var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; +var isChrome = !!window.chrome && !isOpera; +window.addEventListener('message', function (event) { + if (event.origin != window.location.origin) { + return; + } + onMessageCallback(event.data); +}); +function onMessageCallback(data) { + if (data == 'PermissionDeniedError') { + if (screenCallback) + return screenCallback('PermissionDeniedError'); + else + throw new Error('PermissionDeniedError'); + } + if (data == 'rtcmulticonnection-extension-loaded') { + chromeMediaSource = 'desktop'; + } + if (data.sourceId && screenCallback) { + screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true); + } +} +function isChromeExtensionAvailable(callback) { + if (!callback) + return; + if (chromeMediaSource == 'desktop') + return callback(true); + window.postMessage('are-you-there', '*'); + setTimeout(function () { + if (chromeMediaSource == 'screen') { + callback(false); + } + else + callback(true); + }, 2000); +} +function getSourceId(callback) { + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage('get-sourceId', '*'); +} +function getCustomSourceId(arr, callback) { + if (!arr || !arr.forEach) + throw '"arr" parameter is mandatory and it must be an array.'; + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage({ + 'get-custom-sourceId': arr + }, '*'); +} +function getSourceIdWithAudio(callback) { + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage('audio-plus-tab', '*'); +} +function getChromeExtensionStatus(extensionid, callback) { + if (isFirefox) + return callback('not-chrome'); + if (arguments.length != 2) { + callback = extensionid; + extensionid = 'lfcgfepafnobdloecchnfaclibenjold'; + } + var image = document.createElement('img'); + image.src = 'chrome-extension://' + extensionid + '/icon.png'; + image.onload = function () { + chromeMediaSource = 'screen'; + window.postMessage('are-you-there', '*'); + setTimeout(function () { + if (chromeMediaSource == 'screen') { + callback('installed-disabled'); + } + else + callback('installed-enabled'); + }, 2000); + }; + image.onerror = function () { + callback('not-installed'); + }; +} +function getScreenConstraintsWithAudio(callback) { + getScreenConstraints(callback, true); +} +function getScreenConstraints(callback, captureSourceIdWithAudio) { + sourceId = ''; + var firefoxScreenConstraints = { + mozMediaSource: 'window', + mediaSource: 'window' + }; + if (isFirefox) + return callback(null, firefoxScreenConstraints); + var screen_constraints = { + mandatory: { + chromeMediaSource: chromeMediaSource, + maxWidth: screen.width > 1920 ? screen.width : 1920, + maxHeight: screen.height > 1080 ? screen.height : 1080 + }, + optional: [] + }; + if (chromeMediaSource == 'desktop' && !sourceId) { + if (captureSourceIdWithAudio) { + getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + if (canRequestAudioTrack) { + screen_constraints.canRequestAudioTrack = true; + } + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } + else { + getSourceId(function (sourceId) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } + return; + } + if (chromeMediaSource == 'desktop') { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + } + callback(null, screen_constraints); +} +exports.getScreenConstraints = getScreenConstraints; +exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio; +exports.isChromeExtensionAvailable = isChromeExtensionAvailable; +exports.getChromeExtensionStatus = getChromeExtensionStatus; +exports.getSourceId = getSourceId; + +},{}],48:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var freeice = require("freeice"); +var uuid = require("uuid"); +var platform = require("platform"); +var WebRtcPeer = (function () { + function WebRtcPeer(configuration) { + var _this = this; + this.configuration = configuration; + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.iceCandidateList = []; + this.candidategatheringdone = false; + this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice(); + this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers }); + this.id = !!configuration.id ? configuration.id : uuid.v4(); + this.pc.onicecandidate = function (event) { + var candidate = event.candidate; + if (candidate) { + _this.localCandidatesQueue.push({ candidate: candidate.candidate }); + _this.candidategatheringdone = false; + _this.configuration.onicecandidate(event.candidate); + } + else if (!_this.candidategatheringdone) { + _this.candidategatheringdone = true; + } + }; + this.pc.onsignalingstatechange = function () { + if (_this.pc.signalingState === 'stable') { + while (_this.iceCandidateList.length > 0) { + _this.pc.addIceCandidate(_this.iceCandidateList.shift()); + } + } + }; + this.start(); + } + WebRtcPeer.prototype.start = function () { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.pc.signalingState === 'closed') { + reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); + } + if (!!_this.configuration.mediaStream) { + _this.pc.addStream(_this.configuration.mediaStream); + } + if (_this.configuration.mode === 'sendonly' && + (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) { + _this.configuration.mode = 'sendrecv'; + } + resolve(); + }); + }; + WebRtcPeer.prototype.dispose = function () { + var _this = this; + console.debug('Disposing WebRtcPeer'); + try { + if (this.pc) { + if (this.pc.signalingState === 'closed') { + return; + } + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.pc.getLocalStreams().forEach(function (str) { + _this.streamStop(str); + }); + this.pc.close(); + } + } + catch (err) { + console.warn('Exception disposing webrtc peer ' + err); + } + }; + WebRtcPeer.prototype.generateOffer = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var offerAudio, offerVideo = true; + if (!!_this.configuration.mediaConstraints) { + offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ? + _this.configuration.mediaConstraints.audio : true; + offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ? + _this.configuration.mediaConstraints.video : true; + } + var constraints = { + offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio), + offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo) + }; + console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints)); + _this.pc.createOffer(constraints).then(function (offer) { + console.debug('Created SDP offer'); + return _this.pc.setLocalDescription(offer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.processOffer = function (sdpOffer) { + var _this = this; + return new Promise(function (resolve, reject) { + var offer = { + type: 'offer', + sdp: sdpOffer + }; + console.debug('SDP offer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('PeerConnection is closed'); + } + _this.pc.setRemoteDescription(offer) + .then(function () { + return _this.pc.createAnswer(); + }).then(function (answer) { + console.debug('Created SDP answer'); + return _this.pc.setLocalDescription(answer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.processAnswer = function (sdpAnswer) { + var _this = this; + return new Promise(function (resolve, reject) { + var answer = { + type: 'answer', + sdp: sdpAnswer + }; + console.debug('SDP answer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('RTCPeerConnection is closed'); + } + _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) { + var _this = this; + return new Promise(function (resolve, reject) { + console.debug('Remote ICE candidate received', iceCandidate); + _this.remoteCandidatesQueue.push(iceCandidate); + switch (_this.pc.signalingState) { + case 'closed': + reject(new Error('PeerConnection object is closed')); + break; + case 'stable': + if (!!_this.pc.remoteDescription) { + _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); }); + } + break; + default: + _this.iceCandidateList.push(iceCandidate); + resolve(); + } + }); + }; + WebRtcPeer.prototype.streamStop = function (stream) { + stream.getTracks().forEach(function (track) { + track.stop(); + stream.removeTrack(track); + }); + }; + return WebRtcPeer; +}()); +exports.WebRtcPeer = WebRtcPeer; +var WebRtcPeerRecvonly = (function (_super) { + __extends(WebRtcPeerRecvonly, _super); + function WebRtcPeerRecvonly(configuration) { + var _this = this; + configuration.mode = 'recvonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerRecvonly; +}(WebRtcPeer)); +exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; +var WebRtcPeerSendonly = (function (_super) { + __extends(WebRtcPeerSendonly, _super); + function WebRtcPeerSendonly(configuration) { + var _this = this; + configuration.mode = 'sendonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendonly; +}(WebRtcPeer)); +exports.WebRtcPeerSendonly = WebRtcPeerSendonly; +var WebRtcPeerSendrecv = (function (_super) { + __extends(WebRtcPeerSendrecv, _super); + function WebRtcPeerSendrecv(configuration) { + var _this = this; + configuration.mode = 'sendrecv'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendrecv; +}(WebRtcPeer)); +exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; + +},{"freeice":2,"platform":8,"uuid":9}],49:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var platform = require("platform"); +var WebRtcStats = (function () { + function WebRtcStats(stream) { + this.stream = stream; + this.webRtcStatsEnabled = false; + this.statsInterval = 1; + this.stats = { + inbound: { + audio: { + bytesReceived: 0, + packetsReceived: 0, + packetsLost: 0 + }, + video: { + bytesReceived: 0, + packetsReceived: 0, + packetsLost: 0, + framesDecoded: 0, + nackCount: 0 + } + }, + outbound: { + audio: { + bytesSent: 0, + packetsSent: 0, + }, + video: { + bytesSent: 0, + packetsSent: 0, + framesEncoded: 0, + nackCount: 0 + } + } + }; + } + WebRtcStats.prototype.isEnabled = function () { + return this.webRtcStatsEnabled; + }; + WebRtcStats.prototype.initWebRtcStats = function () { + var _this = this; + var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); + if (elastestInstrumentation) { + console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); + this.webRtcStatsEnabled = true; + var instrumentation_1 = JSON.parse(elastestInstrumentation); + this.statsInterval = instrumentation_1.webrtc.interval; + console.warn('localStorage item: ' + JSON.stringify(instrumentation_1)); + this.webRtcStatsIntervalId = setInterval(function () { + _this.sendStatsToHttpEndpoint(instrumentation_1); + }, this.statsInterval * 1000); + return; + } + console.debug('WebRtc stats not enabled'); + }; + WebRtcStats.prototype.stopWebRtcStats = function () { + if (this.webRtcStatsEnabled) { + clearInterval(this.webRtcStatsIntervalId); + console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); + } + }; + WebRtcStats.prototype.getSelectedIceCandidateInfo = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) { + if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0; + var localCandidates = {}; + var remoteCandidates = {}; + for (var key in stats) { + var stat = stats[key]; + if (stat.type === 'localcandidate') { + localCandidates[stat.id] = stat; + } + else if (stat.type === 'remotecandidate') { + remoteCandidates[stat.id] = stat; + } + else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) { + googCandidatePair = stat; + localCandidateId = stat.localCandidateId; + remoteCandidateId = stat.remoteCandidateId; + } + } + var finalLocalCandidate_1 = localCandidates[localCandidateId]; + if (!!finalLocalCandidate_1) { + var candList = _this.stream.getLocalIceCandidateList(); + var cand = candList.filter(function (c) { + return (!!c.candidate && + c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 && + c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 && + c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0); + }); + finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates'; + } + else { + finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used'; + } + var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId]; + if (!!finalRemoteCandidate_1) { + var candList = _this.stream.getRemoteIceCandidateList(); + var cand = candList.filter(function (c) { + return (!!c.candidate && + c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 && + c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 && + c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0); + }); + finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates'; + } + else { + finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used'; + } + resolve({ + googCandidatePair: googCandidatePair, + localCandidate: finalLocalCandidate_1, + remoteCandidate: finalRemoteCandidate_1 + }); + } + else { + reject('Selected ICE candidate info only available for Chrome'); + } + }, function (error) { + reject(error); + }); + }); + }; + WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { + var _this = this; + var sendPost = function (json) { + var http = new XMLHttpRequest(); + var url = instrumentation.webrtc.httpEndpoint; + http.open('POST', url, true); + http.setRequestHeader('Content-type', 'application/json'); + http.onreadystatechange = function () { + if (http.readyState === 4 && http.status === 200) { + console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId); + } + }; + http.send(json); + }; + var f = function (stats) { + if (platform.name.indexOf('Firefox') !== -1) { + stats.forEach(function (stat) { + var json = {}; + if ((stat.type === 'inbound-rtp') && + (stat.nackCount !== null && + stat.isRemote === false && + stat.id.startsWith('inbound') && + stat.remoteId.startsWith('inbound'))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var jit = stat.jitter * 1000; + var metrics = { + bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + jitter: jit, + packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + bytesReceived: 'bytes', + jitter: 'ms', + packetsReceived: 'packets', + packetsLost: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = 'frames'; + units['nackCount'] = 'packets'; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.nackCount; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ((stat.type === 'outbound-rtp') && + (stat.isRemote === false && + stat.id.toLowerCase().includes('outbound'))) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + bytesSent: 'bytes', + packetsSent: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = 'frames'; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + }); + } + else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { + var key = _a[_i]; + var stat = stats[key]; + if (stat.type === 'ssrc') { + var json = {}; + if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || + (stat.mediaType === 'video' && 'qpSum' in stat))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + jitter: stat.googJitterBufferMs, + packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + bytesReceived: 'bytes', + jitter: 'ms', + packetsReceived: 'packets', + packetsLost: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = 'frames'; + units['nackCount'] = 'packets'; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.googNacksSent; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ('bytesSent' in stat) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + bytesSent: 'bytes', + packetsSent: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = 'frames'; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + } + } + } + }; + this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); }); + }; + WebRtcStats.prototype.standardizeReport = function (response) { + console.log(response); + var standardReport = {}; + if (platform.name.indexOf('Firefox') !== -1) { + Object.keys(response).forEach(function (key) { + console.log(response[key]); + }); + return response; + } + response.result().forEach(function (report) { + var standardStats = { + id: report.id, + timestamp: report.timestamp, + type: report.type + }; + report.names().forEach(function (name) { + standardStats[name] = report.stat(name); + }); + standardReport[standardStats.id] = standardStats; + }); + return standardReport; + }; + WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) { + var _this = this; + if (platform.name.indexOf('Firefox') !== -1) { + return pc.getStats(null).then(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }).catch(failureCb); + } + else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + return pc.getStats(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }, null, failureCb); + } + }; + return WebRtcStats; +}()); +exports.WebRtcStats = WebRtcStats; + +},{"platform":8}]},{},[16]) +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9NYXBwZXIuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvSnNvblJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL1htbFJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmctQXV0by5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNQZWVyL1dlYlJ0Y1BlZXIudHMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1N0YXRzL1dlYlJ0Y1N0YXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzZ0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3RlQSxnREFBK0M7QUFFL0MsSUFBSSxNQUFNLEVBQUU7SUFFUixNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsbUJBQVEsQ0FBQztDQUNqQzs7Ozs7QUNhRCxtQ0FBa0M7QUFV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LEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztTQUN2QjtJQUNMLENBQUM7SUFFTCxrQkFBQztBQUFELENBcllBLEFBcVlDLElBQUE7QUFyWVksa0NBQVciLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLyohXG4gKiBQbGF0Zm9ybS5qcyA8aHR0cHM6Ly9tdGhzLmJlL3BsYXRmb3JtPlxuICogQ29weXJpZ2h0IDIwMTQtMjAxOCBCZW5qYW1pbiBUYW4gPGh0dHBzOi8vYm5qbW50NG4ubm93LnNoLz5cbiAqIENvcHlyaWdodCAyMDExLTIwMTMgSm9obi1EYXZpZCBEYWx0b24gPGh0dHA6Ly9hbGx5b3VjYW5sZWV0LmNvbS8+XG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbXRocy5iZS9taXQ+XG4gKi9cbjsoZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBCYWNrdXAgcG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIG9sZFJvb3QgPSByb290O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcyBvciBCcm93c2VyaWZpZWQgY29kZSBhbmQgdXNlIGl0IGFzIGByb290YC4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSBmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlICYmIHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSkge1xuICAgIHJvb3QgPSBmcmVlR2xvYmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgdGhlIG1heGltdW0gbGVuZ3RoIG9mIGFuIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgKiBTZWUgdGhlIFtFUzYgc3BlY10oaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGgpXG4gICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAqL1xuICB2YXIgbWF4U2FmZUludGVnZXIgPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuXG4gIC8qKiBSZWd1bGFyIGV4cHJlc3Npb24gdG8gZGV0ZWN0IE9wZXJhLiAqL1xuICB2YXIgcmVPcGVyYSA9IC9cXGJPcGVyYS87XG5cbiAgLyoqIFBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciB0aGlzQmluZGluZyA9IHRoaXM7XG5cbiAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAvKiogVXNlZCB0byBjaGVjayBmb3Igb3duIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LiAqL1xuICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiB2YWx1ZXMuICovXG4gIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDYXBpdGFsaXplcyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgIHN0cmluZyA9IFN0cmluZyhzdHJpbmcpO1xuICAgIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG4gIH1cblxuICAvKipcbiAgICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGNsZWFuIHVwIHRoZSBPUyBuYW1lLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3MgVGhlIE9TIG5hbWUgdG8gY2xlYW4gdXAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVybl0gQSBgUmVnRXhwYCBwYXR0ZXJuIG1hdGNoaW5nIHRoZSBPUyBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhYmVsXSBBIGxhYmVsIGZvciB0aGUgT1MuXG4gICAqL1xuICBmdW5jdGlvbiBjbGVhbnVwT1Mob3MsIHBhdHRlcm4sIGxhYmVsKSB7XG4gICAgLy8gUGxhdGZvcm0gdG9rZW5zIGFyZSBkZWZpbmVkIGF0OlxuICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIC8vIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDgxMTIyMDUzOTUwL2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIHZhciBkYXRhID0ge1xuICAgICAgJzEwLjAnOiAnMTAnLFxuICAgICAgJzYuNCc6ICAnMTAgVGVjaG5pY2FsIFByZXZpZXcnLFxuICAgICAgJzYuMyc6ICAnOC4xJyxcbiAgICAgICc2LjInOiAgJzgnLFxuICAgICAgJzYuMSc6ICAnU2VydmVyIDIwMDggUjIgLyA3JyxcbiAgICAgICc2LjAnOiAgJ1NlcnZlciAyMDA4IC8gVmlzdGEnLFxuICAgICAgJzUuMic6ICAnU2VydmVyIDIwMDMgLyBYUCA2NC1iaXQnLFxuICAgICAgJzUuMSc6ICAnWFAnLFxuICAgICAgJzUuMDEnOiAnMjAwMCBTUDEnLFxuICAgICAgJzUuMCc6ICAnMjAwMCcsXG4gICAgICAnNC4wJzogICdOVCcsXG4gICAgICAnNC45MCc6ICdNRSdcbiAgICB9O1xuICAgIC8vIERldGVjdCBXaW5kb3dzIHZlcnNpb24gZnJvbSBwbGF0Zm9ybSB0b2tlbnMuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwgJiYgL15XaW4vaS50ZXN0KG9zKSAmJiAhL15XaW5kb3dzIFBob25lIC9pLnRlc3Qob3MpICYmXG4gICAgICAgIChkYXRhID0gZGF0YVsvW1xcZC5dKyQvLmV4ZWMob3MpXSkpIHtcbiAgICAgIG9zID0gJ1dpbmRvd3MgJyArIGRhdGE7XG4gICAgfVxuICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgIG9zID0gU3RyaW5nKG9zKTtcblxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGxhYmVsKTtcbiAgICB9XG5cbiAgICBvcyA9IGZvcm1hdChcbiAgICAgIG9zLnJlcGxhY2UoLyBjZSQvaSwgJyBDRScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJocHcvaSwgJ3dlYicpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWNpbnRvc2hcXGIvLCAnTWFjIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL19Qb3dlclBDXFxiL2ksICcgT1MnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKE9TIFgpIFteIFxcZF0rL2ksICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWMgKE9TIFgpXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyhcXGQpLywgJyAkMScpXG4gICAgICAgIC5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgLnJlcGxhY2UoLyg/OiBCZVBDfFsgLl0qZmNbIFxcZC5dKykkL2ksICcnKVxuICAgICAgICAucmVwbGFjZSgvXFxieDg2XFwuNjRcXGIvZ2ksICd4ODZfNjQnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKFdpbmRvd3MgUGhvbmUpIE9TXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihDaHJvbWUgT1MgXFx3KykgW1xcZC5dK1xcYi8sICckMScpXG4gICAgICAgIC5zcGxpdCgnIG9uICcpWzBdXG4gICAgKTtcblxuICAgIHJldHVybiBvcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpdGVyYXRpb24gdXRpbGl0eSBmb3IgYXJyYXlzIGFuZCBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBlYWNoKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gb2JqZWN0ID8gb2JqZWN0Lmxlbmd0aCA6IDA7XG5cbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPiAtMSAmJiBsZW5ndGggPD0gbWF4U2FmZUludGVnZXIpIHtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtpbmRleF0sIGluZGV4LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3JPd24ob2JqZWN0LCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaW0gYW5kIGNvbmRpdGlvbmFsbHkgY2FwaXRhbGl6ZSBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGZvcm1hdChzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSB0cmltKHN0cmluZyk7XG4gICAgcmV0dXJuIC9eKD86d2ViT1N8aSg/Ok9TfFApKS8udGVzdChzdHJpbmcpXG4gICAgICA/IHN0cmluZ1xuICAgICAgOiBjYXBpdGFsaXplKHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZXMgb3ZlciBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgZXhlY3V0aW5nIHRoZSBgY2FsbGJhY2tgIGZvciBlYWNoLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gZXhlY3V0ZWQgcGVyIG93biBwcm9wZXJ0eS5cbiAgICovXG4gIGZ1bmN0aW9uIGZvck93bihvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtrZXldLCBrZXksIG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIGEgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYFtbQ2xhc3NdXWAuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRDbGFzc09mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGxcbiAgICAgID8gY2FwaXRhbGl6ZSh2YWx1ZSlcbiAgICAgIDogdG9TdHJpbmcuY2FsbCh2YWx1ZSkuc2xpY2UoOCwgLTEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvc3Qgb2JqZWN0cyBjYW4gcmV0dXJuIHR5cGUgdmFsdWVzIHRoYXQgYXJlIGRpZmZlcmVudCBmcm9tIHRoZWlyIGFjdHVhbFxuICAgKiBkYXRhIHR5cGUuIFRoZSBvYmplY3RzIHdlIGFyZSBjb25jZXJuZWQgd2l0aCB1c3VhbGx5IHJldHVybiBub24tcHJpbWl0aXZlXG4gICAqIHR5cGVzIG9mIFwib2JqZWN0XCIsIFwiZnVuY3Rpb25cIiwgb3IgXCJ1bmtub3duXCIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBvd25lciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgYSBub24tcHJpbWl0aXZlLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RUeXBlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICB2YXIgdHlwZSA9IG9iamVjdCAhPSBudWxsID8gdHlwZW9mIG9iamVjdFtwcm9wZXJ0eV0gOiAnbnVtYmVyJztcbiAgICByZXR1cm4gIS9eKD86Ym9vbGVhbnxudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZCkkLy50ZXN0KHR5cGUpICYmXG4gICAgICAodHlwZSA9PSAnb2JqZWN0JyA/ICEhb2JqZWN0W3Byb3BlcnR5XSA6IHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmVzIGEgc3RyaW5nIGZvciB1c2UgaW4gYSBgUmVnRXhwYCBieSBtYWtpbmcgaHlwaGVucyBhbmQgc3BhY2VzIG9wdGlvbmFsLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcXVhbGlmeS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBxdWFsaWZ5KHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC8oWyAtXSkoPyEkKS9nLCAnJDE/Jyk7XG4gIH1cblxuICAvKipcbiAgICogQSBiYXJlLWJvbmVzIGBBcnJheSNyZWR1Y2VgIGxpa2UgdXRpbGl0eSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Kn0gVGhlIGFjY3VtdWxhdGVkIHJlc3VsdC5cbiAgICovXG4gIGZ1bmN0aW9uIHJlZHVjZShhcnJheSwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWNjdW11bGF0b3IgPSBudWxsO1xuICAgIGVhY2goYXJyYXksIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBhcnJheSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvXiArfCArJC9nLCAnJyk7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbGF0Zm9ybSBvYmplY3QuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgKiBAcGFyYW0ge09iamVjdHxzdHJpbmd9IFt1YT1uYXZpZ2F0b3IudXNlckFnZW50XSBUaGUgdXNlciBhZ2VudCBzdHJpbmcgb3JcbiAgICogIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBIHBsYXRmb3JtIG9iamVjdC5cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlKHVhKSB7XG5cbiAgICAvKiogVGhlIGVudmlyb25tZW50IGNvbnRleHQgb2JqZWN0LiAqL1xuICAgIHZhciBjb250ZXh0ID0gcm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBhIGN1c3RvbSBjb250ZXh0IGlzIHByb3ZpZGVkLiAqL1xuICAgIHZhciBpc0N1c3RvbUNvbnRleHQgPSB1YSAmJiB0eXBlb2YgdWEgPT0gJ29iamVjdCcgJiYgZ2V0Q2xhc3NPZih1YSkgIT0gJ1N0cmluZyc7XG5cbiAgICAvLyBKdWdnbGUgYXJndW1lbnRzLlxuICAgIGlmIChpc0N1c3RvbUNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB1YTtcbiAgICAgIHVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKiogQnJvd3NlciBuYXZpZ2F0b3Igb2JqZWN0LiAqL1xuICAgIHZhciBuYXYgPSBjb250ZXh0Lm5hdmlnYXRvciB8fCB7fTtcblxuICAgIC8qKiBCcm93c2VyIHVzZXIgYWdlbnQgc3RyaW5nLiAqL1xuICAgIHZhciB1c2VyQWdlbnQgPSBuYXYudXNlckFnZW50IHx8ICcnO1xuXG4gICAgdWEgfHwgKHVhID0gdXNlckFnZW50KTtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBgdGhpc0JpbmRpbmdgIGlzIHRoZSBbTW9kdWxlU2NvcGVdLiAqL1xuICAgIHZhciBpc01vZHVsZVNjb3BlID0gaXNDdXN0b21Db250ZXh0IHx8IHRoaXNCaW5kaW5nID09IG9sZFJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYnJvd3NlciBpcyBsaWtlIENocm9tZS4gKi9cbiAgICB2YXIgbGlrZUNocm9tZSA9IGlzQ3VzdG9tQ29udGV4dFxuICAgICAgPyAhIW5hdi5saWtlQ2hyb21lXG4gICAgICA6IC9cXGJDaHJvbWVcXGIvLnRlc3QodWEpICYmICEvaW50ZXJuYWx8XFxuL2kudGVzdCh0b1N0cmluZy50b1N0cmluZygpKTtcblxuICAgIC8qKiBJbnRlcm5hbCBgW1tDbGFzc11dYCB2YWx1ZSBzaG9ydGN1dHMuICovXG4gICAgdmFyIG9iamVjdENsYXNzID0gJ09iamVjdCcsXG4gICAgICAgIGFpclJ1bnRpbWVDbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1NjcmlwdEJyaWRnaW5nUHJveHlPYmplY3QnLFxuICAgICAgICBlbnZpcm9DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ0Vudmlyb25tZW50JyxcbiAgICAgICAgamF2YUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBjb250ZXh0LmphdmEpID8gJ0phdmFQYWNrYWdlJyA6IGdldENsYXNzT2YoY29udGV4dC5qYXZhKSxcbiAgICAgICAgcGhhbnRvbUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnUnVudGltZU9iamVjdCc7XG5cbiAgICAvKiogRGV0ZWN0IEphdmEgZW52aXJvbm1lbnRzLiAqL1xuICAgIHZhciBqYXZhID0gL1xcYkphdmEvLnRlc3QoamF2YUNsYXNzKSAmJiBjb250ZXh0LmphdmE7XG5cbiAgICAvKiogRGV0ZWN0IFJoaW5vLiAqL1xuICAgIHZhciByaGlubyA9IGphdmEgJiYgZ2V0Q2xhc3NPZihjb250ZXh0LmVudmlyb25tZW50KSA9PSBlbnZpcm9DbGFzcztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYWxwaGEuICovXG4gICAgdmFyIGFscGhhID0gamF2YSA/ICdhJyA6ICdcXHUwM2IxJztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYmV0YS4gKi9cbiAgICB2YXIgYmV0YSA9IGphdmEgPyAnYicgOiAnXFx1MDNiMic7XG5cbiAgICAvKiogQnJvd3NlciBkb2N1bWVudCBvYmplY3QuICovXG4gICAgdmFyIGRvYyA9IGNvbnRleHQuZG9jdW1lbnQgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgT3BlcmEgYnJvd3NlciAoUHJlc3RvLWJhc2VkKS5cbiAgICAgKiBodHRwOi8vd3d3Lmhvd3RvY3JlYXRlLmNvLnVrL29wZXJhU3R1ZmYvb3BlcmFPYmplY3QuaHRtbFxuICAgICAqIGh0dHA6Ly9kZXYub3BlcmEuY29tL2FydGljbGVzL3ZpZXcvb3BlcmEtbWluaS13ZWItY29udGVudC1hdXRob3JpbmctZ3VpZGVsaW5lcy8jb3BlcmFtaW5pXG4gICAgICovXG4gICAgdmFyIG9wZXJhID0gY29udGV4dC5vcGVyYW1pbmkgfHwgY29udGV4dC5vcGVyYTtcblxuICAgIC8qKiBPcGVyYSBgW1tDbGFzc11dYC4gKi9cbiAgICB2YXIgb3BlcmFDbGFzcyA9IHJlT3BlcmEudGVzdChvcGVyYUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBvcGVyYSkgPyBvcGVyYVsnW1tDbGFzc11dJ10gOiBnZXRDbGFzc09mKG9wZXJhKSlcbiAgICAgID8gb3BlcmFDbGFzc1xuICAgICAgOiAob3BlcmEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKiBUZW1wb3JhcnkgdmFyaWFibGUgdXNlZCBvdmVyIHRoZSBzY3JpcHQncyBsaWZldGltZS4gKi9cbiAgICB2YXIgZGF0YTtcblxuICAgIC8qKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZS4gKi9cbiAgICB2YXIgYXJjaCA9IHVhO1xuXG4gICAgLyoqIFBsYXRmb3JtIGRlc2NyaXB0aW9uIGFycmF5LiAqL1xuICAgIHZhciBkZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgLyoqIFBsYXRmb3JtIGFscGhhL2JldGEgaW5kaWNhdG9yLiAqL1xuICAgIHZhciBwcmVyZWxlYXNlID0gbnVsbDtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgdGhhdCBlbnZpcm9ubWVudCBmZWF0dXJlcyBzaG91bGQgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwbGF0Zm9ybS4gKi9cbiAgICB2YXIgdXNlRmVhdHVyZXMgPSB1YSA9PSB1c2VyQWdlbnQ7XG5cbiAgICAvKiogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi4gKi9cbiAgICB2YXIgdmVyc2lvbiA9IHVzZUZlYXR1cmVzICYmIG9wZXJhICYmIHR5cGVvZiBvcGVyYS52ZXJzaW9uID09ICdmdW5jdGlvbicgJiYgb3BlcmEudmVyc2lvbigpO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgT1MgZW5kcyB3aXRoIFwiLyBWZXJzaW9uXCIgKi9cbiAgICB2YXIgaXNTcGVjaWFsQ2FzZWRPUztcblxuICAgIC8qIERldGVjdGFibGUgbGF5b3V0IGVuZ2luZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIGxheW91dCA9IGdldExheW91dChbXG4gICAgICB7ICdsYWJlbCc6ICdFZGdlSFRNTCcsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnVHJpZGVudCcsXG4gICAgICB7ICdsYWJlbCc6ICdXZWJLaXQnLCAncGF0dGVybic6ICdBcHBsZVdlYktpdCcgfSxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdQcmVzdG8nLFxuICAgICAgJ05ldEZyb250JyxcbiAgICAgICdUYXNtYW4nLFxuICAgICAgJ0tIVE1MJyxcbiAgICAgICdHZWNrbydcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgYnJvd3NlciBuYW1lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbmFtZSA9IGdldE5hbWUoW1xuICAgICAgJ0Fkb2JlIEFJUicsXG4gICAgICAnQXJvcmEnLFxuICAgICAgJ0F2YW50IEJyb3dzZXInLFxuICAgICAgJ0JyZWFjaCcsXG4gICAgICAnQ2FtaW5vJyxcbiAgICAgICdFbGVjdHJvbicsXG4gICAgICAnRXBpcGhhbnknLFxuICAgICAgJ0Zlbm5lYycsXG4gICAgICAnRmxvY2snLFxuICAgICAgJ0dhbGVvbicsXG4gICAgICAnR3JlZW5Ccm93c2VyJyxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdJY2V3ZWFzZWwnLFxuICAgICAgJ0stTWVsZW9uJyxcbiAgICAgICdLb25xdWVyb3InLFxuICAgICAgJ0x1bmFzY2FwZScsXG4gICAgICAnTWF4dGhvbicsXG4gICAgICB7ICdsYWJlbCc6ICdNaWNyb3NvZnQgRWRnZScsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnTWlkb3JpJyxcbiAgICAgICdOb29rIEJyb3dzZXInLFxuICAgICAgJ1BhbGVNb29uJyxcbiAgICAgICdQaGFudG9tSlMnLFxuICAgICAgJ1JhdmVuJyxcbiAgICAgICdSZWtvbnEnLFxuICAgICAgJ1JvY2tNZWx0JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NhbXN1bmcgSW50ZXJuZXQnLCAncGF0dGVybic6ICdTYW1zdW5nQnJvd3NlcicgfSxcbiAgICAgICdTZWFNb25rZXknLFxuICAgICAgeyAnbGFiZWwnOiAnU2lsaycsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdTbGVpcG5pcicsXG4gICAgICAnU2xpbUJyb3dzZXInLFxuICAgICAgeyAnbGFiZWwnOiAnU1JXYXJlIElyb24nLCAncGF0dGVybic6ICdJcm9uJyB9LFxuICAgICAgJ1N1bnJpc2UnLFxuICAgICAgJ1N3aWZ0Zm94JyxcbiAgICAgICdXYXRlcmZveCcsXG4gICAgICAnV2ViUG9zaXRpdmUnLFxuICAgICAgJ09wZXJhIE1pbmknLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEgTWluaScsICdwYXR0ZXJuJzogJ09QaU9TJyB9LFxuICAgICAgJ09wZXJhJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhJywgJ3BhdHRlcm4nOiAnT1BSJyB9LFxuICAgICAgJ0Nocm9tZScsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgTW9iaWxlJywgJ3BhdHRlcm4nOiAnKD86Q3JpT1N8Q3JNbyknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94JywgJ3BhdHRlcm4nOiAnKD86RmlyZWZveHxNaW5lZmllbGQpJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCBmb3IgaU9TJywgJ3BhdHRlcm4nOiAnRnhpT1MnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ0lFTW9iaWxlJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdNU0lFJyB9LFxuICAgICAgJ1NhZmFyaSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgcHJvZHVjdHMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0JsYWNrQmVycnknLCAncGF0dGVybic6ICdCQjEwJyB9LFxuICAgICAgJ0JsYWNrQmVycnknLFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMnLCAncGF0dGVybic6ICdHVC1JOTAwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMicsICdwYXR0ZXJuJzogJ0dULUk5MTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMzJywgJ3BhdHRlcm4nOiAnR1QtSTkzMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzQnLCAncGF0dGVybic6ICdHVC1JOTUwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNScsICdwYXR0ZXJuJzogJ1NNLUc5MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYnLCAncGF0dGVybic6ICdTTS1HOTIwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTI1JyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3JywgJ3BhdHRlcm4nOiAnU00tRzkzMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNyBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkzNScgfSxcbiAgICAgICdHb29nbGUgVFYnLFxuICAgICAgJ0x1bWlhJyxcbiAgICAgICdpUGFkJyxcbiAgICAgICdpUG9kJyxcbiAgICAgICdpUGhvbmUnLFxuICAgICAgJ0tpbmRsZScsXG4gICAgICB7ICdsYWJlbCc6ICdLaW5kbGUgRmlyZScsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdOZXh1cycsXG4gICAgICAnTm9vaycsXG4gICAgICAnUGxheUJvb2snLFxuICAgICAgJ1BsYXlTdGF0aW9uIFZpdGEnLFxuICAgICAgJ1BsYXlTdGF0aW9uJyxcbiAgICAgICdUb3VjaFBhZCcsXG4gICAgICAnVHJhbnNmb3JtZXInLFxuICAgICAgeyAnbGFiZWwnOiAnV2lpIFUnLCAncGF0dGVybic6ICdXaWlVJyB9LFxuICAgICAgJ1dpaScsXG4gICAgICAnWGJveCBPbmUnLFxuICAgICAgeyAnbGFiZWwnOiAnWGJveCAzNjAnLCAncGF0dGVybic6ICdYYm94JyB9LFxuICAgICAgJ1hvb20nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG1hbnVmYWN0dXJlcnMuICovXG4gICAgdmFyIG1hbnVmYWN0dXJlciA9IGdldE1hbnVmYWN0dXJlcih7XG4gICAgICAnQXBwbGUnOiB7ICdpUGFkJzogMSwgJ2lQaG9uZSc6IDEsICdpUG9kJzogMSB9LFxuICAgICAgJ0FyY2hvcyc6IHt9LFxuICAgICAgJ0FtYXpvbic6IHsgJ0tpbmRsZSc6IDEsICdLaW5kbGUgRmlyZSc6IDEgfSxcbiAgICAgICdBc3VzJzogeyAnVHJhbnNmb3JtZXInOiAxIH0sXG4gICAgICAnQmFybmVzICYgTm9ibGUnOiB7ICdOb29rJzogMSB9LFxuICAgICAgJ0JsYWNrQmVycnknOiB7ICdQbGF5Qm9vayc6IDEgfSxcbiAgICAgICdHb29nbGUnOiB7ICdHb29nbGUgVFYnOiAxLCAnTmV4dXMnOiAxIH0sXG4gICAgICAnSFAnOiB7ICdUb3VjaFBhZCc6IDEgfSxcbiAgICAgICdIVEMnOiB7fSxcbiAgICAgICdMRyc6IHt9LFxuICAgICAgJ01pY3Jvc29mdCc6IHsgJ1hib3gnOiAxLCAnWGJveCBPbmUnOiAxIH0sXG4gICAgICAnTW90b3JvbGEnOiB7ICdYb29tJzogMSB9LFxuICAgICAgJ05pbnRlbmRvJzogeyAnV2lpIFUnOiAxLCAgJ1dpaSc6IDEgfSxcbiAgICAgICdOb2tpYSc6IHsgJ0x1bWlhJzogMSB9LFxuICAgICAgJ1NhbXN1bmcnOiB7ICdHYWxheHkgUyc6IDEsICdHYWxheHkgUzInOiAxLCAnR2FsYXh5IFMzJzogMSwgJ0dhbGF4eSBTNCc6IDEgfSxcbiAgICAgICdTb255JzogeyAnUGxheVN0YXRpb24nOiAxLCAnUGxheVN0YXRpb24gVml0YSc6IDEgfVxuICAgIH0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBvcGVyYXRpbmcgc3lzdGVtcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgb3MgPSBnZXRPUyhbXG4gICAgICAnV2luZG93cyBQaG9uZScsXG4gICAgICAnQW5kcm9pZCcsXG4gICAgICAnQ2VudE9TJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBPUycsICdwYXR0ZXJuJzogJ0NyT1MnIH0sXG4gICAgICAnRGViaWFuJyxcbiAgICAgICdGZWRvcmEnLFxuICAgICAgJ0ZyZWVCU0QnLFxuICAgICAgJ0dlbnRvbycsXG4gICAgICAnSGFpa3UnLFxuICAgICAgJ0t1YnVudHUnLFxuICAgICAgJ0xpbnV4IE1pbnQnLFxuICAgICAgJ09wZW5CU0QnLFxuICAgICAgJ1JlZCBIYXQnLFxuICAgICAgJ1N1U0UnLFxuICAgICAgJ1VidW50dScsXG4gICAgICAnWHVidW50dScsXG4gICAgICAnQ3lnd2luJyxcbiAgICAgICdTeW1iaWFuIE9TJyxcbiAgICAgICdocHdPUycsXG4gICAgICAnd2ViT1MgJyxcbiAgICAgICd3ZWJPUycsXG4gICAgICAnVGFibGV0IE9TJyxcbiAgICAgICdUaXplbicsXG4gICAgICAnTGludXgnLFxuICAgICAgJ01hYyBPUyBYJyxcbiAgICAgICdNYWNpbnRvc2gnLFxuICAgICAgJ01hYycsXG4gICAgICAnV2luZG93cyA5ODsnLFxuICAgICAgJ1dpbmRvd3MgJ1xuICAgIF0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGxheW91dCBlbmdpbmUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbGF5b3V0IGVuZ2luZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMYXlvdXQoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIG1hbnVmYWN0dXJlciBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gb2JqZWN0IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbWFudWZhY3R1cmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlcihndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgICAvLyBMb29rdXAgdGhlIG1hbnVmYWN0dXJlciBieSBwcm9kdWN0IG9yIHNjYW4gdGhlIFVBIGZvciB0aGUgbWFudWZhY3R1cmVyLlxuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChcbiAgICAgICAgICB2YWx1ZVtwcm9kdWN0XSB8fFxuICAgICAgICAgIHZhbHVlWy9eW2Etel0rKD86ICtbYS16XStcXGIpKi9pLmV4ZWMocHJvZHVjdCldIHx8XG4gICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBxdWFsaWZ5KGtleSkgKyAnKD86XFxcXGJ8XFxcXHcqXFxcXGQpJywgJ2knKS5leGVjKHVhKVxuICAgICAgICApICYmIGtleTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBicm93c2VyIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgYnJvd3NlciBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hbWUoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIE9TIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgT1MgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRPUyhndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/Oi9bXFxcXGQuXSt8WyBcXFxcdy5dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xlYW51cE9TKHJlc3VsdCwgcGF0dGVybiwgZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgcHJvZHVjdCBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHByb2R1Y3QgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRQcm9kdWN0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcZCtbLlxcXFx3X10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcdystW1xcXFx3XSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzo7ICooPzpbYS16XStbXy1dKT9bYS16XStcXFxcZCt8W14gKCk7LV0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAvLyBTcGxpdCBieSBmb3J3YXJkIHNsYXNoIGFuZCBhcHBlbmQgcHJvZHVjdCB2ZXJzaW9uIGlmIG5lZWRlZC5cbiAgICAgICAgICBpZiAoKHJlc3VsdCA9IFN0cmluZygoZ3Vlc3MubGFiZWwgJiYgIVJlZ0V4cChwYXR0ZXJuLCAnaScpLnRlc3QoZ3Vlc3MubGFiZWwpKSA/IGd1ZXNzLmxhYmVsIDogcmVzdWx0KS5zcGxpdCgnLycpKVsxXSAmJiAhL1tcXGQuXSsvLnRlc3QocmVzdWx0WzBdKSkge1xuICAgICAgICAgICAgcmVzdWx0WzBdICs9ICcgJyArIHJlc3VsdFsxXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgICAgICAgZ3Vlc3MgPSBndWVzcy5sYWJlbCB8fCBndWVzcztcbiAgICAgICAgICByZXN1bHQgPSBmb3JtYXQocmVzdWx0WzBdXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgZ3Vlc3MpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJzsgKig/OicgKyBndWVzcyArICdbXy1dKT8nLCAnaScpLCAnICcpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJygnICsgZ3Vlc3MgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCAnJDEgJDInKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2ZXJzaW9uIHVzaW5nIGFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXR0ZXJucyBBbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCB2ZXJzaW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZlcnNpb24ocGF0dGVybnMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UocGF0dGVybnMsIGZ1bmN0aW9uKHJlc3VsdCwgcGF0dGVybikge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChSZWdFeHAocGF0dGVybiArXG4gICAgICAgICAgJyg/Oi1bXFxcXGQuXSsvfCg/OiBmb3IgW1xcXFx3LV0rKT9bIC8tXSkoW1xcXFxkLl0rW14gKCk7L18tXSopJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fCBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIHdoZW4gdGhlIHBsYXRmb3JtIG9iamVjdCBpcyBjb2VyY2VkIHRvIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG5hbWUgdG9TdHJpbmdcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgaWYgYXZhaWxhYmxlLCBlbHNlIGFuIGVtcHR5IHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZ1BsYXRmb3JtKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRpb24gfHwgJyc7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQ29udmVydCBsYXlvdXQgdG8gYW4gYXJyYXkgc28gd2UgY2FuIGFkZCBleHRyYSBkZXRhaWxzLlxuICAgIGxheW91dCAmJiAobGF5b3V0ID0gW2xheW91dF0pO1xuXG4gICAgLy8gRGV0ZWN0IHByb2R1Y3QgbmFtZXMgdGhhdCBjb250YWluIHRoZWlyIG1hbnVmYWN0dXJlcidzIG5hbWUuXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiAhcHJvZHVjdCkge1xuICAgICAgcHJvZHVjdCA9IGdldFByb2R1Y3QoW21hbnVmYWN0dXJlcl0pO1xuICAgIH1cbiAgICAvLyBDbGVhbiB1cCBHb29nbGUgVFYuXG4gICAgaWYgKChkYXRhID0gL1xcYkdvb2dsZSBUVlxcYi8uZXhlYyhwcm9kdWN0KSkpIHtcbiAgICAgIHByb2R1Y3QgPSBkYXRhWzBdO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc2ltdWxhdG9ycy5cbiAgICBpZiAoL1xcYlNpbXVsYXRvclxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBwcm9kdWN0ID0gKHByb2R1Y3QgPyBwcm9kdWN0ICsgJyAnIDogJycpICsgJ1NpbXVsYXRvcic7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBNaW5pIDgrIHJ1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUgb24gaU9TLlxuICAgIGlmIChuYW1lID09ICdPcGVyYSBNaW5pJyAmJiAvXFxiT1BpT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBNb2JpbGUgMTEuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAvXFxibGlrZSBpUGhvbmUgT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkYXRhID0gcGFyc2UodWEucmVwbGFjZSgvbGlrZSBpUGhvbmUgT1MvLCAnJykpO1xuICAgICAgbWFudWZhY3R1cmVyID0gZGF0YS5tYW51ZmFjdHVyZXI7XG4gICAgICBwcm9kdWN0ID0gZGF0YS5wcm9kdWN0O1xuICAgIH1cbiAgICAvLyBEZXRlY3QgaU9TLlxuICAgIGVsc2UgaWYgKC9eaVAvLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIG5hbWUgfHwgKG5hbWUgPSAnU2FmYXJpJyk7XG4gICAgICBvcyA9ICdpT1MnICsgKChkYXRhID0gLyBPUyAoW1xcZF9dKykvaS5leGVjKHVhKSlcbiAgICAgICAgPyAnICcgKyBkYXRhWzFdLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICA6ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEt1YnVudHUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnS29ucXVlcm9yJyAmJiAhL2J1bnR1L2kudGVzdChvcykpIHtcbiAgICAgIG9zID0gJ0t1YnVudHUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQW5kcm9pZCBicm93c2Vycy5cbiAgICBlbHNlIGlmICgobWFudWZhY3R1cmVyICYmIG1hbnVmYWN0dXJlciAhPSAnR29vZ2xlJyAmJlxuICAgICAgICAoKC9DaHJvbWUvLnRlc3QobmFtZSkgJiYgIS9cXGJNb2JpbGUgU2FmYXJpXFxiL2kudGVzdCh1YSkpIHx8IC9cXGJWaXRhXFxiLy50ZXN0KHByb2R1Y3QpKSkgfHxcbiAgICAgICAgKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSAmJiAvXkNocm9tZS8udGVzdChuYW1lKSAmJiAvXFxiVmVyc2lvblxcLy9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSA9ICdBbmRyb2lkIEJyb3dzZXInO1xuICAgICAgb3MgPSAvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6ICdBbmRyb2lkJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFNpbGsgZGVza3RvcC9hY2NlbGVyYXRlZCBtb2Rlcy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTaWxrJykge1xuICAgICAgaWYgKCEvXFxiTW9iaS9pLnRlc3QodWEpKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQnO1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIH1cbiAgICAgIGlmICgvQWNjZWxlcmF0ZWQgKj0gKnRydWUvaS50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdhY2NlbGVyYXRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgUGFsZU1vb24gaWRlbnRpZnlpbmcgYXMgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdQYWxlTW9vbicgJiYgKGRhdGEgPSAvXFxiRmlyZWZveFxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyBGaXJlZm94ICcgKyBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggT1MgYW5kIHByb2R1Y3RzIHJ1bm5pbmcgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdGaXJlZm94JyAmJiAoZGF0YSA9IC9cXGIoTW9iaWxlfFRhYmxldHxUVilcXGIvaS5leGVjKHVhKSkpIHtcbiAgICAgIG9zIHx8IChvcyA9ICdGaXJlZm94IE9TJyk7XG4gICAgICBwcm9kdWN0IHx8IChwcm9kdWN0ID0gZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBmYWxzZSBwb3NpdGl2ZXMgZm9yIEZpcmVmb3gvU2FmYXJpLlxuICAgIGVsc2UgaWYgKCFuYW1lIHx8IChkYXRhID0gIS9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAvXFxiKD86RmlyZWZveHxTYWZhcmkpXFxiLy5leGVjKG5hbWUpKSkge1xuICAgICAgLy8gRXNjYXBlIHRoZSBgL2AgZm9yIEZpcmVmb3ggMS5cbiAgICAgIGlmIChuYW1lICYmICFwcm9kdWN0ICYmIC9bXFwvLF18XlteKF0rP1xcKS8udGVzdCh1YS5zbGljZSh1YS5pbmRleE9mKGRhdGEgKyAnLycpICsgOCkpKSB7XG4gICAgICAgIC8vIENsZWFyIG5hbWUgb2YgZmFsc2UgcG9zaXRpdmVzLlxuICAgICAgICBuYW1lID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFJlYXNzaWduIGEgZ2VuZXJpYyBuYW1lLlxuICAgICAgaWYgKChkYXRhID0gcHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgb3MpICYmXG4gICAgICAgICAgKHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IC9cXGIoPzpBbmRyb2lkfFN5bWJpYW4gT1N8VGFibGV0IE9TfHdlYk9TKVxcYi8udGVzdChvcykpKSB7XG4gICAgICAgIG5hbWUgPSAvW2Etel0rKD86IEhhdCk/L2kuZXhlYygvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6IGRhdGEpICsgJyBCcm93c2VyJztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIENocm9tZSB2ZXJzaW9uIHRvIGRlc2NyaXB0aW9uIGZvciBFbGVjdHJvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdFbGVjdHJvbicgJiYgKGRhdGEgPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBub24tT3BlcmEgKFByZXN0by1iYXNlZCkgdmVyc2lvbnMgKG9yZGVyIGlzIGltcG9ydGFudCkuXG4gICAgaWYgKCF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbihbXG4gICAgICAgICcoPzpDbG91ZDl8Q3JpT1N8Q3JNb3xFZGdlfEZ4aU9TfElFTW9iaWxlfElyb258T3BlcmEgP01pbml8T1BpT1N8T1BSfFJhdmVufFNhbXN1bmdCcm93c2VyfFNpbGsoPyEvW1xcXFxkLl0rJCkpJyxcbiAgICAgICAgJ1ZlcnNpb24nLFxuICAgICAgICBxdWFsaWZ5KG5hbWUpLFxuICAgICAgICAnKD86RmlyZWZveHxNaW5lZmllbGR8TmV0RnJvbnQpJ1xuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBzdHViYm9ybiBsYXlvdXQgZW5naW5lcy5cbiAgICBpZiAoKGRhdGEgPVxuICAgICAgICAgIGxheW91dCA9PSAnaUNhYicgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+IDMgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAvXFxiT3BlcmFcXGIvLnRlc3QobmFtZSkgJiYgKC9cXGJPUFJcXGIvLnRlc3QodWEpID8gJ0JsaW5rJyA6ICdQcmVzdG8nKSB8fFxuICAgICAgICAgIC9cXGIoPzpNaWRvcml8Tm9va3xTYWZhcmkpXFxiL2kudGVzdCh1YSkgJiYgIS9eKD86VHJpZGVudHxFZGdlSFRNTCkkLy50ZXN0KGxheW91dCkgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAhbGF5b3V0ICYmIC9cXGJNU0lFXFxiL2kudGVzdCh1YSkgJiYgKG9zID09ICdNYWMgT1MnID8gJ1Rhc21hbicgOiAnVHJpZGVudCcpIHx8XG4gICAgICAgICAgbGF5b3V0ID09ICdXZWJLaXQnICYmIC9cXGJQbGF5U3RhdGlvblxcYig/ISBWaXRhXFxiKS9pLnRlc3QobmFtZSkgJiYgJ05ldEZyb250J1xuICAgICAgICApKSB7XG4gICAgICBsYXlvdXQgPSBbZGF0YV07XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDcgZGVza3RvcCBtb2RlLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgKGRhdGEgPSAoLzsgKig/OlhCTFdQfFp1bmVXUCkoXFxkKykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSAnICsgKC9cXCskLy50ZXN0KGRhdGEpID8gZGF0YSA6IGRhdGEgKyAnLngnKTtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA4LnggZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKC9cXGJXUERlc2t0b3BcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgbmFtZSA9ICdJRSBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSA4LngnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB2ZXJzaW9uIHx8ICh2ZXJzaW9uID0gKC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpIHx8IDApWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIDExIGlkZW50aWZ5aW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKG5hbWUgIT0gJ0lFJyAmJiBsYXlvdXQgPT0gJ1RyaWRlbnQnICYmIChkYXRhID0gL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkpKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyAnICsgbmFtZSArICh2ZXJzaW9uID8gJyAnICsgdmVyc2lvbiA6ICcnKSk7XG4gICAgICB9XG4gICAgICBuYW1lID0gJ0lFJztcbiAgICAgIHZlcnNpb24gPSBkYXRhWzFdO1xuICAgIH1cbiAgICAvLyBMZXZlcmFnZSBlbnZpcm9ubWVudCBmZWF0dXJlcy5cbiAgICBpZiAodXNlRmVhdHVyZXMpIHtcbiAgICAgIC8vIERldGVjdCBzZXJ2ZXItc2lkZSBlbnZpcm9ubWVudHMuXG4gICAgICAvLyBSaGlubyBoYXMgYSBnbG9iYWwgZnVuY3Rpb24gd2hpbGUgb3RoZXJzIGhhdmUgYSBnbG9iYWwgb2JqZWN0LlxuICAgICAgaWYgKGlzSG9zdFR5cGUoY29udGV4dCwgJ2dsb2JhbCcpKSB7XG4gICAgICAgIGlmIChqYXZhKSB7XG4gICAgICAgICAgZGF0YSA9IGphdmEubGFuZy5TeXN0ZW07XG4gICAgICAgICAgYXJjaCA9IGRhdGEuZ2V0UHJvcGVydHkoJ29zLmFyY2gnKTtcbiAgICAgICAgICBvcyA9IG9zIHx8IGRhdGEuZ2V0UHJvcGVydHkoJ29zLm5hbWUnKSArICcgJyArIGRhdGEuZ2V0UHJvcGVydHkoJ29zLnZlcnNpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmhpbm8pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmVyc2lvbiA9IGNvbnRleHQucmVxdWlyZSgncmluZ28vZW5naW5lJykudmVyc2lvbi5qb2luKCcuJyk7XG4gICAgICAgICAgICBuYW1lID0gJ1JpbmdvSlMnO1xuICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgaWYgKChkYXRhID0gY29udGV4dC5zeXN0ZW0pICYmIGRhdGEuZ2xvYmFsLnN5c3RlbSA9PSBjb250ZXh0LnN5c3RlbSkge1xuICAgICAgICAgICAgICBuYW1lID0gJ05hcndoYWwnO1xuICAgICAgICAgICAgICBvcyB8fCAob3MgPSBkYXRhWzBdLm9zIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnUmhpbm8nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgY29udGV4dC5wcm9jZXNzID09ICdvYmplY3QnICYmICFjb250ZXh0LnByb2Nlc3MuYnJvd3NlciAmJlxuICAgICAgICAgIChkYXRhID0gY29udGV4dC5wcm9jZXNzKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5lbGVjdHJvbiA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ0VsZWN0cm9uJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMuZWxlY3Ryb247XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLm53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyB2ZXJzaW9uLCAnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOVy5qcyc7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLm53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnTm9kZS5qcyc7XG4gICAgICAgICAgICBhcmNoID0gZGF0YS5hcmNoO1xuICAgICAgICAgICAgb3MgPSBkYXRhLnBsYXRmb3JtO1xuICAgICAgICAgICAgdmVyc2lvbiA9IC9bXFxkLl0rLy5leGVjKGRhdGEudmVyc2lvbik7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbiA/IHZlcnNpb25bMF0gOiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEFkb2JlIEFJUi5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnJ1bnRpbWUpKSA9PSBhaXJSdW50aW1lQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdBZG9iZSBBSVInO1xuICAgICAgICBvcyA9IGRhdGEuZmxhc2guc3lzdGVtLkNhcGFiaWxpdGllcy5vcztcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBQaGFudG9tSlMuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5waGFudG9tKSkgPT0gcGhhbnRvbUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnUGhhbnRvbUpTJztcbiAgICAgICAgdmVyc2lvbiA9IChkYXRhID0gZGF0YS52ZXJzaW9uIHx8IG51bGwpICYmIChkYXRhLm1ham9yICsgJy4nICsgZGF0YS5taW5vciArICcuJyArIGRhdGEucGF0Y2gpO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIGNvbXBhdGliaWxpdHkgbW9kZXMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAoZGF0YSA9IC9cXGJUcmlkZW50XFwvKFxcZCspL2kuZXhlYyh1YSkpKSB7XG4gICAgICAgIC8vIFdlJ3JlIGluIGNvbXBhdGliaWxpdHkgbW9kZSB3aGVuIHRoZSBUcmlkZW50IHZlcnNpb24gKyA0IGRvZXNuJ3RcbiAgICAgICAgLy8gZXF1YWwgdGhlIGRvY3VtZW50IG1vZGUuXG4gICAgICAgIHZlcnNpb24gPSBbdmVyc2lvbiwgZG9jLmRvY3VtZW50TW9kZV07XG4gICAgICAgIGlmICgoZGF0YSA9ICtkYXRhWzFdICsgNCkgIT0gdmVyc2lvblsxXSkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0lFICcgKyB2ZXJzaW9uWzFdICsgJyBtb2RlJyk7XG4gICAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnJyk7XG4gICAgICAgICAgdmVyc2lvblsxXSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgdmVyc2lvbiA9IG5hbWUgPT0gJ0lFJyA/IFN0cmluZyh2ZXJzaW9uWzFdLnRvRml4ZWQoMSkpIDogdmVyc2lvblswXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSAxMSBtYXNraW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgL14oPzpDaHJvbWV8RmlyZWZveClcXGIvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnbWFza2luZyBhcyAnICsgbmFtZSArICcgJyArIHZlcnNpb24pO1xuICAgICAgICBuYW1lID0gJ0lFJztcbiAgICAgICAgdmVyc2lvbiA9ICcxMS4wJztcbiAgICAgICAgbGF5b3V0ID0gWydUcmlkZW50J107XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcyAmJiBmb3JtYXQob3MpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgcHJlcmVsZWFzZSBwaGFzZXMuXG4gICAgaWYgKHZlcnNpb24gJiYgKGRhdGEgPVxuICAgICAgICAgIC8oPzpbYWJdfGRwfHByZXxbYWJdXFxkK3ByZSkoPzpcXGQrXFwrPyk/JC9pLmV4ZWModmVyc2lvbikgfHxcbiAgICAgICAgICAvKD86YWxwaGF8YmV0YSkoPzogP1xcZCk/L2kuZXhlYyh1YSArICc7JyArICh1c2VGZWF0dXJlcyAmJiBuYXYuYXBwTWlub3JWZXJzaW9uKSkgfHxcbiAgICAgICAgICAvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgJ2EnXG4gICAgICAgICkpIHtcbiAgICAgIHByZXJlbGVhc2UgPSAvYi9pLnRlc3QoZGF0YSkgPyAnYmV0YScgOiAnYWxwaGEnO1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZShSZWdFeHAoZGF0YSArICdcXFxcKz8kJyksICcnKSArXG4gICAgICAgIChwcmVyZWxlYXNlID09ICdiZXRhJyA/IGJldGEgOiBhbHBoYSkgKyAoL1xcZCtcXCs/Ly5leGVjKGRhdGEpIHx8ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggTW9iaWxlLlxuICAgIGlmIChuYW1lID09ICdGZW5uZWMnIHx8IG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGIoPzpBbmRyb2lkfEZpcmVmb3ggT1MpXFxiLy50ZXN0KG9zKSkge1xuICAgICAgbmFtZSA9ICdGaXJlZm94IE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIE9ic2N1cmUgTWF4dGhvbidzIHVucmVsaWFibGUgdmVyc2lvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdNYXh0aG9uJyAmJiB2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKC9cXC5bXFxkLl0rLywgJy54Jyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBYYm94IDM2MCBhbmQgWGJveCBPbmUuXG4gICAgZWxzZSBpZiAoL1xcYlhib3hcXGIvaS50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnKSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcgJiYgL1xcYklFTW9iaWxlXFxiLy50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdtb2JpbGUgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgbW9iaWxlIHBvc3RmaXguXG4gICAgZWxzZSBpZiAoKC9eKD86Q2hyb21lfElFfE9wZXJhKSQvLnRlc3QobmFtZSkgfHwgbmFtZSAmJiAhcHJvZHVjdCAmJiAhL0Jyb3dzZXJ8TW9iaS8udGVzdChuYW1lKSkgJiZcbiAgICAgICAgKG9zID09ICdXaW5kb3dzIENFJyB8fCAvTW9iaS9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBwbGF0Zm9ybSBwcmV2aWV3LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0lFJyAmJiB1c2VGZWF0dXJlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGNvbnRleHQuZXh0ZXJuYWwgPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdwbGF0Zm9ybSBwcmV2aWV3Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdlbWJlZGRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgQmxhY2tCZXJyeSBPUyB2ZXJzaW9uLlxuICAgIC8vIGh0dHA6Ly9kb2NzLmJsYWNrYmVycnkuY29tL2VuL2RldmVsb3BlcnMvZGVsaXZlcmFibGVzLzE4MTY5L0hUVFBfaGVhZGVyc19zZW50X2J5X0JCX0Jyb3dzZXJfMTIzNDkxMV8xMS5qc3BcbiAgICBlbHNlIGlmICgoL1xcYkJsYWNrQmVycnlcXGIvLnRlc3QocHJvZHVjdCkgfHwgL1xcYkJCMTBcXGIvLnRlc3QodWEpKSAmJiAoZGF0YSA9XG4gICAgICAgICAgKFJlZ0V4cChwcm9kdWN0LnJlcGxhY2UoLyArL2csICcgKicpICsgJy8oWy5cXFxcZF0rKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICkpIHtcbiAgICAgIGRhdGEgPSBbZGF0YSwgL0JCMTAvLnRlc3QodWEpXTtcbiAgICAgIG9zID0gKGRhdGFbMV0gPyAocHJvZHVjdCA9IG51bGwsIG1hbnVmYWN0dXJlciA9ICdCbGFja0JlcnJ5JykgOiAnRGV2aWNlIFNvZnR3YXJlJykgKyAnICcgKyBkYXRhWzBdO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBpZGVudGlmeWluZy9tYXNraW5nIGl0c2VsZiBhcyBhbm90aGVyIGJyb3dzZXIuXG4gICAgLy8gaHR0cDovL3d3dy5vcGVyYS5jb20vc3VwcG9ydC9rYi92aWV3Lzg0My9cbiAgICBlbHNlIGlmICh0aGlzICE9IGZvck93biAmJiBwcm9kdWN0ICE9ICdXaWknICYmIChcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgb3BlcmEpIHx8XG4gICAgICAgICAgKC9PcGVyYS8udGVzdChuYW1lKSAmJiAvXFxiKD86TVNJRXxGaXJlZm94KVxcYi9pLnRlc3QodWEpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiT1MgWCAoPzpcXGQrXFwuKXsyLH0vLnRlc3Qob3MpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdJRScgJiYgKFxuICAgICAgICAgICAgKG9zICYmICEvXldpbi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDUuNSkgfHxcbiAgICAgICAgICAgIC9cXGJXaW5kb3dzIFhQXFxiLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gOCB8fFxuICAgICAgICAgICAgdmVyc2lvbiA9PSA4ICYmICEvXFxiVHJpZGVudFxcYi8udGVzdCh1YSlcbiAgICAgICAgICApKVxuICAgICAgICApICYmICFyZU9wZXJhLnRlc3QoKGRhdGEgPSBwYXJzZS5jYWxsKGZvck93biwgdWEucmVwbGFjZShyZU9wZXJhLCAnJykgKyAnOycpKSkgJiYgZGF0YS5uYW1lKSB7XG4gICAgICAvLyBXaGVuIFwiaWRlbnRpZnlpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIGJvdGggT3BlcmEgYW5kIHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGRhdGEgPSAnaW5nIGFzICcgKyBkYXRhLm5hbWUgKyAoKGRhdGEgPSBkYXRhLnZlcnNpb24pID8gJyAnICsgZGF0YSA6ICcnKTtcbiAgICAgIGlmIChyZU9wZXJhLnRlc3QobmFtZSkpIHtcbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSAmJiBvcyA9PSAnTWFjIE9TJykge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gJ2lkZW50aWZ5JyArIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBXaGVuIFwibWFza2luZ1wiLCB0aGUgVUEgY29udGFpbnMgb25seSB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBlbHNlIHtcbiAgICAgICAgZGF0YSA9ICdtYXNrJyArIGRhdGE7XG4gICAgICAgIGlmIChvcGVyYUNsYXNzKSB7XG4gICAgICAgICAgbmFtZSA9IGZvcm1hdChvcGVyYUNsYXNzLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMSAkMicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lID0gJ09wZXJhJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdXNlRmVhdHVyZXMpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGF5b3V0ID0gWydQcmVzdG8nXTtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXZWJLaXQgTmlnaHRseSBhbmQgYXBwcm94aW1hdGUgQ2hyb21lL1NhZmFyaSB2ZXJzaW9ucy5cbiAgICBpZiAoKGRhdGEgPSAoL1xcYkFwcGxlV2ViS2l0XFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgLy8gQ29ycmVjdCBidWlsZCBudW1iZXIgZm9yIG51bWVyaWMgY29tcGFyaXNvbi5cbiAgICAgIC8vIChlLmcuIFwiNTMyLjVcIiBiZWNvbWVzIFwiNTMyLjA1XCIpXG4gICAgICBkYXRhID0gW3BhcnNlRmxvYXQoZGF0YS5yZXBsYWNlKC9cXC4oXFxkKSQvLCAnLjAkMScpKSwgZGF0YV07XG4gICAgICAvLyBOaWdodGx5IGJ1aWxkcyBhcmUgcG9zdGZpeGVkIHdpdGggYSBcIitcIi5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmIGRhdGFbMV0uc2xpY2UoLTEpID09ICcrJykge1xuICAgICAgICBuYW1lID0gJ1dlYktpdCBOaWdodGx5JztcbiAgICAgICAgcHJlcmVsZWFzZSA9ICdhbHBoYSc7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhWzFdLnNsaWNlKDAsIC0xKTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFyIGluY29ycmVjdCBicm93c2VyIHZlcnNpb25zLlxuICAgICAgZWxzZSBpZiAodmVyc2lvbiA9PSBkYXRhWzFdIHx8XG4gICAgICAgICAgdmVyc2lvbiA9PSAoZGF0YVsyXSA9ICgvXFxiU2FmYXJpXFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgZnVsbCBDaHJvbWUgdmVyc2lvbiB3aGVuIGF2YWlsYWJsZS5cbiAgICAgIGRhdGFbMV0gPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKS9pLmV4ZWModWEpIHx8IDApWzFdO1xuICAgICAgLy8gRGV0ZWN0IEJsaW5rIGxheW91dCBlbmdpbmUuXG4gICAgICBpZiAoZGF0YVswXSA9PSA1MzcuMzYgJiYgZGF0YVsyXSA9PSA1MzcuMzYgJiYgcGFyc2VGbG9hdChkYXRhWzFdKSA+PSAyOCAmJiBsYXlvdXQgPT0gJ1dlYktpdCcpIHtcbiAgICAgICAgbGF5b3V0ID0gWydCbGluayddO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEphdmFTY3JpcHRDb3JlLlxuICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzY4NDc0L2hvdy1jYW4taS1kZXRlY3Qtd2hpY2gtamF2YXNjcmlwdC1lbmdpbmUtdjgtb3ItanNjLWlzLXVzZWQtYXQtcnVudGltZS1pbi1hbmRyb2lcbiAgICAgIGlmICghdXNlRmVhdHVyZXMgfHwgKCFsaWtlQ2hyb21lICYmICFkYXRhWzFdKSkge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIFNhZmFyaScpO1xuICAgICAgICBkYXRhID0gKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNDAwID8gMSA6IGRhdGEgPCA1MDAgPyAyIDogZGF0YSA8IDUyNiA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQgPyAnNCsnIDogZGF0YSA8IDUzNSA/IDUgOiBkYXRhIDwgNTM3ID8gNiA6IGRhdGEgPCA1MzggPyA3IDogZGF0YSA8IDYwMSA/IDggOiAnOCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBDaHJvbWUnKTtcbiAgICAgICAgZGF0YSA9IGRhdGFbMV0gfHwgKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNTMwID8gMSA6IGRhdGEgPCA1MzIgPyAyIDogZGF0YSA8IDUzMi4wNSA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQuMDMgPyA1IDogZGF0YSA8IDUzNC4wNyA/IDYgOiBkYXRhIDwgNTM0LjEwID8gNyA6IGRhdGEgPCA1MzQuMTMgPyA4IDogZGF0YSA8IDUzNC4xNiA/IDkgOiBkYXRhIDwgNTM0LjI0ID8gMTAgOiBkYXRhIDwgNTM0LjMwID8gMTEgOiBkYXRhIDwgNTM1LjAxID8gMTIgOiBkYXRhIDwgNTM1LjAyID8gJzEzKycgOiBkYXRhIDwgNTM1LjA3ID8gMTUgOiBkYXRhIDwgNTM1LjExID8gMTYgOiBkYXRhIDwgNTM1LjE5ID8gMTcgOiBkYXRhIDwgNTM2LjA1ID8gMTggOiBkYXRhIDwgNTM2LjEwID8gMTkgOiBkYXRhIDwgNTM3LjAxID8gMjAgOiBkYXRhIDwgNTM3LjExID8gJzIxKycgOiBkYXRhIDwgNTM3LjEzID8gMjMgOiBkYXRhIDwgNTM3LjE4ID8gMjQgOiBkYXRhIDwgNTM3LjI0ID8gMjUgOiBkYXRhIDwgNTM3LjM2ID8gMjYgOiBsYXlvdXQgIT0gJ0JsaW5rJyA/ICcyNycgOiAnMjgnKTtcbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgcG9zdGZpeCBvZiBcIi54XCIgb3IgXCIrXCIgZm9yIGFwcHJveGltYXRlIHZlcnNpb25zLlxuICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gKz0gJyAnICsgKGRhdGEgKz0gdHlwZW9mIGRhdGEgPT0gJ251bWJlcicgPyAnLngnIDogL1suK10vLnRlc3QoZGF0YSkgPyAnJyA6ICcrJykpO1xuICAgICAgLy8gT2JzY3VyZSB2ZXJzaW9uIGZvciBzb21lIFNhZmFyaSAxLTIgcmVsZWFzZXMuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAoIXZlcnNpb24gfHwgcGFyc2VJbnQodmVyc2lvbikgPiA0NSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IGRhdGE7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBkZXNrdG9wIG1vZGVzLlxuICAgIGlmIChuYW1lID09ICdPcGVyYScgJiYgIChkYXRhID0gL1xcYnpib3Z8enZhdiQvLmV4ZWMob3MpKSkge1xuICAgICAgbmFtZSArPSAnICc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIGlmIChkYXRhID09ICd6dmF2Jykge1xuICAgICAgICBuYW1lICs9ICdNaW5pJztcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuYW1lICs9ICdNb2JpbGUnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSArICckJyksICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IENocm9tZSBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAvXFxiQ2hyb21lXFxiLy5leGVjKGxheW91dCAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIG5hbWUgPSAnQ2hyb21lIE1vYmlsZSc7XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcblxuICAgICAgaWYgKC9cXGJPUyBYXFxiLy50ZXN0KG9zKSkge1xuICAgICAgICBtYW51ZmFjdHVyZXIgPSAnQXBwbGUnO1xuICAgICAgICBvcyA9ICdpT1MgNC4zKyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFN0cmlwIGluY29ycmVjdCBPUyB2ZXJzaW9ucy5cbiAgICBpZiAodmVyc2lvbiAmJiB2ZXJzaW9uLmluZGV4T2YoKGRhdGEgPSAvW1xcZC5dKyQvLmV4ZWMob3MpKSkgPT0gMCAmJlxuICAgICAgICB1YS5pbmRleE9mKCcvJyArIGRhdGEgKyAnLScpID4gLTEpIHtcbiAgICAgIG9zID0gdHJpbShvcy5yZXBsYWNlKGRhdGEsICcnKSk7XG4gICAgfVxuICAgIC8vIEFkZCBsYXlvdXQgZW5naW5lLlxuICAgIGlmIChsYXlvdXQgJiYgIS9cXGIoPzpBdmFudHxOb29rKVxcYi8udGVzdChuYW1lKSAmJiAoXG4gICAgICAgIC9Ccm93c2VyfEx1bmFzY2FwZXxNYXh0aG9uLy50ZXN0KG5hbWUpIHx8XG4gICAgICAgIG5hbWUgIT0gJ1NhZmFyaScgJiYgL15pT1MvLnRlc3Qob3MpICYmIC9cXGJTYWZhcmlcXGIvLnRlc3QobGF5b3V0WzFdKSB8fFxuICAgICAgICAvXig/OkFkb2JlfEFyb3JhfEJyZWFjaHxNaWRvcml8T3BlcmF8UGhhbnRvbXxSZWtvbnF8Um9ja3xTYW1zdW5nIEludGVybmV0fFNsZWlwbmlyfFdlYikvLnRlc3QobmFtZSkgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgLy8gRG9uJ3QgYWRkIGxheW91dCBkZXRhaWxzIHRvIGRlc2NyaXB0aW9uIGlmIHRoZXkgYXJlIGZhbHNleS5cbiAgICAgIChkYXRhID0gbGF5b3V0W2xheW91dC5sZW5ndGggLSAxXSkgJiYgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gQ29tYmluZSBjb250ZXh0dWFsIGluZm9ybWF0aW9uLlxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIGRlc2NyaXB0aW9uID0gWycoJyArIGRlc2NyaXB0aW9uLmpvaW4oJzsgJykgKyAnKSddO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgbWFudWZhY3R1cmVyIHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgcHJvZHVjdCAmJiBwcm9kdWN0LmluZGV4T2YobWFudWZhY3R1cmVyKSA8IDApIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ29uICcgKyBtYW51ZmFjdHVyZXIpO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgcHJvZHVjdCB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAocHJvZHVjdCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgoL15vbiAvLnRlc3QoZGVzY3JpcHRpb25bZGVzY3JpcHRpb24ubGVuZ3RoIC0gMV0pID8gJycgOiAnb24gJykgKyBwcm9kdWN0KTtcbiAgICB9XG4gICAgLy8gUGFyc2UgdGhlIE9TIGludG8gYW4gb2JqZWN0LlxuICAgIGlmIChvcykge1xuICAgICAgZGF0YSA9IC8gKFtcXGQuK10rKSQvLmV4ZWMob3MpO1xuICAgICAgaXNTcGVjaWFsQ2FzZWRPUyA9IGRhdGEgJiYgb3MuY2hhckF0KG9zLmxlbmd0aCAtIGRhdGFbMF0ubGVuZ3RoIC0gMSkgPT0gJy8nO1xuICAgICAgb3MgPSB7XG4gICAgICAgICdhcmNoaXRlY3R1cmUnOiAzMixcbiAgICAgICAgJ2ZhbWlseSc6IChkYXRhICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/IG9zLnJlcGxhY2UoZGF0YVswXSwgJycpIDogb3MsXG4gICAgICAgICd2ZXJzaW9uJzogZGF0YSA/IGRhdGFbMV0gOiBudWxsLFxuICAgICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgdmVyc2lvbiA9IHRoaXMudmVyc2lvbjtcbiAgICAgICAgICByZXR1cm4gdGhpcy5mYW1pbHkgKyAoKHZlcnNpb24gJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gJyAnICsgdmVyc2lvbiA6ICcnKSArICh0aGlzLmFyY2hpdGVjdHVyZSA9PSA2NCA/ICcgNjQtYml0JyA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gQWRkIGJyb3dzZXIvT1MgYXJjaGl0ZWN0dXJlLlxuICAgIGlmICgoZGF0YSA9IC9cXGIoPzpBTUR8SUF8V2lufFdPV3x4ODZffHgpNjRcXGIvaS5leGVjKGFyY2gpKSAmJiAhL1xcYmk2ODZcXGIvaS50ZXN0KGFyY2gpKSB7XG4gICAgICBpZiAob3MpIHtcbiAgICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgICAgIG9zLmZhbWlseSA9IG9zLmZhbWlseS5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSksICcnKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgICBuYW1lICYmICgvXFxiV09XNjRcXGIvaS50ZXN0KHVhKSB8fFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiAvXFx3KD86ODZ8MzIpJC8udGVzdChuYXYuY3B1Q2xhc3MgfHwgbmF2LnBsYXRmb3JtKSAmJiAhL1xcYldpbjY0OyB4NjRcXGIvaS50ZXN0KHVhKSkpXG4gICAgICApIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnMzItYml0Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENocm9tZSAzOSBhbmQgYWJvdmUgb24gT1MgWCBpcyBhbHdheXMgNjQtYml0LlxuICAgIGVsc2UgaWYgKFxuICAgICAgICBvcyAmJiAvXk9TIFgvLnRlc3Qob3MuZmFtaWx5KSAmJlxuICAgICAgICBuYW1lID09ICdDaHJvbWUnICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPj0gMzlcbiAgICApIHtcbiAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgIH1cblxuICAgIHVhIHx8ICh1YSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgdmFyIHBsYXRmb3JtID0ge307XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gZGVzY3JpcHRpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3NlcidzIGxheW91dCBlbmdpbmUuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gbGF5b3V0IGVuZ2luZXMgaW5jbHVkZTpcbiAgICAgKiBcIkJsaW5rXCIsIFwiRWRnZUhUTUxcIiwgXCJHZWNrb1wiLCBcIlRyaWRlbnRcIiBhbmQgXCJXZWJLaXRcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5sYXlvdXQgPSBsYXlvdXQgJiYgbGF5b3V0WzBdO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QncyBtYW51ZmFjdHVyZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBtYW51ZmFjdHVyZXJzIGluY2x1ZGU6XG4gICAgICogXCJBcHBsZVwiLCBcIkFyY2hvc1wiLCBcIkFtYXpvblwiLCBcIkFzdXNcIiwgXCJCYXJuZXMgJiBOb2JsZVwiLCBcIkJsYWNrQmVycnlcIixcbiAgICAgKiBcIkdvb2dsZVwiLCBcIkhQXCIsIFwiSFRDXCIsIFwiTEdcIiwgXCJNaWNyb3NvZnRcIiwgXCJNb3Rvcm9sYVwiLCBcIk5pbnRlbmRvXCIsXG4gICAgICogXCJOb2tpYVwiLCBcIlNhbXN1bmdcIiBhbmQgXCJTb255XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubWFudWZhY3R1cmVyID0gbWFudWZhY3R1cmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIvZW52aXJvbm1lbnQuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gYnJvd3NlciBuYW1lcyBpbmNsdWRlOlxuICAgICAqIFwiQ2hyb21lXCIsIFwiRWxlY3Ryb25cIiwgXCJGaXJlZm94XCIsIFwiRmlyZWZveCBmb3IgaU9TXCIsIFwiSUVcIixcbiAgICAgKiBcIk1pY3Jvc29mdCBFZGdlXCIsIFwiUGhhbnRvbUpTXCIsIFwiU2FmYXJpXCIsIFwiU2VhTW9ua2V5XCIsIFwiU2lsa1wiLFxuICAgICAqIFwiT3BlcmEgTWluaVwiIGFuZCBcIk9wZXJhXCJcbiAgICAgKlxuICAgICAqIE1vYmlsZSB2ZXJzaW9ucyBvZiBzb21lIGJyb3dzZXJzIGhhdmUgXCJNb2JpbGVcIiBhcHBlbmRlZCB0byB0aGVpciBuYW1lOlxuICAgICAqIGVnLiBcIkNocm9tZSBNb2JpbGVcIiwgXCJGaXJlZm94IE1vYmlsZVwiLCBcIklFIE1vYmlsZVwiIGFuZCBcIk9wZXJhIE1vYmlsZVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm5hbWUgPSBuYW1lO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFscGhhL2JldGEgcmVsZWFzZSBpbmRpY2F0b3IuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByZXJlbGVhc2UgPSBwcmVyZWxlYXNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QgaG9zdGluZyB0aGUgYnJvd3Nlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBwcm9kdWN0cyBpbmNsdWRlOlxuICAgICAqXG4gICAgICogXCJCbGFja0JlcnJ5XCIsIFwiR2FsYXh5IFM0XCIsIFwiTHVtaWFcIiwgXCJpUGFkXCIsIFwiaVBvZFwiLCBcImlQaG9uZVwiLCBcIktpbmRsZVwiLFxuICAgICAqIFwiS2luZGxlIEZpcmVcIiwgXCJOZXh1c1wiLCBcIk5vb2tcIiwgXCJQbGF5Qm9va1wiLCBcIlRvdWNoUGFkXCIgYW5kIFwiVHJhbnNmb3JtZXJcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcm9kdWN0ID0gcHJvZHVjdDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyJ3MgdXNlciBhZ2VudCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnVhID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS52ZXJzaW9uID0gbmFtZSAmJiB2ZXJzaW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5vcyA9IG9zIHx8IHtcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZSB0aGUgT1MgaXMgYnVpbHQgZm9yLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgbnVtYmVyfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2FyY2hpdGVjdHVyZSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIGZhbWlseSBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQ29tbW9uIHZhbHVlcyBpbmNsdWRlOlxuICAgICAgICogXCJXaW5kb3dzXCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCBSMiAvIDdcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IC8gVmlzdGFcIixcbiAgICAgICAqIFwiV2luZG93cyBYUFwiLCBcIk9TIFhcIiwgXCJVYnVudHVcIiwgXCJEZWJpYW5cIiwgXCJGZWRvcmFcIiwgXCJSZWQgSGF0XCIsIFwiU3VTRVwiLFxuICAgICAgICogXCJBbmRyb2lkXCIsIFwiaU9TXCIgYW5kIFwiV2luZG93cyBQaG9uZVwiXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAnZmFtaWx5JzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAndmVyc2lvbic6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogUmV0dXJucyB0aGUgT1Mgc3RyaW5nLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIE9TIHN0cmluZy5cbiAgICAgICAqL1xuICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7IHJldHVybiAnbnVsbCc7IH1cbiAgICB9O1xuXG4gICAgcGxhdGZvcm0ucGFyc2UgPSBwYXJzZTtcbiAgICBwbGF0Zm9ybS50b1N0cmluZyA9IHRvU3RyaW5nUGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0udmVyc2lvbikge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCh2ZXJzaW9uKTtcbiAgICB9XG4gICAgaWYgKHBsYXRmb3JtLm5hbWUpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuICAgIGlmIChvcyAmJiBuYW1lICYmICEob3MgPT0gU3RyaW5nKG9zKS5zcGxpdCgnICcpWzBdICYmIChvcyA9PSBuYW1lLnNwbGl0KCcgJylbMF0gfHwgcHJvZHVjdCkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKHByb2R1Y3QgPyAnKCcgKyBvcyArICcpJyA6ICdvbiAnICsgb3MpO1xuICAgIH1cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLmpvaW4oJyAnKTtcbiAgICB9XG4gICAgcmV0dXJuIHBsYXRmb3JtO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IHBsYXRmb3JtLlxuICB2YXIgcGxhdGZvcm0gPSBwYXJzZSgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMsIGxpa2Ugci5qcywgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEV4cG9zZSBwbGF0Zm9ybSBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIHBsYXRmb3JtIGlzXG4gICAgLy8gbG9hZGVkIGJ5IGEgc2NyaXB0IHRhZyBpbiB0aGUgcHJlc2VuY2Ugb2YgYW4gQU1EIGxvYWRlci5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvIHBsYXRmb3JtIGNhbiBiZSBhbGlhc2VkIHRocm91Z2ggcGF0aCBtYXBwaW5nLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBhbiBgZXhwb3J0c2Agb2JqZWN0LlxuICBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZvck93bihwbGF0Zm9ybSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgZnJlZUV4cG9ydHNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJ2YXIgdjEgPSByZXF1aXJlKCcuL3YxJyk7XG52YXIgdjQgPSByZXF1aXJlKCcuL3Y0Jyk7XG5cbnZhciB1dWlkID0gdjQ7XG51dWlkLnYxID0gdjE7XG51dWlkLnY0ID0gdjQ7XG5cbm1vZHVsZS5leHBvcnRzID0gdXVpZDtcbiIsIi8qKlxuICogQ29udmVydCBhcnJheSBvZiAxNiBieXRlIHZhbHVlcyB0byBVVUlEIHN0cmluZyBmb3JtYXQgb2YgdGhlIGZvcm06XG4gKiBYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFhcbiAqL1xudmFyIGJ5dGVUb0hleCA9IFtdO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICBieXRlVG9IZXhbaV0gPSAoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpO1xufVxuXG5mdW5jdGlvbiBieXRlc1RvVXVpZChidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IG9mZnNldCB8fCAwO1xuICB2YXIgYnRoID0gYnl0ZVRvSGV4O1xuICByZXR1cm4gYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJ5dGVzVG9VdWlkO1xuIiwiLy8gVW5pcXVlIElEIGNyZWF0aW9uIHJlcXVpcmVzIGEgaGlnaCBxdWFsaXR5IHJhbmRvbSAjIGdlbmVyYXRvci4gIEluIHRoZVxuLy8gYnJvd3NlciB0aGlzIGlzIGEgbGl0dGxlIGNvbXBsaWNhdGVkIGR1ZSB0byB1bmtub3duIHF1YWxpdHkgb2YgTWF0aC5yYW5kb20oKVxuLy8gYW5kIGluY29uc2lzdGVudCBzdXBwb3J0IGZvciB0aGUgYGNyeXB0b2AgQVBJLiAgV2UgZG8gdGhlIGJlc3Qgd2UgY2FuIHZpYVxuLy8gZmVhdHVyZS1kZXRlY3Rpb25cblxuLy8gZ2V0UmFuZG9tVmFsdWVzIG5lZWRzIHRvIGJlIGludm9rZWQgaW4gYSBjb250ZXh0IHdoZXJlIFwidGhpc1wiIGlzIGEgQ3J5cHRvIGltcGxlbWVudGF0aW9uLlxudmFyIGdldFJhbmRvbVZhbHVlcyA9ICh0eXBlb2YoY3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQoY3J5cHRvKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAodHlwZW9mKG1zQ3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChtc0NyeXB0bykpO1xuaWYgKGdldFJhbmRvbVZhbHVlcykge1xuICAvLyBXSEFUV0cgY3J5cHRvIFJORyAtIGh0dHA6Ly93aWtpLndoYXR3Zy5vcmcvd2lraS9DcnlwdG9cbiAgdmFyIHJuZHM4ID0gbmV3IFVpbnQ4QXJyYXkoMTYpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB3aGF0d2dSTkcoKSB7XG4gICAgZ2V0UmFuZG9tVmFsdWVzKHJuZHM4KTtcbiAgICByZXR1cm4gcm5kczg7XG4gIH07XG59IGVsc2Uge1xuICAvLyBNYXRoLnJhbmRvbSgpLWJhc2VkIChSTkcpXG4gIC8vXG4gIC8vIElmIGFsbCBlbHNlIGZhaWxzLCB1c2UgTWF0aC5yYW5kb20oKS4gIEl0J3MgZmFzdCwgYnV0IGlzIG9mIHVuc3BlY2lmaWVkXG4gIC8vIHF1YWxpdHkuXG4gIHZhciBybmRzID0gbmV3IEFycmF5KDE2KTtcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1hdGhSTkcoKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIHI7IGkgPCAxNjsgaSsrKSB7XG4gICAgICBpZiAoKGkgJiAweDAzKSA9PT0gMCkgciA9IE1hdGgucmFuZG9tKCkgKiAweDEwMDAwMDAwMDtcbiAgICAgIHJuZHNbaV0gPSByID4+PiAoKGkgJiAweDAzKSA8PCAzKSAmIDB4ZmY7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJuZHM7XG4gIH07XG59XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG4vLyAqKmB2MSgpYCAtIEdlbmVyYXRlIHRpbWUtYmFzZWQgVVVJRCoqXG4vL1xuLy8gSW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL0xpb3NLL1VVSUQuanNcbi8vIGFuZCBodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvdXVpZC5odG1sXG5cbnZhciBfbm9kZUlkO1xudmFyIF9jbG9ja3NlcTtcblxuLy8gUHJldmlvdXMgdXVpZCBjcmVhdGlvbiB0aW1lXG52YXIgX2xhc3RNU2VjcyA9IDA7XG52YXIgX2xhc3ROU2VjcyA9IDA7XG5cbi8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYnJvb2ZhL25vZGUtdXVpZCBmb3IgQVBJIGRldGFpbHNcbmZ1bmN0aW9uIHYxKG9wdGlvbnMsIGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gYnVmICYmIG9mZnNldCB8fCAwO1xuICB2YXIgYiA9IGJ1ZiB8fCBbXTtcblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgdmFyIG5vZGUgPSBvcHRpb25zLm5vZGUgfHwgX25vZGVJZDtcbiAgdmFyIGNsb2Nrc2VxID0gb3B0aW9ucy5jbG9ja3NlcSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jbG9ja3NlcSA6IF9jbG9ja3NlcTtcblxuICAvLyBub2RlIGFuZCBjbG9ja3NlcSBuZWVkIHRvIGJlIGluaXRpYWxpemVkIHRvIHJhbmRvbSB2YWx1ZXMgaWYgdGhleSdyZSBub3RcbiAgLy8gc3BlY2lmaWVkLiAgV2UgZG8gdGhpcyBsYXppbHkgdG8gbWluaW1pemUgaXNzdWVzIHJlbGF0ZWQgdG8gaW5zdWZmaWNpZW50XG4gIC8vIHN5c3RlbSBlbnRyb3B5LiAgU2VlICMxODlcbiAgaWYgKG5vZGUgPT0gbnVsbCB8fCBjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgdmFyIHNlZWRCeXRlcyA9IHJuZygpO1xuICAgIGlmIChub2RlID09IG51bGwpIHtcbiAgICAgIC8vIFBlciA0LjUsIGNyZWF0ZSBhbmQgNDgtYml0IG5vZGUgaWQsICg0NyByYW5kb20gYml0cyArIG11bHRpY2FzdCBiaXQgPSAxKVxuICAgICAgbm9kZSA9IF9ub2RlSWQgPSBbXG4gICAgICAgIHNlZWRCeXRlc1swXSB8IDB4MDEsXG4gICAgICAgIHNlZWRCeXRlc1sxXSwgc2VlZEJ5dGVzWzJdLCBzZWVkQnl0ZXNbM10sIHNlZWRCeXRlc1s0XSwgc2VlZEJ5dGVzWzVdXG4gICAgICBdO1xuICAgIH1cbiAgICBpZiAoY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuMi4yLCByYW5kb21pemUgKDE0IGJpdCkgY2xvY2tzZXFcbiAgICAgIGNsb2Nrc2VxID0gX2Nsb2Nrc2VxID0gKHNlZWRCeXRlc1s2XSA8PCA4IHwgc2VlZEJ5dGVzWzddKSAmIDB4M2ZmZjtcbiAgICB9XG4gIH1cblxuICAvLyBVVUlEIHRpbWVzdGFtcHMgYXJlIDEwMCBuYW5vLXNlY29uZCB1bml0cyBzaW5jZSB0aGUgR3JlZ29yaWFuIGVwb2NoLFxuICAvLyAoMTU4Mi0xMC0xNSAwMDowMCkuICBKU051bWJlcnMgYXJlbid0IHByZWNpc2UgZW5vdWdoIGZvciB0aGlzLCBzb1xuICAvLyB0aW1lIGlzIGhhbmRsZWQgaW50ZXJuYWxseSBhcyAnbXNlY3MnIChpbnRlZ2VyIG1pbGxpc2Vjb25kcykgYW5kICduc2VjcydcbiAgLy8gKDEwMC1uYW5vc2Vjb25kcyBvZmZzZXQgZnJvbSBtc2Vjcykgc2luY2UgdW5peCBlcG9jaCwgMTk3MC0wMS0wMSAwMDowMC5cbiAgdmFyIG1zZWNzID0gb3B0aW9ucy5tc2VjcyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5tc2VjcyA6IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuXG4gIC8vIFBlciA0LjIuMS4yLCB1c2UgY291bnQgb2YgdXVpZCdzIGdlbmVyYXRlZCBkdXJpbmcgdGhlIGN1cnJlbnQgY2xvY2tcbiAgLy8gY3ljbGUgdG8gc2ltdWxhdGUgaGlnaGVyIHJlc29sdXRpb24gY2xvY2tcbiAgdmFyIG5zZWNzID0gb3B0aW9ucy5uc2VjcyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5uc2VjcyA6IF9sYXN0TlNlY3MgKyAxO1xuXG4gIC8vIFRpbWUgc2luY2UgbGFzdCB1dWlkIGNyZWF0aW9uIChpbiBtc2VjcylcbiAgdmFyIGR0ID0gKG1zZWNzIC0gX2xhc3RNU2VjcykgKyAobnNlY3MgLSBfbGFzdE5TZWNzKS8xMDAwMDtcblxuICAvLyBQZXIgNC4yLjEuMiwgQnVtcCBjbG9ja3NlcSBvbiBjbG9jayByZWdyZXNzaW9uXG4gIGlmIChkdCA8IDAgJiYgb3B0aW9ucy5jbG9ja3NlcSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgY2xvY2tzZXEgPSBjbG9ja3NlcSArIDEgJiAweDNmZmY7XG4gIH1cblxuICAvLyBSZXNldCBuc2VjcyBpZiBjbG9jayByZWdyZXNzZXMgKG5ldyBjbG9ja3NlcSkgb3Igd2UndmUgbW92ZWQgb250byBhIG5ld1xuICAvLyB0aW1lIGludGVydmFsXG4gIGlmICgoZHQgPCAwIHx8IG1zZWNzID4gX2xhc3RNU2VjcykgJiYgb3B0aW9ucy5uc2VjcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbnNlY3MgPSAwO1xuICB9XG5cbiAgLy8gUGVyIDQuMi4xLjIgVGhyb3cgZXJyb3IgaWYgdG9vIG1hbnkgdXVpZHMgYXJlIHJlcXVlc3RlZFxuICBpZiAobnNlY3MgPj0gMTAwMDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3V1aWQudjEoKTogQ2FuXFwndCBjcmVhdGUgbW9yZSB0aGFuIDEwTSB1dWlkcy9zZWMnKTtcbiAgfVxuXG4gIF9sYXN0TVNlY3MgPSBtc2VjcztcbiAgX2xhc3ROU2VjcyA9IG5zZWNzO1xuICBfY2xvY2tzZXEgPSBjbG9ja3NlcTtcblxuICAvLyBQZXIgNC4xLjQgLSBDb252ZXJ0IGZyb20gdW5peCBlcG9jaCB0byBHcmVnb3JpYW4gZXBvY2hcbiAgbXNlY3MgKz0gMTIyMTkyOTI4MDAwMDA7XG5cbiAgLy8gYHRpbWVfbG93YFxuICB2YXIgdGwgPSAoKG1zZWNzICYgMHhmZmZmZmZmKSAqIDEwMDAwICsgbnNlY3MpICUgMHgxMDAwMDAwMDA7XG4gIGJbaSsrXSA9IHRsID4+PiAyNCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiAxNiAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdGwgJiAweGZmO1xuXG4gIC8vIGB0aW1lX21pZGBcbiAgdmFyIHRtaCA9IChtc2VjcyAvIDB4MTAwMDAwMDAwICogMTAwMDApICYgMHhmZmZmZmZmO1xuICBiW2krK10gPSB0bWggPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bWggJiAweGZmO1xuXG4gIC8vIGB0aW1lX2hpZ2hfYW5kX3ZlcnNpb25gXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMjQgJiAweGYgfCAweDEwOyAvLyBpbmNsdWRlIHZlcnNpb25cbiAgYltpKytdID0gdG1oID4+PiAxNiAmIDB4ZmY7XG5cbiAgLy8gYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgIChQZXIgNC4yLjIgLSBpbmNsdWRlIHZhcmlhbnQpXG4gIGJbaSsrXSA9IGNsb2Nrc2VxID4+PiA4IHwgMHg4MDtcblxuICAvLyBgY2xvY2tfc2VxX2xvd2BcbiAgYltpKytdID0gY2xvY2tzZXEgJiAweGZmO1xuXG4gIC8vIGBub2RlYFxuICBmb3IgKHZhciBuID0gMDsgbiA8IDY7ICsrbikge1xuICAgIGJbaSArIG5dID0gbm9kZVtuXTtcbiAgfVxuXG4gIHJldHVybiBidWYgPyBidWYgOiBieXRlc1RvVXVpZChiKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2MTtcbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbmZ1bmN0aW9uIHY0KG9wdGlvbnMsIGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gYnVmICYmIG9mZnNldCB8fCAwO1xuXG4gIGlmICh0eXBlb2Yob3B0aW9ucykgPT0gJ3N0cmluZycpIHtcbiAgICBidWYgPSBvcHRpb25zID09PSAnYmluYXJ5JyA/IG5ldyBBcnJheSgxNikgOiBudWxsO1xuICAgIG9wdGlvbnMgPSBudWxsO1xuICB9XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBybmRzID0gb3B0aW9ucy5yYW5kb20gfHwgKG9wdGlvbnMucm5nIHx8IHJuZykoKTtcblxuICAvLyBQZXIgNC40LCBzZXQgYml0cyBmb3IgdmVyc2lvbiBhbmQgYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgXG4gIHJuZHNbNl0gPSAocm5kc1s2XSAmIDB4MGYpIHwgMHg0MDtcbiAgcm5kc1s4XSA9IChybmRzWzhdICYgMHgzZikgfCAweDgwO1xuXG4gIC8vIENvcHkgYnl0ZXMgdG8gYnVmZmVyLCBpZiBwcm92aWRlZFxuICBpZiAoYnVmKSB7XG4gICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IDE2OyArK2lpKSB7XG4gICAgICBidWZbaSArIGlpXSA9IHJuZHNbaWldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWYgfHwgYnl0ZXNUb1V1aWQocm5kcyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjQ7XG4iLCIvKlxyXG5XaWxkRW1pdHRlci5qcyBpcyBhIHNsaW0gbGl0dGxlIGV2ZW50IGVtaXR0ZXIgYnkgQGhlbnJpa2pvcmV0ZWcgbGFyZ2VseSBiYXNlZFxyXG5vbiBAdmlzaW9ubWVkaWEncyBFbWl0dGVyIGZyb20gVUkgS2l0LlxyXG5cclxuV2h5PyBJIHdhbnRlZCBpdCBzdGFuZGFsb25lLlxyXG5cclxuSSBhbHNvIHdhbnRlZCBzdXBwb3J0IGZvciB3aWxkY2FyZCBlbWl0dGVycyBsaWtlIHRoaXM6XHJcblxyXG5lbWl0dGVyLm9uKCcqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgb3RoZXIsIGV2ZW50LCBwYXlsb2Fkcykge1xyXG5cclxufSk7XHJcblxyXG5lbWl0dGVyLm9uKCdzb21lbmFtZXNwYWNlKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcblBsZWFzZSBub3RlIHRoYXQgY2FsbGJhY2tzIHRyaWdnZXJlZCBieSB3aWxkY2FyZCByZWdpc3RlcmVkIGV2ZW50cyBhbHNvIGdldFxyXG50aGUgZXZlbnQgbmFtZSBhcyB0aGUgZmlyc3QgYXJndW1lbnQuXHJcbiovXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IFdpbGRFbWl0dGVyO1xyXG5cclxuZnVuY3Rpb24gV2lsZEVtaXR0ZXIoKSB7IH1cclxuXHJcbldpbGRFbWl0dGVyLm1peGluID0gZnVuY3Rpb24gKGNvbnN0cnVjdG9yKSB7XHJcbiAgICB2YXIgcHJvdG90eXBlID0gY29uc3RydWN0b3IucHJvdG90eXBlIHx8IGNvbnN0cnVjdG9yO1xyXG5cclxuICAgIHByb3RvdHlwZS5pc1dpbGRFbWl0dGVyPSB0cnVlO1xyXG5cclxuICAgIC8vIExpc3RlbiBvbiB0aGUgZ2l2ZW4gYGV2ZW50YCB3aXRoIGBmbmAuIFN0b3JlIGEgZ3JvdXAgbmFtZSBpZiBwcmVzZW50LlxyXG4gICAgcHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXHJcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcclxuICAgICAgICBmdW5jLl9ncm91cE5hbWUgPSBncm91cDtcclxuICAgICAgICAodGhpcy5jYWxsYmFja3NbZXZlbnRdID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdIHx8IFtdKS5wdXNoKGZ1bmMpO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBBZGRzIGFuIGBldmVudGAgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBzaW5nbGVcclxuICAgIC8vIHRpbWUgdGhlbiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQuXHJcbiAgICBwcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xyXG4gICAgICAgIHZhciBzZWxmID0gdGhpcyxcclxuICAgICAgICAgICAgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXHJcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcclxuICAgICAgICBmdW5jdGlvbiBvbigpIHtcclxuICAgICAgICAgICAgc2VsZi5vZmYoZXZlbnQsIG9uKTtcclxuICAgICAgICAgICAgZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLm9uKGV2ZW50LCBncm91cCwgb24pO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBVbmJpbmRzIGFuIGVudGlyZSBncm91cFxyXG4gICAgcHJvdG90eXBlLnJlbGVhc2VHcm91cCA9IGZ1bmN0aW9uIChncm91cE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLCBpLCBsZW4sIGhhbmRsZXJzO1xyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBoYW5kbGVycyA9IHRoaXMuY2FsbGJhY2tzW2l0ZW1dO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBoYW5kbGVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICAgICAgICAgICAgaWYgKGhhbmRsZXJzW2ldLl9ncm91cE5hbWUgPT09IGdyb3VwTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coJ3JlbW92aW5nJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0IGFuZCBzaG9ydGVuIHRoZSBhcnJheSB3ZSdyZSBsb29waW5nIHRocm91Z2hcclxuICAgICAgICAgICAgICAgICAgICBoYW5kbGVycy5zcGxpY2UoaSwgMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaS0tO1xyXG4gICAgICAgICAgICAgICAgICAgIGxlbi0tO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBSZW1vdmUgdGhlIGdpdmVuIGNhbGxiYWNrIGZvciBgZXZlbnRgIG9yIGFsbFxyXG4gICAgLy8gcmVnaXN0ZXJlZCBjYWxsYmFja3MuXHJcbiAgICBwcm90b3R5cGUub2ZmID0gZnVuY3Rpb24gKGV2ZW50LCBmbikge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcclxuICAgICAgICAgICAgaTtcclxuXHJcbiAgICAgICAgaWYgKCFjYWxsYmFja3MpIHJldHVybiB0aGlzO1xyXG5cclxuICAgICAgICAvLyByZW1vdmUgYWxsIGhhbmRsZXJzXHJcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcclxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyByZW1vdmUgc3BlY2lmaWMgaGFuZGxlclxyXG4gICAgICAgIGkgPSBjYWxsYmFja3MuaW5kZXhPZihmbik7XHJcbiAgICAgICAgY2FsbGJhY2tzLnNwbGljZShpLCAxKTtcclxuICAgICAgICBpZiAoY2FsbGJhY2tzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8vIEVtaXQgYGV2ZW50YCB3aXRoIHRoZSBnaXZlbiBhcmdzLlxyXG4gICAgLy8gYWxzbyBjYWxscyBhbnkgYCpgIGhhbmRsZXJzXHJcbiAgICBwcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIChldmVudCkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXHJcbiAgICAgICAgICAgIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcclxuICAgICAgICAgICAgc3BlY2lhbENhbGxiYWNrcyA9IHRoaXMuZ2V0V2lsZGNhcmRDYWxsYmFja3MoZXZlbnQpLFxyXG4gICAgICAgICAgICBpLFxyXG4gICAgICAgICAgICBsZW4sXHJcbiAgICAgICAgICAgIGl0ZW0sXHJcbiAgICAgICAgICAgIGxpc3RlbmVycztcclxuXHJcbiAgICAgICAgaWYgKGNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBjYWxsYmFja3Muc2xpY2UoKTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoc3BlY2lhbENhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBsZW4gPSBzcGVjaWFsQ2FsbGJhY2tzLmxlbmd0aDtcclxuICAgICAgICAgICAgbGlzdGVuZXJzID0gc3BlY2lhbENhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgW2V2ZW50XS5jb25jYXQoYXJncykpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gSGVscGVyIGZvciBmb3IgZmluZGluZyBzcGVjaWFsIHdpbGRjYXJkIGV2ZW50IGhhbmRsZXJzIHRoYXQgbWF0Y2ggdGhlIGV2ZW50XHJcbiAgICBwcm90b3R5cGUuZ2V0V2lsZGNhcmRDYWxsYmFja3MgPSBmdW5jdGlvbiAoZXZlbnROYW1lKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaXRlbSxcclxuICAgICAgICAgICAgc3BsaXQsXHJcbiAgICAgICAgICAgIHJlc3VsdCA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgc3BsaXQgPSBpdGVtLnNwbGl0KCcqJyk7XHJcbiAgICAgICAgICAgIGlmIChpdGVtID09PSAnKicgfHwgKHNwbGl0Lmxlbmd0aCA9PT0gMiAmJiBldmVudE5hbWUuc2xpY2UoMCwgc3BsaXRbMF0ubGVuZ3RoKSA9PT0gc3BsaXRbMF0pKSB7XHJcbiAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KHRoaXMuY2FsbGJhY2tzW2l0ZW1dKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfTtcclxuXHJcbn07XHJcblxyXG5XaWxkRW1pdHRlci5taXhpbihXaWxkRW1pdHRlcik7XHJcbiIsIi8qIVxuICogRXZlbnRFbWl0dGVyIHY1LjIuNCAtIGdpdC5pby9lZVxuICogVW5saWNlbnNlIC0gaHR0cDovL3VubGljZW5zZS5vcmcvXG4gKiBPbGl2ZXIgQ2FsZHdlbGwgLSBodHRwOi8vb2xpLm1lLnVrL1xuICogQHByZXNlcnZlXG4gKi9cblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuICAgICd1c2Ugc3RyaWN0JztcblxuICAgIC8qKlxuICAgICAqIENsYXNzIGZvciBtYW5hZ2luZyBldmVudHMuXG4gICAgICogQ2FuIGJlIGV4dGVuZGVkIHRvIHByb3ZpZGUgZXZlbnQgZnVuY3Rpb25hbGl0eSBpbiBvdGhlciBjbGFzc2VzLlxuICAgICAqXG4gICAgICogQGNsYXNzIEV2ZW50RW1pdHRlciBNYW5hZ2VzIGV2ZW50IHJlZ2lzdGVyaW5nIGFuZCBlbWl0dGluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7fVxuXG4gICAgLy8gU2hvcnRjdXRzIHRvIGltcHJvdmUgc3BlZWQgYW5kIHNpemVcbiAgICB2YXIgcHJvdG8gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlO1xuICAgIHZhciBvcmlnaW5hbEdsb2JhbFZhbHVlID0gZXhwb3J0cy5FdmVudEVtaXR0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyB0aGUgaW5kZXggb2YgdGhlIGxpc3RlbmVyIGZvciB0aGUgZXZlbnQgaW4gaXRzIHN0b3JhZ2UgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IGxpc3RlbmVycyBBcnJheSBvZiBsaXN0ZW5lcnMgdG8gc2VhcmNoIHRocm91Z2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGxvb2sgZm9yLlxuICAgICAqIEByZXR1cm4ge051bWJlcn0gSW5kZXggb2YgdGhlIHNwZWNpZmllZCBsaXN0ZW5lciwgLTEgaWYgbm90IGZvdW5kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVycywgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzW2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFsaWFzIGEgbWV0aG9kIHdoaWxlIGtlZXBpbmcgdGhlIGNvbnRleHQgY29ycmVjdCwgdG8gYWxsb3cgZm9yIG92ZXJ3cml0aW5nIG9mIHRhcmdldCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGFsaWFzZWQgbWV0aG9kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWxpYXMobmFtZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gYWxpYXNDbG9zdXJlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbbmFtZV0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBsaXN0ZW5lciBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaWxsIGluaXRpYWxpc2UgdGhlIGV2ZW50IG9iamVjdCBhbmQgbGlzdGVuZXIgYXJyYXlzIGlmIHJlcXVpcmVkLlxuICAgICAqIFdpbGwgcmV0dXJuIGFuIG9iamVjdCBpZiB5b3UgdXNlIGEgcmVnZXggc2VhcmNoLiBUaGUgb2JqZWN0IGNvbnRhaW5zIGtleXMgZm9yIGVhY2ggbWF0Y2hlZCBldmVudC4gU28gL2JhW3J6XS8gbWlnaHQgcmV0dXJuIGFuIG9iamVjdCBjb250YWluaW5nIGJhciBhbmQgYmF6LiBCdXQgb25seSBpZiB5b3UgaGF2ZSBlaXRoZXIgZGVmaW5lZCB0aGVtIHdpdGggZGVmaW5lRXZlbnQgb3IgYWRkZWQgc29tZSBsaXN0ZW5lcnMgdG8gdGhlbS5cbiAgICAgKiBFYWNoIHByb3BlcnR5IGluIHRoZSBvYmplY3QgcmVzcG9uc2UgaXMgYW4gYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfE9iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgdGhlIGV2ZW50LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldExpc3RlbmVycyhldnQpIHtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmV0dXJuIGEgY29uY2F0ZW5hdGVkIGFycmF5IG9mIGFsbCBtYXRjaGluZyBldmVudHMgaWZcbiAgICAgICAgLy8gdGhlIHNlbGVjdG9yIGlzIGEgcmVndWxhciBleHByZXNzaW9uLlxuICAgICAgICBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2Vba2V5XSA9IGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0gZXZlbnRzW2V2dF0gfHwgKGV2ZW50c1tldnRdID0gW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGxpc3Qgb2YgbGlzdGVuZXIgb2JqZWN0cyBhbmQgZmxhdHRlbnMgaXQgaW50byBhIGxpc3Qgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3RbXX0gbGlzdGVuZXJzIFJhdyBsaXN0ZW5lciBvYmplY3RzLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW119IEp1c3QgdGhlIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKi9cbiAgICBwcm90by5mbGF0dGVuTGlzdGVuZXJzID0gZnVuY3Rpb24gZmxhdHRlbkxpc3RlbmVycyhsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGZsYXRMaXN0ZW5lcnMgPSBbXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgZmxhdExpc3RlbmVycy5wdXNoKGxpc3RlbmVyc1tpXS5saXN0ZW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmxhdExpc3RlbmVycztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgcmVxdWVzdGVkIGxpc3RlbmVycyB2aWEgZ2V0TGlzdGVuZXJzIGJ1dCB3aWxsIGFsd2F5cyByZXR1cm4gdGhlIHJlc3VsdHMgaW5zaWRlIGFuIG9iamVjdC4gVGhpcyBpcyBtYWlubHkgZm9yIGludGVybmFsIHVzZSBidXQgb3RoZXJzIG1heSBmaW5kIGl0IHVzZWZ1bC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciBhbiBldmVudCBpbiBhbiBvYmplY3QuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzQXNPYmplY3QgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnNBc09iamVjdChldnQpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBpZiAobGlzdGVuZXJzIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICByZXNwb25zZVtldnRdID0gbGlzdGVuZXJzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlIHx8IGxpc3RlbmVycztcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gaXNWYWxpZExpc3RlbmVyIChsaXN0ZW5lcikge1xuICAgICAgICBpZiAodHlwZW9mIGxpc3RlbmVyID09PSAnZnVuY3Rpb24nIHx8IGxpc3RlbmVyIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9IGVsc2UgaWYgKGxpc3RlbmVyICYmIHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIubGlzdGVuZXIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBsaXN0ZW5lciBmdW5jdGlvbiB0byB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFRoZSBsaXN0ZW5lciB3aWxsIG5vdCBiZSBhZGRlZCBpZiBpdCBpcyBhIGR1cGxpY2F0ZS5cbiAgICAgKiBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGl0IGlzIGNhbGxlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSB0aGVuIHRoZSBsaXN0ZW5lciB3aWxsIGJlIGFkZGVkIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICghaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJJc1dyYXBwZWQgPSB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnB1c2gobGlzdGVuZXJJc1dyYXBwZWQgPyBsaXN0ZW5lciA6IHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgICAgICAgICBvbmNlOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZExpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub24gPSBhbGlhcygnYWRkTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIFNlbWktYWxpYXMgb2YgYWRkTGlzdGVuZXIuIEl0IHdpbGwgYWRkIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlXG4gICAgICogYXV0b21hdGljYWxseSByZW1vdmVkIGFmdGVyIGl0cyBmaXJzdCBleGVjdXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZE9uY2VMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZE9uY2VMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZExpc3RlbmVyKGV2dCwge1xuICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgb25jZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkT25jZUxpc3RlbmVyLlxuICAgICAqL1xuICAgIHByb3RvLm9uY2UgPSBhbGlhcygnYWRkT25jZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmVzIGFuIGV2ZW50IG5hbWUuIFRoaXMgaXMgcmVxdWlyZWQgaWYgeW91IHdhbnQgdG8gdXNlIGEgcmVnZXggdG8gYWRkIGEgbGlzdGVuZXIgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIElmIHlvdSBkb24ndCBkbyB0aGlzIHRoZW4gaG93IGRvIHlvdSBleHBlY3QgaXQgdG8ga25vdyB3aGF0IGV2ZW50IHRvIGFkZCB0bz8gU2hvdWxkIGl0IGp1c3QgYWRkIHRvIGV2ZXJ5IHBvc3NpYmxlIG1hdGNoIGZvciBhIHJlZ2V4PyBOby4gVGhhdCBpcyBzY2FyeSBhbmQgYmFkLlxuICAgICAqIFlvdSBuZWVkIHRvIHRlbGwgaXQgd2hhdCBldmVudCBuYW1lcyBzaG91bGQgYmUgbWF0Y2hlZCBieSBhIHJlZ2V4LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBjcmVhdGUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnQgPSBmdW5jdGlvbiBkZWZpbmVFdmVudChldnQpIHtcbiAgICAgICAgdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFVzZXMgZGVmaW5lRXZlbnQgdG8gZGVmaW5lIG11bHRpcGxlIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nW119IGV2dHMgQW4gYXJyYXkgb2YgZXZlbnQgbmFtZXMgdG8gZGVmaW5lLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50cyA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50cyhldnRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXZ0cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgdGhpcy5kZWZpbmVFdmVudChldnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIGZyb20gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaGVuIHBhc3NlZCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSwgaXQgd2lsbCByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byByZW1vdmUgZnJvbSB0aGUgZXZlbnQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBpbmRleDtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcik7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUxpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub2ZmID0gYWxpYXMoJ3JlbW92ZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBhZGQgdGhlIGFycmF5IG9mIGxpc3RlbmVycyB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICogWWVhaCwgdGhpcyBmdW5jdGlvbiBkb2VzIHF1aXRlIGEgYml0LiBUaGF0J3MgcHJvYmFibHkgYSBiYWQgdGhpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyhmYWxzZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byByZW1vdmUgdGhlIGxpc3RlbmVycyBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byByZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXJzID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnModHJ1ZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBFZGl0cyBsaXN0ZW5lcnMgaW4gYnVsay4gVGhlIGFkZExpc3RlbmVycyBhbmQgcmVtb3ZlTGlzdGVuZXJzIG1ldGhvZHMgYm90aCB1c2UgdGhpcyB0byBkbyB0aGVpciBqb2IuIFlvdSBzaG91bGQgcmVhbGx5IHVzZSB0aG9zZSBpbnN0ZWFkLCB0aGlzIGlzIGEgbGl0dGxlIGxvd2VyIGxldmVsLlxuICAgICAqIFRoZSBmaXJzdCBhcmd1bWVudCB3aWxsIGRldGVybWluZSBpZiB0aGUgbGlzdGVuZXJzIGFyZSByZW1vdmVkICh0cnVlKSBvciBhZGRlZCAoZmFsc2UpLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHlvdSBjYW4gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkL3JlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gbWFuaXB1bGF0ZSB0aGUgbGlzdGVuZXJzIG9mIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVtb3ZlIFRydWUgaWYgeW91IHdhbnQgdG8gcmVtb3ZlIGxpc3RlbmVycywgZmFsc2UgaWYgeW91IHdhbnQgdG8gYWRkLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkL3JlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5tYW5pcHVsYXRlTGlzdGVuZXJzID0gZnVuY3Rpb24gbWFuaXB1bGF0ZUxpc3RlbmVycyhyZW1vdmUsIGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgdmFsdWU7XG4gICAgICAgIHZhciBzaW5nbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVyIDogdGhpcy5hZGRMaXN0ZW5lcjtcbiAgICAgICAgdmFyIG11bHRpcGxlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lcnMgOiB0aGlzLmFkZExpc3RlbmVycztcblxuICAgICAgICAvLyBJZiBldnQgaXMgYW4gb2JqZWN0IHRoZW4gcGFzcyBlYWNoIG9mIGl0cyBwcm9wZXJ0aWVzIHRvIHRoaXMgbWV0aG9kXG4gICAgICAgIGlmICh0eXBlb2YgZXZ0ID09PSAnb2JqZWN0JyAmJiAhKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgICAgICAgIGZvciAoaSBpbiBldnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZ0Lmhhc093blByb3BlcnR5KGkpICYmICh2YWx1ZSA9IGV2dFtpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGFzcyB0aGUgc2luZ2xlIGxpc3RlbmVyIHN0cmFpZ2h0IHRocm91Z2ggdG8gdGhlIHNpbmd1bGFyIG1ldGhvZFxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgcGFzcyBiYWNrIHRvIHRoZSBtdWx0aXBsZSBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBTbyBldnQgbXVzdCBiZSBhIHN0cmluZ1xuICAgICAgICAgICAgLy8gQW5kIGxpc3RlbmVycyBtdXN0IGJlIGFuIGFycmF5IG9mIGxpc3RlbmVyc1xuICAgICAgICAgICAgLy8gTG9vcCBvdmVyIGl0IGFuZCBwYXNzIGVhY2ggb25lIHRvIHRoZSBtdWx0aXBsZSBtZXRob2RcbiAgICAgICAgICAgIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGV2dCwgbGlzdGVuZXJzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgZnJvbSBhIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBJZiB5b3UgZG8gbm90IHNwZWNpZnkgYW4gZXZlbnQgdGhlbiBhbGwgbGlzdGVuZXJzIHdpbGwgYmUgcmVtb3ZlZC5cbiAgICAgKiBUaGF0IG1lYW5zIGV2ZXJ5IGV2ZW50IHdpbGwgYmUgZW1wdGllZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ2V4IHRvIHJlbW92ZSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IFtldnRdIE9wdGlvbmFsIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvci4gV2lsbCByZW1vdmUgZnJvbSBldmVyeSBldmVudCBpZiBub3QgcGFzc2VkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24gcmVtb3ZlRXZlbnQoZXZ0KSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mIGV2dDtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJlbW92ZSBkaWZmZXJlbnQgdGhpbmdzIGRlcGVuZGluZyBvbiB0aGUgc3RhdGUgb2YgZXZ0XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbZXZ0XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgZXZlbnRzIG1hdGNoaW5nIHRoZSByZWdleC5cbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBpbiBhbGwgZXZlbnRzXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUV2ZW50LlxuICAgICAqXG4gICAgICogQWRkZWQgdG8gbWlycm9yIHRoZSBub2RlIEFQSS5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBhbGlhcygncmVtb3ZlRXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGFuIGV2ZW50IG9mIHlvdXIgY2hvaWNlLlxuICAgICAqIFdoZW4gZW1pdHRlZCwgZXZlcnkgbGlzdGVuZXIgYXR0YWNoZWQgdG8gdGhhdCBldmVudCB3aWxsIGJlIGV4ZWN1dGVkLlxuICAgICAqIElmIHlvdSBwYXNzIHRoZSBvcHRpb25hbCBhcmd1bWVudCBhcnJheSB0aGVuIHRob3NlIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCB0byBldmVyeSBsaXN0ZW5lciB1cG9uIGV4ZWN1dGlvbi5cbiAgICAgKiBCZWNhdXNlIGl0IHVzZXMgYGFwcGx5YCwgeW91ciBhcnJheSBvZiBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgYXMgaWYgeW91IHdyb3RlIHRoZW0gb3V0IHNlcGFyYXRlbHkuXG4gICAgICogU28gdGhleSB3aWxsIG5vdCBhcnJpdmUgd2l0aGluIHRoZSBhcnJheSBvbiB0aGUgb3RoZXIgc2lkZSwgdGhleSB3aWxsIGJlIHNlcGFyYXRlLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthcmdzXSBPcHRpb25hbCBhcnJheSBvZiBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdEV2ZW50ID0gZnVuY3Rpb24gZW1pdEV2ZW50KGV2dCwgYXJncykge1xuICAgICAgICB2YXIgbGlzdGVuZXJzTWFwID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJzO1xuICAgICAgICB2YXIgbGlzdGVuZXI7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzTWFwKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzTWFwLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnNNYXBba2V5XS5zbGljZSgwKTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHNoYWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkIGVpdGhlciB3aXRoIGEgYmFzaWMgY2FsbCBvciBhbiBhcHBseSBpZiB0aGVyZSBpcyBhbiBhcmdzIGFycmF5XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChsaXN0ZW5lci5vbmNlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBsaXN0ZW5lci5saXN0ZW5lci5hcHBseSh0aGlzLCBhcmdzIHx8IFtdKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgPT09IHRoaXMuX2dldE9uY2VSZXR1cm5WYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGVtaXRFdmVudFxuICAgICAqL1xuICAgIHByb3RvLnRyaWdnZXIgPSBhbGlhcygnZW1pdEV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBTdWJ0bHkgZGlmZmVyZW50IGZyb20gZW1pdEV2ZW50IGluIHRoYXQgaXQgd2lsbCBwYXNzIGl0cyBhcmd1bWVudHMgb24gdG8gdGhlIGxpc3RlbmVycywgYXMgb3Bwb3NlZCB0byB0YWtpbmcgYSBzaW5nbGUgYXJyYXkgb2YgYXJndW1lbnRzIHRvIHBhc3Mgb24uXG4gICAgICogQXMgd2l0aCBlbWl0RXZlbnQsIHlvdSBjYW4gcGFzcyBhIHJlZ2V4IGluIHBsYWNlIG9mIHRoZSBldmVudCBuYW1lIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gT3B0aW9uYWwgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdCA9IGZ1bmN0aW9uIGVtaXQoZXZ0KSB7XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW1pdEV2ZW50KGV2dCwgYXJncyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmIGFcbiAgICAgKiBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhlIG9uZSBzZXQgaGVyZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZFxuICAgICAqIGFmdGVyIGV4ZWN1dGlvbi4gVGhpcyB2YWx1ZSBkZWZhdWx0cyB0byB0cnVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbmV3IHZhbHVlIHRvIGNoZWNrIGZvciB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uc2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gc2V0T25jZVJldHVyblZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX29uY2VSZXR1cm5WYWx1ZSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWZcbiAgICAgKiB0aGUgbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoaXMgb25lIHRoZW4gaXQgc2hvdWxkIGJlIHJlbW92ZWRcbiAgICAgKiBhdXRvbWF0aWNhbGx5LiBJdCB3aWxsIHJldHVybiB0cnVlIGJ5IGRlZmF1bHQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHsqfEJvb2xlYW59IFRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGZvciBvciB0aGUgZGVmYXVsdCwgdHJ1ZS5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gX2dldE9uY2VSZXR1cm5WYWx1ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkoJ19vbmNlUmV0dXJuVmFsdWUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29uY2VSZXR1cm5WYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGV2ZW50cyBvYmplY3QgYW5kIGNyZWF0ZXMgb25lIGlmIHJlcXVpcmVkLlxuICAgICAqXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgZXZlbnRzIHN0b3JhZ2Ugb2JqZWN0LlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRFdmVudHMgPSBmdW5jdGlvbiBfZ2V0RXZlbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXZlbnRzIHx8ICh0aGlzLl9ldmVudHMgPSB7fSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJldmVydHMgdGhlIGdsb2JhbCB7QGxpbmsgRXZlbnRFbWl0dGVyfSB0byBpdHMgcHJldmlvdXMgdmFsdWUgYW5kIHJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhpcyB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IE5vbiBjb25mbGljdGluZyBFdmVudEVtaXR0ZXIgY2xhc3MuXG4gICAgICovXG4gICAgRXZlbnRFbWl0dGVyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiBub0NvbmZsaWN0KCkge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IG9yaWdpbmFsR2xvYmFsVmFsdWU7XG4gICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgfTtcblxuICAgIC8vIEV4cG9zZSB0aGUgY2xhc3MgZWl0aGVyIHZpYSBBTUQsIENvbW1vbkpTIG9yIHRoZSBnbG9iYWwgb2JqZWN0XG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKXtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG59KHRoaXMgfHwge30pKTtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdS9PcGVuVmlkdSc7XG5cbmlmICh3aW5kb3cpIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICB3aW5kb3dbJ09wZW5WaWR1J10gPSBPcGVuVmlkdTtcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmRlYnVnKCghIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCcgOiAnUmVtb3RlJyksICdjYW5kaWRhdGUgZm9yJyxcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkLCBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcblxuICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ29uSWNlQ2FuZGlkYXRlJywge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJ1xuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0UmVtb3RlU3RyZWFtcyhvcHRpb25zOiBTdHJlYW1PcHRpb25zU2VydmVyW10pOiB2b2lkIHtcblxuICAgICAgICAvLyBUaGlzIGlzIHJlYWR5IGZvciBzdXBwb3J0aW5nIG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb24gb2JqZWN0LiBSaWdodCBub3cgdGhlIGxvb3Agd2lsbCBhbHdheXMgcnVuIGp1c3Qgb25jZVxuICAgICAgICAvLyB0aGlzLnN0cmVhbSBzaG91bGQgYWxzbyBiZSByZXBsYWNlZCBieSBhIGNvbGxlY3Rpb24gb2Ygc3RyZWFtcyB0byBzdXBwb3J0IG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb25cbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IG9wdHMuaWQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogdGhpcyxcbiAgICAgICAgICAgICAgICBmcmFtZVJhdGU6IG9wdHMuZnJhbWVSYXRlLFxuICAgICAgICAgICAgICAgIHJlY3ZBdWRpbzogb3B0cy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICByZWN2VmlkZW86IG9wdHMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyZWFtKHRoaXMuc2Vzc2lvbiwgc3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgIHRoaXMuYWRkU3RyZWFtKHN0cmVhbSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnQ29ubmVjdGlvbicgd2l0aCAnY29ubmVjdGlvbklkJyBbXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArICddIGlzIG5vdyBjb25maWd1cmVkIGZvciByZWNlaXZpbmcgU3RyZWFtcyB3aXRoIG9wdGlvbnM6ICcsIHRoaXMuc3RyZWFtLmluYm91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkU3RyZWFtKHN0cmVhbTogU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5jb25uZWN0aW9uID0gdGhpcztcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZVN0cmVhbShzdHJlYW1JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IExvY2FsUmVjb3JkZXJTdGF0ZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmRlY2xhcmUgdmFyIE1lZGlhUmVjb3JkZXI6IGFueTtcblxuXG4vKipcbiAqIEVhc3kgcmVjb3JkaW5nIG9mIFtbU3RyZWFtXV0gb2JqZWN0cyBzdHJhaWdodGF3YXkgZnJvbSB0aGUgYnJvd3Nlci5cbiAqXG4gKiA+IFdBUk5JTkc6IFBlcmZvcm1pbmcgYnJvd3NlciBsb2NhbCByZWNvcmRpbmcgb2YgKipyZW1vdGUgc3RyZWFtcyoqIG1heSBjYXVzZSBzb21lIHRyb3VibGVzLiBBIGxvbmcgd2FpdGluZyB0aW1lIG1heSBiZSByZXF1aXJlZCBhZnRlciBjYWxsaW5nIF9Mb2NhbFJlY29yZGVyLnN0b3AoKV8gaW4gdGhpcyBjYXNlXG4gKi9cbmV4cG9ydCBjbGFzcyBMb2NhbFJlY29yZGVyIHtcblxuICAgIHN0YXRlOiBMb2NhbFJlY29yZGVyU3RhdGU7XG5cbiAgICBwcml2YXRlIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuICAgIHByaXZhdGUgbWVkaWFSZWNvcmRlcjogYW55O1xuICAgIHByaXZhdGUgY2h1bmtzOiBhbnlbXSA9IFtdO1xuICAgIHByaXZhdGUgYmxvYjogQmxvYjtcbiAgICBwcml2YXRlIGNvdW50ID0gMDtcbiAgICBwcml2YXRlIGlkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXdTcmM6IHN0cmluZztcbiAgICBwcml2YXRlIGh0bWxQYXJlbnRFbGVtZW50SWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlldzogSFRNTFZpZGVvRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gKCEhdGhpcy5zdHJlYW0uY29ubmVjdGlvbikgPyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA6ICdkZWZhdWx0LWNvbm5lY3Rpb24nO1xuICAgICAgICB0aGlzLmlkID0gdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXycgKyB0aGlzLmNvbm5lY3Rpb25JZCArICdfbG9jYWxyZWNvcmQnO1xuICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU3RhcnRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQURZYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdGFydGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZWNvcmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdHJ5IHtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlY29yZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQURZXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuY2xlYW4oKVxcJyBvciBpbml0IGEgbmV3IExvY2FsUmVjb3JkZXIgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIlN0YXJ0aW5nIGxvY2FsIHJlY29yZGluZyBvZiBzdHJlYW0gJ1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyBcIicgb2YgY29ubmVjdGlvbiAnXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArIFwiJ1wiKTtcblxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgb3B0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDknKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz12cDknIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JyB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDgnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz12cDgnIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1VzaW5nIG1pbWVUeXBlICcgKyBvcHRpb25zLm1pbWVUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIodGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdpc1R5cGVTdXBwb3J0ZWQgaXMgbm90IHN1cHBvcnRlZCwgdXNpbmcgZGVmYXVsdCBjb2RlY3MgZm9yIGJyb3dzZXInKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIodGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXJ0KDEwKTtcblxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmRhdGFhdmFpbGFibGUgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY2h1bmtzLnB1c2goZS5kYXRhKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmVycm9yID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIGVycm9yOiAnLCBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0YXJ0ID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0YXJ0ZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnBhdXNlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHBhdXNlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25yZXN1bWUgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcmVzdW1lZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub253YXJuaW5nID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciB3YXJuaW5nOiAnICsgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIHJlc29sdmUoKTtcblxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEVuZHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYCBvciBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgRklOSVNIRURgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0b3BwZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHN0b3AoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIG9yIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0b3AoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUGF1c2VzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2AuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFBBVVNFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyB3YXMgc3VjY2Vzc2Z1bGx5IHBhdXNlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcGF1c2UoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC5wYXVzZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgb3IgXFwnTG9jYWxSZWNvcmRlci5yZXN1bWUoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5wYXVzZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXN1bWVzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFBBVVNFRGAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyB3YXMgc3VjY2Vzc2Z1bGx5IHJlc3VtZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlc3VtZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlc3VtZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnBhdXNlKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucmVzdW1lKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHJldmlld3MgdGhlIHJlY29yZGluZywgYXBwZW5kaW5nIGEgbmV3IEhUTUxWaWRlb0VsZW1lbnQgdG8gZWxlbWVudCB3aXRoIGlkIGBwYXJlbnRJZGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBwcmV2aWV3KHBhcmVudEVsZW1lbnQpOiBIVE1MVmlkZW9FbGVtZW50IHtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnByZXZpZXcoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuaWQgPSB0aGlzLmlkO1xuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5hdXRvcGxheSA9IHRydWU7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBwYXJlbnRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhpcy5odG1sUGFyZW50RWxlbWVudElkID0gcGFyZW50RWxlbWVudDtcblxuICAgICAgICAgICAgY29uc3QgcGFyZW50RWxlbWVudERvbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBhcmVudEVsZW1lbnQpO1xuICAgICAgICAgICAgaWYgKHBhcmVudEVsZW1lbnREb20pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnREb20uYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5odG1sUGFyZW50RWxlbWVudElkID0gcGFyZW50RWxlbWVudC5pZDtcbiAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5zcmMgPSB0aGlzLnZpZGVvUHJldmlld1NyYztcblxuICAgICAgICByZXR1cm4gdGhpcy52aWRlb1ByZXZpZXc7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBHcmFjZWZ1bGx5IHN0b3BzIGFuZCBjbGVhbnMgdGhlIGN1cnJlbnQgcmVjb3JkaW5nIChXQVJOSU5HOiBpdCBpcyBjb21wbGV0ZWx5IGRpc21pc3NlZCkuIFNldHMgW1tzdGF0ZV1dIHRvIGBSRUFEWWAgc28gdGhlIHJlY29yZGluZyBjYW4gc3RhcnQgYWdhaW5cbiAgICAgKi9cbiAgICBjbGVhbigpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZiA9ICgpID0+IHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmJsb2I7XG4gICAgICAgICAgICB0aGlzLmNodW5rcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IDA7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tZWRpYVJlY29yZGVyO1xuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkcgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgdGhpcy5zdG9wKCkudGhlbigoKSA9PiBmKCkpLmNhdGNoKCgpID0+IGYoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIERvd25sb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gdGhyb3VnaCB0aGUgYnJvd3Nlci4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIGRvd25sb2FkKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLmRvd25sb2FkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgYTogSFRNTEFuY2hvckVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICAgICAgICBhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xuXG4gICAgICAgICAgICBjb25zdCB1cmwgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgYS5ocmVmID0gdXJsO1xuICAgICAgICAgICAgYS5kb3dubG9hZCA9IHRoaXMuaWQgKyAnLndlYm0nO1xuICAgICAgICAgICAgYS5jbGljaygpO1xuICAgICAgICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcblxuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHJhdyBCbG9iIGZpbGUuIE1ldGhvZHMgcHJldmlldywgZG93bmxvYWQsIHVwbG9hZEFzQmluYXJ5IGFuZCB1cGxvYWRBc011bHRpcGFydGZpbGUgdXNlIHRoaXMgc2FtZSBmaWxlIHRvIHBlcmZvcm0gdGhlaXIgc3BlY2lmaWMgYWN0aW9ucy4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIGdldEJsb2IoKTogQmxvYiB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignQ2FsbCBcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgYmVmb3JlIGdldHRpbmcgQmxvYiBmaWxlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmxvYjtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBsb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gYXMgYSBiaW5hcnkgZmlsZSBwZXJmb3JtaW5nIGFuIEhUVFAvUE9TVCBvcGVyYXRpb24gdG8gVVJMIGBlbmRwb2ludGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGAuIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBjYW4gYmUgcGFzc2VkIGFzIHNlY29uZCBwYXJhbWV0ZXIuIEZvciBleGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHZhciBoZWFkZXJzID0ge1xuICAgICAqICBcIkNvb2tpZVwiOiBcIiRWZXJzaW9uPTE7IFNraW49bmV3O1wiLFxuICAgICAqICBcIkF1dGhvcml6YXRpb25cIjpcIkJhc2ljIFFXeGhaR3BianB1SUhObGN0WlE9PVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB3aXRoIHRoZSBgaHR0cC5yZXNwb25zZVRleHRgIGZyb20gc2VydmVyIGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggdGhlIGZhaWxlZCBgaHR0cC5zdGF0dXNgIGlmIG5vdFxuICAgICAqL1xuICAgIHVwbG9hZEFzQmluYXJ5KGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNCaW5hcnkoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoaHR0cC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBodHRwLnNlbmQodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIG11bHRpcGFydCBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90OlxuICAgICAqL1xuICAgIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzZW5kYWJsZSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgICAgIHNlbmRhYmxlLmFwcGVuZCgnZmlsZScsIHRoaXMuYmxvYiwgdGhpcy5pZCArICcud2VibScpO1xuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoaHR0cC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGh0dHAuc2VuZChzZW5kYWJsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIG9uU3RvcERlZmF1bHQoKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0b3BwZWQgIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcblxuICAgICAgICB0aGlzLmJsb2IgPSBuZXcgQmxvYih0aGlzLmNodW5rcywgeyB0eXBlOiAndmlkZW8vd2VibScgfSk7XG4gICAgICAgIHRoaXMuY2h1bmtzID0gW107XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXdTcmMgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTCh0aGlzLmJsb2IpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQ7XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IExvY2FsUmVjb3JkZXIgfSBmcm9tICcuL0xvY2FsUmVjb3JkZXInO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBEZXZpY2UgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0RldmljZSc7XG5pbXBvcnQgeyBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IHsgUHVibGlzaGVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvUHVibGlzaGVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmdBdXRvIGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8nO1xuaW1wb3J0ICogYXMgc2NyZWVuU2hhcmluZyBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZyc7XG5cbmltcG9ydCBScGNCdWlsZGVyID0gcmVxdWlyZSgnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbi8qKlxuICogRW50cnlwb2ludCBvZiBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKiBVc2UgaXQgdG8gaW5pdGlhbGl6ZSBvYmplY3RzIG9mIHR5cGUgW1tTZXNzaW9uXV0sIFtbUHVibGlzaGVyXV0gYW5kIFtbTG9jYWxSZWNvcmRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgcHJpdmF0ZSBqc29uUnBjQ2xpZW50OiBhbnk7XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlc3Npb246IFNlc3Npb247XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICB3c1VyaTogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VjcmV0ID0gJyc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByZWNvcmRlciA9IGZhbHNlO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaWNlU2VydmVyczogUlRDSWNlU2VydmVyW107XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByb2xlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBhZHZhbmNlZENvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uID0ge307XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgY29uc29sZS5pbmZvKFwiJ09wZW5WaWR1JyBpbml0aWFsaXplZFwiKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgbmV3IHNlc3Npb25cbiAgICovXG4gIGluaXRTZXNzaW9uKCk6IFNlc3Npb24ge1xuICAgIHRoaXMuc2Vzc2lvbiA9IG5ldyBTZXNzaW9uKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnNlc3Npb247XG4gIH1cblxuXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcblxuICAvKipcbiAgICogUmV0dXJucyBhIG5ldyBwdWJsaXNoZXJcbiAgICpcbiAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzRGlhbG9nT3BlbmVkYCBldmVudCwgb25seSBpZiB0aGUgcG9wLXVwIHNob3duIGJ5IHRoZSBicm93c2VyIHRvIHJlcXVlc3QgcGVybWlzc2lvbnMgZm9yIHRoZSBjYW1lcmEgaXMgb3BlbmVkLiBZb3UgY2FuIHVzZSB0aGlzIGV2ZW50IHRvIGFsZXJ0IHRoZSB1c2VyIGFib3V0IGdyYW50aW5nIHBlcm1pc3Npb25zXG4gICAqIGZvciB5b3VyIHdlYnNpdGUuIEFuIGBhY2Nlc3NEaWFsb2dDbG9zZWRgIGV2ZW50IHdpbGwgYWxzbyBiZSBkaXNwYXRjaGVkIGFmdGVyIHVzZXIgY2xpY2tzIG9uIFwiQWxsb3dcIiBvciBcIkJsb2NrXCIgaW4gdGhlIHBvcC11cC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGBhY2Nlc3NEZW5pZWRgIGV2ZW50IG9uY2UgaXQgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSBhIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2AgZXZlbnQgb25jZSB0aGUgbG9jYWwgc3RyZWFtcyBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgIEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSkuIElmICpudWxsKiBvciAqdW5kZWZpbmVkKiBubyBkZWZhdWx0IHZpZGVvIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBQdWJsaXNoZXIuXG4gICAqIFlvdSBjYW4gYWx3YXlzIGNhbGwgbWV0aG9kIFtbUHVibGlzaGVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24pXG4gICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBpbml0UHVibGlzaGVyYCBzdWNjZWVkcywgYW5kIGlzIGRlZmluZWQgaWYgaXQgZmFpbHMuXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICBgY29tcGxldGlvbkhhbmRsZXJgIGZ1bmN0aW9uIGlzIGNhbGxlZCBiZWZvcmUgdGhlIFB1Ymxpc2hlciBkaXNwYXRjaGVzIGFuIGBhY2Nlc3NBbGxvd2VkYCBvciBhbiBgYWNjZXNzRGVuaWVkYCBldmVudFxuICAgKi9cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcGFyYW0yPywgcGFyYW0zPyk6IFB1Ymxpc2hlciB7XG5cbiAgICBsZXQgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcztcblxuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiAhPT0gJ2Z1bmN0aW9uJykpIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzKScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0gKDxQdWJsaXNoZXJQcm9wZXJ0aWVzPnBhcmFtMik7XG5cbiAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGF1ZGlvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgOiB1bmRlZmluZWQsXG4gICAgICAgIGZyYW1lUmF0ZTogdGhpcy5pc01lZGlhU3RyZWFtVHJhY2socHJvcGVydGllcy52aWRlb1NvdXJjZSkgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5mcmFtZVJhdGUgOiB1bmRlZmluZWQpLFxuICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSAhPT0gJ3VuZGVmaW5lZCcpID8gKCh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlID09PSAnc3RyaW5nJykgPyBWaWRlb0luc2VydE1vZGVbcHJvcGVydGllcy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6ICh0eXBlb2YgcHJvcGVydGllcy5taXJyb3IgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMubWlycm9yIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaEF1ZGlvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaEF1ZGlvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMucmVzb2x1dGlvbiAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5yZXNvbHV0aW9uIDogJzY0MHg0ODAnKSxcbiAgICAgICAgdmlkZW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy52aWRlb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy52aWRlb1NvdXJjZSA6IHVuZGVmaW5lZFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogdHJ1ZSxcbiAgICAgICAgcHVibGlzaEF1ZGlvOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246ICc2NDB4NDgwJ1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBwdWJsaXNoZXI6IFB1Ymxpc2hlciA9IG5ldyBQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgdGhpcyk7XG5cbiAgICBsZXQgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTI7XG4gICAgfSBlbHNlIGlmICghIXBhcmFtMykge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTM7XG4gICAgfVxuXG4gICAgcHVibGlzaGVyLmluaXRpYWxpemUoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzQWxsb3dlZCcsIFtdKTtcbiAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnLCBbXSk7XG4gICAgICB9KTtcblxuICAgIHJldHVybiBwdWJsaXNoZXI7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBQcm9taXNpZmllZCB2ZXJzaW9uIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqXG4gICAqID4gV0FSTklORzogZXZlbnRzIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGFuZCBgYWNjZXNzRGlhbG9nQ2xvc2VkYCB3aWxsIG5vdCBiZSBkaXNwYXRjaGVkIGlmIHVzaW5nIHRoaXMgbWV0aG9kIGluc3RlYWQgb2YgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICovXG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFByb21pc2U8UHVibGlzaGVyPjtcbiAgaW5pdFB1Ymxpc2hlckFzeW5jKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+O1xuXG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQcm9taXNlPFB1Ymxpc2hlcj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxQdWJsaXNoZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgbGV0IHB1Ymxpc2hlcjogUHVibGlzaGVyO1xuXG4gICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUocHVibGlzaGVyKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICBwdWJsaXNoZXIgPSB0aGlzLmluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgbG9jYWwgcmVjb3JkZXIgZm9yIHJlY29yZGluZyBzdHJlYW1zIHN0cmFpZ2h0IGF3YXkgZnJvbSB0aGUgYnJvd3NlclxuICAgKiBAcGFyYW0gc3RyZWFtICBTdHJlYW0gdG8gcmVjb3JkXG4gICAqL1xuICBpbml0TG9jYWxSZWNvcmRlcihzdHJlYW06IFN0cmVhbSk6IExvY2FsUmVjb3JkZXIge1xuICAgIHJldHVybiBuZXcgTG9jYWxSZWNvcmRlcihzdHJlYW0pO1xuICB9XG5cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1XG4gICAqIEByZXR1cm5zIDEgaWYgdGhlIGJyb3dzZXIgc3VwcG9ydHMgT3BlblZpZHUsIDAgb3RoZXJ3aXNlXG4gICAqL1xuICBjaGVja1N5c3RlbVJlcXVpcmVtZW50cygpOiBudW1iZXIge1xuICAgIGNvbnN0IGJyb3dzZXIgPSBwbGF0Zm9ybS5uYW1lO1xuICAgIGNvbnN0IHZlcnNpb24gPSBwbGF0Zm9ybS52ZXJzaW9uO1xuXG4gICAgaWYgKChicm93c2VyICE9PSAnQ2hyb21lJykgJiYgKGJyb3dzZXIgIT09ICdDaHJvbWUgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnRmlyZWZveCcpICYmIChicm93c2VyICE9PSAnRmlyZWZveCBNb2JpbGUnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggZm9yIGlPUycpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ09wZXJhJykgJiYgKGJyb3dzZXIgIT09ICdPcGVyYSBNb2JpbGUnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdTYWZhcmknKSkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIENvbGxlY3RzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtZWRpYSBpbnB1dCBkZXZpY2VzIGF2YWlsYWJsZSBvbiB0aGUgc3lzdGVtLiBZb3UgY2FuIHBhc3MgcHJvcGVydHkgYGRldmljZUlkYCBvZiBhIFtbRGV2aWNlXV0gb2JqZWN0IGFzIHZhbHVlIG9mIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgKi9cbiAgZ2V0RGV2aWNlcygpOiBQcm9taXNlPERldmljZVtdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPERldmljZVtdPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKS50aGVuKChkZXZpY2VJbmZvcykgPT4ge1xuICAgICAgICBjb25zdCBkZXZpY2VzOiBEZXZpY2VbXSA9IFtdO1xuICAgICAgICBkZXZpY2VJbmZvcy5mb3JFYWNoKGRldmljZUluZm8gPT4ge1xuICAgICAgICAgIGlmIChkZXZpY2VJbmZvLmtpbmQgPT09ICdhdWRpb2lucHV0JyB8fCBkZXZpY2VJbmZvLmtpbmQgPT09ICd2aWRlb2lucHV0Jykge1xuICAgICAgICAgICAgZGV2aWNlcy5wdXNoKHtcbiAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICBkZXZpY2VJZDogZGV2aWNlSW5mby5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgbGFiZWw6IGRldmljZUluZm8ubGFiZWxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc29sdmUoZGV2aWNlcyk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZ2V0dGluZyBkZXZpY2VzJywgZXJyb3IpO1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBHZXQgYSBNZWRpYVN0cmVhbSBvYmplY3QgdGhhdCB5b3UgY2FuIGN1c3RvbWl6ZSBiZWZvcmUgY2FsbGluZyBbW2luaXRQdWJsaXNoZXJdXSAocGFzcyBfTWVkaWFTdHJlYW1UcmFja18gcHJvcGVydHkgb2YgdGhlIF9NZWRpYVN0cmVhbV8gdmFsdWUgcmVzb2x2ZWQgYnkgdGhlIFByb21pc2UgYXMgYGF1ZGlvU291cmNlYCBvciBgdmlkZW9Tb3VyY2VgIHByb3BlcnRpZXMgaW4gW1tpbml0UHVibGlzaGVyXV0pXG4gICAqXG4gICAqIFBhcmFtZXRlciBgb3B0aW9uc2AgaXMgdGhlIHNhbWUgYXMgaW4gW1tpbml0UHVibGlzaGVyXV0gc2Vjb25kIHBhcmFtZXRlciAob2YgdHlwZSBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSksIGJ1dCBvbmx5IHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyB3aWxsIGJlIGFwcGxpZWQ6IGBhdWRpb1NvdXJjZWAsIGB2aWRlb1NvdXJjZWAsIGBmcmFtZVJhdGVgLCBgcmVzb2x1dGlvbmBcbiAgICpcbiAgICogVG8gY3VzdG9taXplIHRoZSBQdWJsaXNoZXIncyB2aWRlbywgdGhlIEFQSSBmb3IgSFRNTENhbnZhc0VsZW1lbnQgaXMgdmVyeSB1c2VmdWwuIEZvciBleGFtcGxlLCB0byBnZXQgYSBibGFjay1hbmQtd2hpdGUgdmlkZW8gYXQgMTAgZnBzIGFuZCBIRCByZXNvbHV0aW9uIHdpdGggbm8gc291bmQ6XG4gICAqIGBgYFxuICAgKiB2YXIgT1YgPSBuZXcgT3BlblZpZHUoKTtcbiAgICogdmFyIEZSQU1FX1JBVEUgPSAxMDtcbiAgICpcbiAgICogT1YuZ2V0VXNlck1lZGlhKHtcbiAgICogICAgYXVkaW9Tb3VyY2U6IGZhbHNlO1xuICAgKiAgICB2aWRlb1NvdXJjZTogdW5kZWZpbmVkLFxuICAgKiAgICByZXNvbHV0aW9uOiAnMTI4MHg3MjAnLFxuICAgKiAgICBmcmFtZVJhdGU6IEZSQU1FX1JBVEVcbiAgICogfSlcbiAgICogLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgKlxuICAgKiAgICB2YXIgdmlkZW9UcmFjayA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAqICAgIHZpZGVvLnNyY09iamVjdCA9IG5ldyBNZWRpYVN0cmVhbShbdmlkZW9UcmFja10pO1xuICAgKlxuICAgKiAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAqICAgIHZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICogICAgY3R4LmZpbHRlciA9ICdncmF5c2NhbGUoMTAwJSknO1xuICAgKlxuICAgKiAgICB2aWRlby5hZGRFdmVudExpc3RlbmVyKCdwbGF5JywgKCkgPT4ge1xuICAgKiAgICAgIHZhciBsb29wID0gKCkgPT4ge1xuICAgKiAgICAgICAgaWYgKCF2aWRlby5wYXVzZWQgJiYgIXZpZGVvLmVuZGVkKSB7XG4gICAqICAgICAgICAgIGN0eC5kcmF3SW1hZ2UodmlkZW8sIDAsIDAsIDMwMCwgMTcwKTtcbiAgICogICAgICAgICAgc2V0VGltZW91dChsb29wLCAxMDAwLyBGUkFNRV9SQVRFKTsgLy8gRHJhd2luZyBhdCAxMCBmcHNcbiAgICogICAgICAgIH1cbiAgICogICAgICB9O1xuICAgKiAgICAgIGxvb3AoKTtcbiAgICogICAgfSk7XG4gICAqICAgIHZpZGVvLnBsYXkoKTtcbiAgICpcbiAgICogICAgdmFyIGdyYXlWaWRlb1RyYWNrID0gY2FudmFzLmNhcHR1cmVTdHJlYW0oRlJBTUVfUkFURSkuZ2V0VmlkZW9UcmFja3MoKVswXTtcbiAgICogICAgdmFyIHB1Ymxpc2hlciA9IHRoaXMuT1YuaW5pdFB1Ymxpc2hlcihcbiAgICogICAgICBteUh0bWxUYXJnZXQsXG4gICAqICAgICAge1xuICAgKiAgICAgICAgYXVkaW9Tb3VyY2U6IGZhbHNlLFxuICAgKiAgICAgICAgdmlkZW9Tb3VyY2U6IGdyYXlWaWRlb1RyYWNrXG4gICAqICAgICAgfSk7XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGdldFVzZXJNZWRpYShvcHRpb25zOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxNZWRpYVN0cmVhbT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5nZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMob3B0aW9ucylcbiAgICAgICAgLnRoZW4oY29uc3RyYWludHMgPT4ge1xuICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKVxuICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICBsZXQgZXJyb3JOYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKCEob3B0aW9ucy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbicpKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoZXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG5cbiAgLyogdHNsaW50OmRpc2FibGU6bm8tZW1wdHkgKi9cbiAgLyoqXG4gICAqIERpc2FibGUgYWxsIGxvZ2dpbmcgZXhjZXB0IGVycm9yIGxldmVsXG4gICAqL1xuICBlbmFibGVQcm9kTW9kZSgpOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmRlYnVnID0gKCkgPT4geyB9O1xuICAgIGNvbnNvbGUuaW5mbyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLndhcm4gPSAoKSA9PiB7IH07XG4gIH1cbiAgLyogdHNsaW50OmVuYWJsZTpuby1lbXB0eSAqL1xuXG5cbiAgLyoqXG4gICAqIFNldCBPcGVuVmlkdSBhZHZhbmNlZCBjb25maWd1cmF0aW9uIG9wdGlvbnMuIEN1cnJlbnRseSBgY29uZmlndXJhdGlvbmAgaXMgYW4gb2JqZWN0IHdpdGggdGhlIGZvbGxvd2luZyBvcHRpb25hbCBwcm9wZXJ0aWVzIChzZWUgW1tPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbl1dIGZvciBtb3JlIGRldGFpbHMpOlxuICAgKiAtIGBpY2VTZXJ2ZXJzYDogc2V0IGN1c3RvbSBTVFVOL1RVUk4gc2VydmVycyB0byBiZSB1c2VkIGJ5IE9wZW5WaWR1IEJyb3dzZXJcbiAgICogLSBgc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb25gOiB1cmwgdG8gYSBjdXN0b20gc2NyZWVuIHNoYXJlIGV4dGVuc2lvbiBmb3IgQ2hyb21lIHRvIGJlIHVzZWQgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBvbmUsIGJhc2VkIG9uIG91cnMgW2h0dHBzOi8vZ2l0aHViLmNvbS9PcGVuVmlkdS9vcGVudmlkdS1zY3JlZW4tc2hhcmluZy1jaHJvbWUtZXh0ZW5zaW9uXShodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbilcbiAgICogLSBgcHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zYDogY3VzdG9tIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBbW1B1Ymxpc2hlclNwZWFraW5nRXZlbnRdXSBmZWF0dXJlXG4gICAqL1xuICBzZXRBZHZhbmNlZENvbmZpZ3VyYXRpb24oY29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24pOiB2b2lkIHtcbiAgICB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb247XG4gIH1cblxuXG4gIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyhwdWJsaXNoZXJQcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPE1lZGlhU3RyZWFtQ29uc3RyYWludHM+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGxldCBhdWRpbywgdmlkZW87XG5cbiAgICAgIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBudWxsIHx8IHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgPT09IGZhbHNlKSB7XG4gICAgICAgIGF1ZGlvID0gZmFsc2U7XG4gICAgICB9IGVsc2UgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBhdWRpbyA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhdWRpbyA9IHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBudWxsIHx8IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09IGZhbHNlKSB7XG4gICAgICAgIHZpZGVvID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2aWRlbyA9IHtcbiAgICAgICAgICBoZWlnaHQ6IHtcbiAgICAgICAgICAgIGlkZWFsOiA0ODBcbiAgICAgICAgICB9LFxuICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICBpZGVhbDogNjQwXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtZWRpYUNvbnN0cmFpbnRzOiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbyxcbiAgICAgICAgdmlkZW9cbiAgICAgIH07XG5cbiAgICAgIGlmICh0eXBlb2YgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA9IHsgZGV2aWNlSWQ6IHsgZXhhY3Q6IG1lZGlhQ29uc3RyYWludHMuYXVkaW8gfSB9O1xuICAgICAgfVxuXG4gICAgICBpZiAobWVkaWFDb25zdHJhaW50cy52aWRlbykge1xuXG4gICAgICAgIGlmICghIXB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbikge1xuICAgICAgICAgIGNvbnN0IHdpZHRoQW5kSGVpZ2h0ID0gcHVibGlzaGVyUHJvcGVydGllcy5yZXNvbHV0aW9uLnRvTG93ZXJDYXNlKCkuc3BsaXQoJ3gnKTtcbiAgICAgICAgICBjb25zdCB3aWR0aCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFswXSk7XG4gICAgICAgICAgY29uc3QgaGVpZ2h0ID0gTnVtYmVyKHdpZHRoQW5kSGVpZ2h0WzFdKTtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLndpZHRoLmlkZWFsID0gd2lkdGg7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS5oZWlnaHQuaWRlYWwgPSBoZWlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZSkge1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuZnJhbWVSYXRlID0geyBpZGVhbDogcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghIXB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgJiYgdHlwZW9mIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzdHJpbmcnKSB7XG5cbiAgICAgICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbicpIHtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUgIT09ICdDaHJvbWUnICYmIHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVELCAnWW91IGNhbiBvbmx5IHNjcmVlbiBzaGFyZSBpbiBkZXNrdG9wIENocm9tZSBhbmQgRmlyZWZveC4gRGV0ZWN0ZWQgYnJvd3NlcjogJyArIHBsYXRmb3JtLm5hbWUpO1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gJiYgIShwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSkge1xuXG4gICAgICAgICAgICAgICAgLy8gQ3VzdG9tIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lXG5cbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldFNjcmVlbkNvbnN0cmFpbnRzKChlcnJvciwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yIHx8ICEhc2NyZWVuQ29uc3RyYWludHMubWFuZGF0b3J5ICYmIHNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZSA9PT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnIHx8IGVycm9yID09PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25JZCA9IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIS5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbklkLCAoc3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICg8c3RyaW5nPnRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWZhdWx0IHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lXG5cbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nQXV0by5nZXRTY3JlZW5JZCgoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25VcmwgPSAhIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uID8gdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gOlxuICAgICAgICAgICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2hyb21lLmdvb2dsZS5jb20vd2Vic3RvcmUvZGV0YWlsL29wZW52aWR1LXNjcmVlbnNoYXJpbmcvbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCBleHRlbnNpb25VcmwpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdpbnN0YWxsZWQtZGlzYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9ICdzY3JlZW4nO1xuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zdHJpbmctbGl0ZXJhbFxuICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlb1snZGV2aWNlSWQnXSA9IHsgZXhhY3Q6IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgfTtcbiAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc3RhcnRXcyhvbkNvbm5lY3RTdWNjZXM6IChlcnJvcjogRXJyb3IpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSB7XG4gICAgICBoZWFydGJlYXQ6IDUwMDAsXG4gICAgICBzZW5kQ2xvc2VNZXNzYWdlOiBmYWxzZSxcbiAgICAgIHdzOiB7XG4gICAgICAgIHVyaTogdGhpcy53c1VyaSxcbiAgICAgICAgdXNlU29ja0pTOiBmYWxzZSxcbiAgICAgICAgb25jb25uZWN0ZWQ6IG9uQ29ubmVjdFN1Y2NlcyxcbiAgICAgICAgb25kaXNjb25uZWN0OiB0aGlzLmRpc2Nvbm5lY3RDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBvbnJlY29ubmVjdGluZzogdGhpcy5yZWNvbm5lY3RpbmdDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBvbnJlY29ubmVjdGVkOiB0aGlzLnJlY29ubmVjdGVkQ2FsbGJhY2suYmluZCh0aGlzKVxuICAgICAgfSxcbiAgICAgIHJwYzoge1xuICAgICAgICByZXF1ZXN0VGltZW91dDogMTAwMDAsXG4gICAgICAgIHBhcnRpY2lwYW50Sm9pbmVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEpvaW5lZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50UHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50VW5wdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50VW5wdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudExlZnQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50TGVmdC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50RXZpY3RlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRFdmljdGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RhcnRlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RhcnRlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0b3BwZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0b3BwZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzZW5kTWVzc2FnZTogdGhpcy5zZXNzaW9uLm9uTmV3TWVzc2FnZS5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5cbi8qKlxuICogUGFja3MgbG9jYWwgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGNhbiBwdWJsaXNoIGl0IHRvIGEgc2Vzc2lvbi4gSW5pdGlhbGl6ZWQgd2l0aCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAqL1xuZXhwb3J0IGNsYXNzIFB1Ymxpc2hlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgUHVibGlzaGVyIGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3RcbiAgICAgKi9cbiAgICBhY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHlvdSBoYXZlIGNhbGxlZCBbW1B1Ymxpc2hlci5zdWJzY3JpYmVUb1JlbW90ZV1dIHdpdGggdmFsdWUgYHRydWVgIG9yIGBmYWxzZWAgKCpmYWxzZSogYnkgZGVmYXVsdClcbiAgICAgKi9cbiAgICBpc1N1YnNjcmliZWRUb1JlbW90ZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIHRvIHdoaWNoIHRoZSBQdWJsaXNoZXIgYmVsb25nc1xuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247IC8vIEluaXRpYWxpemVkIGJ5IFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpXG5cbiAgICBwcml2YXRlIGFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcztcbiAgICBwcml2YXRlIHBlcm1pc3Npb25EaWFsb2dUaW1lb3V0OiBOb2RlSlMuVGltZXI7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgcHJpdmF0ZSBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uZWUub24oJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQtYnktZGlzY29ubmVjdCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgYXVkaW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIGF1ZGlvIHN0cmVhbScpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gcHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVucHVibGlzaCBpdFxuICAgICAqL1xuICAgIHB1Ymxpc2hWaWRlbyh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIENhbGwgdGhpcyBtZXRob2QgYmVmb3JlIFtbU2Vzc2lvbi5wdWJsaXNoXV0gdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBQdWJsaXNoZXIge1xuICAgICAgICBzdXBlci5vbmNlKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbUNyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHRoaXMuc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUub25jZSgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgZXJyb3JDYWxsYmFjayA9IChvcGVuVmlkdUVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJlamVjdChvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmlzTWVkaWFTdHJlYW1UcmFjayh0aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjaygoPE1lZGlhU3RyZWFtVHJhY2s+dGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQXBwbHkgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW8gYW5kIFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvXG4gICAgICAgICAgICAgICAgaWYgKCEhbWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdLmVuYWJsZWQgPSAhIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCEhbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSAhIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBzdWJzY3JpYmVkIHRvIG91ciByZW1vdGUgd2UgZG9uJ3Qgc3RpbGwgc2V0IHRoZSBNZWRpYVN0cmVhbSBvYmplY3QgaW4gdGhlIHZpZGVvIGVsZW1lbnRzIHRvXG4gICAgICAgICAgICAgICAgICAgIC8vIGF2b2lkIGVhcmx5ICdzdHJlYW1QbGF5aW5nJyBldmVudFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS51cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcblxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuZmlyc3RWaWRlb0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVWaWRlb0VsZW1lbnQodGhpcy5maXJzdFZpZGVvRWxlbWVudC50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnRoaXMucHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyh0aGlzLnByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgLnRoZW4oY29uc3RyYWludHMgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG91dGJvdW5kU3RyZWFtT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IGNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyUHJvcGVydGllczogdGhpcy5wcm9wZXJ0aWVzXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHNBdXg6IE1lZGlhU3RyZWFtQ29uc3RyYWludHMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGltZUZvckRpYWxvZ0V2ZW50ID0gMTI1MDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kVmlkZW8oKSB8fCB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZpbmVkQXVkaW9Db25zdHJhaW50ID0gKChjb25zdHJhaW50cy5hdWRpbyA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiBjb25zdHJhaW50cy5hdWRpbyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gZmFsc2UgOiBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBjb25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIodGltZUZvckRpYWxvZ0V2ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHNBdXgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgJiYgdGhpcy5zdHJlYW0uaXNTZW5kQXVkaW8oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiBnZXR0aW5nIGRlc2t0b3AgYXMgdXNlciBtZWRpYSBhdWRpbyBjb25zdHJhaW50IG11c3QgYmUgZmFsc2UuIE5vdyB3ZSBjYW4gYXNrIGZvciBpdCBpZiByZXF1aXJlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXguYXVkaW8gPSBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihhdWRpb09ubHlTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soYXVkaW9Pbmx5U3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWUsIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnb3ZlcmNvbnN0cmFpbmVkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlBVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWUsIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogY29uc3RyYWludHMudmlkZW9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEIDogT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ1wiICsgKDxDb25zdHJhaW5ET01TdHJpbmdQYXJhbWV0ZXJzPig8TWVkaWFUcmFja0NvbnN0cmFpbnRzPmNvbnN0cmFpbnRzLmF1ZGlvKS5kZXZpY2VJZCEhKS5leGFjdCArIFwiJyBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IHRoZSB2YWx1ZSBwYXNzZWQgZm9yIGNvbnN0cmFpbnQgJ1wiICsgZXJyb3IuY29uc3RyYWludCArIFwiJ1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiVmlkZW8gaW5wdXQgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ1wiICsgKDxDb25zdHJhaW5ET01TdHJpbmdQYXJhbWV0ZXJzPig8TWVkaWFUcmFja0NvbnN0cmFpbnRzPmNvbnN0cmFpbnRzLnZpZGVvKS5kZXZpY2VJZCEhKS5leGFjdCArIFwiJyBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IHRoZSB2YWx1ZSBwYXNzZWQgZm9yIGNvbnN0cmFpbnQgJ1wiICsgZXJyb3IuY29uc3RyYWludCArIFwiJ1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk5PX0lOUFVUX1NPVVJDRV9TRVQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJQcm9wZXJ0aWVzICdhdWRpb1NvdXJjZScgYW5kICd2aWRlb1NvdXJjZScgY2Fubm90IGJlIHNldCB0byBmYWxzZSBvciBudWxsIGF0IHRoZSBzYW1lIHRpbWUgd2hlbiBjYWxsaW5nICdPcGVuVmlkdS5pbml0UHVibGlzaGVyJ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVTZXNzaW9uKHNlc3Npb246IFNlc3Npb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbiA9IHNlc3Npb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWVzdGFibGlzaFN0cmVhbVBsYXlpbmdFdmVudCgpIHtcbiAgICAgICAgaWYgKHRoaXMuZWUuZ2V0TGlzdGVuZXJzKCdzdHJlYW1QbGF5aW5nJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5hZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIHNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih3YWl0VGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEaWFsb2dPcGVuZWQnLCBbXSk7XG4gICAgICAgIH0sIHdhaXRUaW1lKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZTogbnVtYmVyLCB3YWl0VGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0KTtcbiAgICAgICAgaWYgKChEYXRlLm5vdygpIC0gc3RhcnRUaW1lKSA+IHdhaXRUaW1lKSB7XG4gICAgICAgICAgICAvLyBQZXJtaXNzaW9uIGRpYWxvZyB3YXMgc2hvd24gYW5kIG5vdyBpcyBjbG9zZWRcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEaWFsb2dDbG9zZWQnLCBbXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4vUHVibGlzaGVyJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU3Vic2NyaWJlciB9IGZyb20gJy4vU3Vic2NyaWJlcic7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTaWduYWxPcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TaWduYWxPcHRpb25zJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0Nvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IE9iak1hcCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL09iak1hcCc7XG5pbXBvcnQgeyBTZXNzaW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL1Nlc3Npb25PcHRpb25zJztcbmltcG9ydCB7IENvbm5lY3Rpb25FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0Nvbm5lY3Rpb25FdmVudCc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5pbXBvcnQgeyBSZWNvcmRpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1JlY29yZGluZ0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudCc7XG5pbXBvcnQgeyBTaWduYWxFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50JztcbmltcG9ydCB7IFN0cmVhbUV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLy8gVGhpcyBtYXAgaXMgb25seSB1c2VkIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gJ2pvaW5Sb29tJyByZXNwb25zZSBhbmQgJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnIG5vdGlmaWNhdGlvblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVTdHJlYW1zQ3JlYXRlZDogT2JqTWFwPGJvb2xlYW4+ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE9iak1hcDxDb25uZWN0aW9uPiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcml6ZWQgZm9ybWF0XG4gICAgICogYXMgSlNPTiBvciBYTUwgaXMgYSBnb29kIGlkZWEpLCB0aGUgb25seSByZXN0cmljdGlvbiBpcyBhIG1heGltdW0gbGVuZ3RoIG9mIDEwMDAwIGNoYXJzLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRhZGF0YSBpcyBub3QgY29uc2lkZXJlZCBzZWN1cmUsIGFzIGl0IGlzIGdlbmVyYXRlZCBpbiB0aGUgY2xpZW50IHNpZGUuIFRvIHBhc3Mgc2VjdXJpemVkIGRhdGEsIGFkZCBpdCBhcyBhIHBhcmFtZXRlciBpbiB0aGVcbiAgICAgKiB0b2tlbiBnZW5lcmF0aW9uIG9wZXJhdGlvbiAodGhyb3VnaCB0aGUgQVBJIFJFU1QsIG9wZW52aWR1LWphdmEtY2xpZW50IG9yIG9wZW52aWR1LW5vZGUtY2xpZW50KS5cbiAgICAgKlxuICAgICAqIE9ubHkgYWZ0ZXIgdGhlIHJldHVybmVkIFByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gb2JqZWN0IHdpbGwgYmUgYXZhaWxhYmxlIGFuZCBwcm9wZXJseSBkZWZpbmVkLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBmaXJzdCBkaXNwYXRjaCBvbmUgb3IgbW9yZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cyB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2Q6XG4gICAgICogLSBGaXJzdCBvbmUgZm9yIHlvdXIgb3duIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0LCBzbyB5b3UgY2FuIHJldHJpZXZlIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gcHJvcGVydHkuXG4gICAgICogLSBUaGVuIG9uZSBmb3IgZWFjaCByZW1vdGUgQ29ubmVjdGlvbiBwcmV2aW91c2x5IGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiwgaWYgYW55LiBBbnkgb3RoZXIgcmVtb3RlIHVzZXIgY29ubmVjdGluZyB0byB0aGUgU2Vzc2lvbiBhZnRlciB5b3UgaGF2ZVxuICAgICAqIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCB3aGVuIHRoZXkgZG8gc28uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgZm9yIGVhY2ggcmVtb3RlIGFjdGl2ZSBbW1B1Ymxpc2hlcl1dIHRoYXQgd2FzIGFscmVhZHkgc3RyZWFtaW5nXG4gICAgICogd2hlbiBjb25uZWN0aW5nLCBqdXN0IGFmdGVyIGRpc3BhdGNoaW5nIGFsbCByZW1vdGUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0byB3aGljaCB5b3UgbXVzdCBzdWJzY3JpYmUgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqXG4gICAgICovXG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YT86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1Rva2VuKHRva2VuKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIEVhcmx5IGNvbmZpZ3VyYXRpb24gdG8gZGVhY3RpdmF0ZSBhdXRvbWF0aWMgc3Vic2NyaXB0aW9uIHRvIHN0cmVhbXNcbiAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRva2VuLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISFtZXRhZGF0YSA/IHRoaXMuc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGEpIDogJydcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdEF1eCh0b2tlbikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBwbGF0Zm9ybS5uYW1lICsgJyAnICsgcGxhdGZvcm0udmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGVhdmVzIHRoZSBzZXNzaW9uLCBkZXN0cm95aW5nIGFsbCBzdHJlYW1zIGFuZCBkZWxldGluZyB0aGUgdXNlciBhcyBhIHBhcnRpY2lwYW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBlYWNoIFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgdG8gYXZvaWQgdGhpcyBiZWhhdmlvdXIgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24gKHRvIGRvIHNvIGl0IGlzIGEgbWFuZGF0b3J5IHJlcXVpcmVtZW50IHRvIGNhbGwgYFNlc3Npb24udW5wdWJsaXNoKClgXG4gICAgICogb3IvYW5kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaW4gdGhlIHByZXZpb3VzIHNlc3Npb24pLiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZGlzY29ubmVjdGVkIHBhcnRpY2lwYW50IHdhcyBwdWJsaXNoaW5nLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvdXIgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgaW4gYW55IGNhc2UuIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sZWF2ZShmYWxzZSwgJ2Rpc2Nvbm5lY3QnKTtcbiAgICB9XG5cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgYHN0cmVhbWAsIGFkZGluZyBhIG5ldyBIVE1MIHZpZGVvIGVsZW1lbnQgdG8gRE9NIHdpdGggYHN1YnNjcmliZXJQcm9wZXJ0aWVzYCBzZXR0aW5ncy4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWQgaW4gdGhlIGNhbGxiYWNrIG9mIGBzdHJlYW1DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliaW5nIHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZCA9IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAndW5zdWJzY3JpYmVGcm9tVmlkZW8nLFxuICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHVuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcykgYW5kXG4gICAgICogZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsJywgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0uY29ubmVjdGlvbiAhPT0gdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5wdWJsaXNoaW5nIGxvY2FsIG1lZGlhICgnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyknKTtcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyBvbmUgc2lnbmFsLiBgc2lnbmFsYCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiBgYGBqc29uXG4gICAgICoge2RhdGE6c3RyaW5nLCB0bzpDb25uZWN0aW9uW10sIHR5cGU6c3RyaW5nfVxuICAgICAqIGBgYFxuICAgICAqIEFsbCB1c2VycyBzdWJzY3JpYmVkIHRvIHRoYXQgc2lnbmFsIChgc2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCAuLi4pYCBvciBgc2Vzc2lvbi5vbignc2lnbmFsJywgLi4uKWAgZm9yIGFsbCBzaWduYWxzKSBhbmQgd2hvc2UgQ29ubmVjdGlvbiBvYmplY3RzIGFyZSBpbiBgdG9gIGFycmF5IHdpbGwgcmVjZWl2ZSBpdC4gVGhlaXIgbG9jYWxcbiAgICAgKiBTZXNzaW9uIG9iamVjdHMgd2lsbCBkaXNwYXRjaCBhIGBzaWduYWxgIG9yIGBzaWduYWw6dHlwZWAgZXZlbnQuIFNlZSBbW1NpZ25hbEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgbWVzc2FnZSBzdWNjZXNzZnVsbHkgcmVhY2hlZCBvcGVudmlkdS1zZXJ2ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdC4gX1RoaXMgZG9lc24ndFxuICAgICAqIG1lYW4gdGhhdCBvcGVudmlkdS1zZXJ2ZXIgY291bGQgcmVzZW5kIHRoZSBtZXNzYWdlIHRvIGFsbCB0aGUgbGlzdGVkIHJlY2VpdmVycy5fXG4gICAgICovXG4gICAgLyogdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cbiAgICBzaWduYWwoc2lnbmFsOiBTaWduYWxPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsTWVzc2FnZSA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWRzLnB1c2goY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogSlNPTi5zdHJpbmdpZnkoc2lnbmFsTWVzc2FnZSlcbiAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qIHRzbGludDplbmFibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayAnc3BlYWtpbmcnIGV2ZW50IGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGRpc2FibGFlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhIXN0ci5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24ocmVzcG9uc2UuaWQsICcnKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Nvbm5lY3Rpb24gJyArIHJlc3BvbnNlLmlkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tyZXNwb25zZS5pZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5uYW1lLCAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIG1zZy5uYW1lICsgXCIgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50TGVmdCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBzdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGFmdGVyQ29ubmVjdGlvbkZvdW5kID0gKGNvbm5lY3Rpb24pID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSkge1xuICAgICAgICAgICAgICAgIC8vIEF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gc3RyZWFtLnN1YnNjcmliZSgpIGluIFwib25QYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGFuZCBpbiBcImpvaW5Sb29tXCIgcnBjIGNhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBjb25kaXRpb24gaXMgZmFsc2UgaWYgb3BlbnZpZHUtc2VydmVyIHNlbmRzIFwicGFydGljaXBhbnRQdWJsaXNoZWRcIiBldmVudCB0byBhIHN1YnNjcmliZXIgcGFydGljaXBhbnQgdGhhdCBoYXNcbiAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IHN1YnNjcmliZWQgdG8gY2VydGFpbiBzdHJlYW0gaW4gdGhlIGNhbGxiYWNrIG9mIFwiam9pblJvb21cIiBtZXRob2RcblxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBHZXQgdGhlIGV4aXN0aW5nIENvbm5lY3Rpb24gY3JlYXRlZCBvbiAnb25QYXJ0aWNpcGFudEpvaW5lZCcgZm9yXG4gICAgICAgIC8vIGV4aXN0aW5nIHBhcnRpY2lwYW50cyBvciBjcmVhdGUgYSBuZXcgb25lIGZvciBuZXcgcGFydGljaXBhbnRzXG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24ocmVzcG9uc2UuaWQsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgcmVzcG9uc2UuaWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50UHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29uID0+IHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgZXhpc3RpbmcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBjb247XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UubWV0YWRhdGEgPSBjb24uZGF0YTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLm9wdGlvbnMgPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlLnN0cmVhbXMpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgbmV3IENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5uYW1lLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIG1zZy5uYW1lICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgY29ubmVjdGlvbi5zdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuXG4gICAgICAgICAgICAgICAgLy8gRGVsZXRpbmcgdGhlIHJlbW90ZSBzdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZDogc3RyaW5nID0gY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ucmVtb3ZlU3RyZWFtKHN0cmVhbUlkKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50RXZpY3RlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgLyp0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLm5hbWUgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgJ2ZvcmNlRGlzY29ubmVjdCcpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5kaXNwb3NlKCk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgJ2ZvcmNlRGlzY29ubmVjdCcpXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTsqL1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk5ld01lc3NhZ2UobXNnKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgc2lnbmFsOiAnICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG5cbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKG1zZy5mcm9tLCBcIkNvbm5lY3Rpb24gJ1wiICsgbXNnLmZyb20gKyBcIicgdW5rbm93IHdoZW4gJ29uTmV3TWVzc2FnZScuIEV4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogXCJcbiAgICAgICAgICAgICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpICsgJy4gRXhpc3RpbmcgbG9jYWwgY29ubmVjdGlvbjogJyArIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWwnLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsOicgKyBtc2cudHlwZSwgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVjdkljZUNhbmRpZGF0ZShtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY2FuZGlkYXRlID0ge1xuICAgICAgICAgICAgY2FuZGlkYXRlOiBtc2cuY2FuZGlkYXRlLFxuICAgICAgICAgICAgc2RwTWlkOiBtc2cuc2RwTWlkLFxuICAgICAgICAgICAgc2RwTUxpbmVJbmRleDogbXNnLnNkcE1MaW5lSW5kZXgsXG4gICAgICAgICAgICB0b0pTT046ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKG1zZy5lbmRwb2ludE5hbWUsICdDb25uZWN0aW9uIG5vdCBmb3VuZCBmb3IgZW5kcG9pbnQgJyArIG1zZy5lbmRwb2ludE5hbWUgKyAnLiBJY2UgY2FuZGlkYXRlIHdpbGwgYmUgaWdub3JlZDogJyArIGNhbmRpZGF0ZSlcbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgIHN0cmVhbS5nZXRXZWJSdGNQZWVyKCkuYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBhZGRpbmcgY2FuZGlkYXRlIGZvciAnICsgc3RyZWFtLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblNlc3Npb25DbG9zZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnU2Vzc2lvbiBjbG9zZWQ6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcbiAgICAgICAgY29uc3QgcyA9IG1zZy5yb29tO1xuICAgICAgICBpZiAocyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbi1jbG9zZWQnLCBbe1xuICAgICAgICAgICAgICAgIHNlc3Npb246IHNcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWQnLCBtc2cpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTG9zdENvbm5lY3Rpb24oKTogdm9pZCB7XG5cbiAgICAgICAgLyppZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0qL1xuXG4gICAgICAgIGNvbnNvbGUud2FybignTG9zdCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgdGhpcy5sZWF2ZSh0cnVlLCAnbmV0d29ya0Rpc2Nvbm5lY3QnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk1lZGlhRXJyb3IocGFyYW1zKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWEgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgY29uc3QgZXJyID0gcGFyYW1zLmVycm9yO1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnZXJyb3ItbWVkaWEnLCBbe1xuICAgICAgICAgICAgICAgIGVycm9yOiBlcnJcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignUmVjZWl2ZWQgdW5kZWZpbmVkIG1lZGlhIGVycm9yLiBQYXJhbXM6JywgcGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0YXJ0ZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0YXJ0ZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdGFydGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3JkaW5nU3RvcHBlZChyZXNwb25zZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVjb3JkaW5nU3RvcHBlZCcsIFtuZXcgUmVjb3JkaW5nRXZlbnQodGhpcywgJ3JlY29yZGluZ1N0b3BwZWQnLCByZXNwb25zZS5pZCwgcmVzcG9uc2UubmFtZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxlYXZlKGZvcmNlZDogYm9vbGVhbiwgcmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBmb3JjZWQgPSAhIWZvcmNlZDtcbiAgICAgICAgY29uc29sZS5pbmZvKCdMZWF2aW5nIFNlc3Npb24gKGZvcmNlZD0nICsgZm9yY2VkICsgJyknKTtcblxuICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkICYmICFmb3JjZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdsZWF2ZVJvb20nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVlLmVtaXRFdmVudCgnbG9jYWwtc3RyZWFtLWRlc3Ryb3llZC1ieS1kaXNjb25uZWN0JywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBNYWtlIFNlc3Npb24gb2JqZWN0IGRpc3BhdGNoICdzZXNzaW9uRGlzY29ubmVjdGVkJyBldmVudCAoaWYgaXQgaXMgbm90IGFscmVhZHkgZGlzcG9zZWQpXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudCA9IG5ldyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQodGhpcywgcmVhc29uKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcsIFtzZXNzaW9uRGlzY29ubmVjdEV2ZW50XSk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3Ugd2VyZSBub3QgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0QXV4KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zdGFydFdzKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBqb2luUGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46ICghIXRva2VuKSA/IHRva2VuIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdqb2luUm9vbScsIGpvaW5QYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGF0YSA9IHJlc3BvbnNlLm1ldGFkYXRhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSByZW1vdGUgQ29ubmVjdGlvbnMgd2l0aCB2YWx1ZSByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25zOiBuZXcgQXJyYXk8Q29ubmVjdGlvbj4oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJ0aWNpcGFudHM6IENvbm5lY3Rpb25PcHRpb25zW10gPSByZXNwb25zZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50cy5mb3JFYWNoKHBhcnRpY2lwYW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMucHVzaChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLnB1c2goY29ubmVjdGlvbi5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCB0aGlzLmNvbm5lY3Rpb24sICcnKV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggZXhpc3RpbmcgY29ubmVjdGlvbiBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ3N0cmVhbUNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGFjdGl2ZSBzdHJlYW0gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5mb3JFYWNoKHN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBzdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW1vdGVDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIGNvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodG9rZW4pO1xuICAgICAgICB0aGlzLnNlc3Npb25JZCA9IDxzdHJpbmc+dXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Nlc3Npb25JZCcpO1xuICAgICAgICBjb25zdCBzZWNyZXQgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnc2VjcmV0Jyk7XG4gICAgICAgIGNvbnN0IHJlY29yZGVyID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3JlY29yZGVyJyk7XG4gICAgICAgIGNvbnN0IHR1cm5Vc2VybmFtZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0dXJuVXNlcm5hbWUnKTtcbiAgICAgICAgY29uc3QgdHVybkNyZWRlbnRpYWwgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVybkNyZWRlbnRpYWwnKTtcbiAgICAgICAgY29uc3Qgcm9sZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyb2xlJyk7XG5cbiAgICAgICAgaWYgKCEhc2VjcmV0KSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyZWNvcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdHVyblVzZXJuYW1lICYmICEhdHVybkNyZWRlbnRpYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0dW5VcmwgPSAnc3R1bjonICsgdXJsLmhvc3RuYW1lICsgJzozNDc4JztcbiAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMiA9IHR1cm5VcmwxICsgJz90cmFuc3BvcnQ9dGNwJztcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtcbiAgICAgICAgICAgICAgICB7IHVybHM6IFtzdHVuVXJsXSB9LFxuICAgICAgICAgICAgICAgIHsgdXJsczogW3R1cm5VcmwxLCB0dXJuVXJsMl0sIHVzZXJuYW1lOiB0dXJuVXNlcm5hbWUsIGNyZWRlbnRpYWw6IHR1cm5DcmVkZW50aWFsIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnVFVSTiB0ZW1wIGNyZWRlbnRpYWxzIFsnICsgdHVyblVzZXJuYW1lICsgJzonICsgdHVybkNyZWRlbnRpYWwgKyAnXScpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcm9sZSkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yb2xlID0gcm9sZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub3BlbnZpZHUud3NVcmkgPSAnd3NzOi8vJyArIHVybC5ob3N0ICsgJy9vcGVudmlkdSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBXZWJSdGNQZWVyLCBXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlclNlbmRyZWN2IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNQZWVyL1dlYlJ0Y1BlZXInO1xuaW1wb3J0IHsgV2ViUnRjU3RhdHMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1N0YXRzL1dlYlJ0Y1N0YXRzJztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5pbXBvcnQgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKTtcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIG1lZGlhIHN0cmVhbXMgYXZhaWxhYmxlIGluIE9wZW5WaWR1IFNlcnZlciBmb3IgY2VydGFpbiBzZXNzaW9uLlxuICogRWFjaCBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBoYXMgYW4gYXR0cmlidXRlIG9mIHR5cGUgU3RyZWFtLCBhcyB0aGV5IGdpdmUgYWNjZXNzXG4gKiB0byBvbmUgb2YgdGhlbSAoc2VuZGluZyBhbmQgcmVjZWl2aW5nIGl0LCByZXNwZWN0aXZlbHkpXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW0ge1xuXG4gICAgLyoqXG4gICAgICogVGhlIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgaXMgcHVibGlzaGluZyB0aGUgc3RyZWFtXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZyYW1lIHJhdGUgb2YgdGhlIHZpZGVvIGluIGZyYW1lcyBwZXIgc2Vjb25kLiBUaGlzIHByb3BlcnR5IGlzIG9ubHkgZGVmaW5lZCBpZiB0aGUgW1tQdWJsaXNoZXJdXSBvZlxuICAgICAqIHRoZSBzdHJlYW0gd2FzIGluaXRpYWxpemVkIHBhc3NpbmcgYSBfZnJhbWVSYXRlXyBwcm9wZXJ0eSBvbiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICAgKi9cbiAgICBmcmFtZVJhdGU/OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIGEgdmlkZW8gdHJhY2sgb3Igbm90XG4gICAgICovXG4gICAgaGFzVmlkZW86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIGFuIGF1ZGlvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc0F1ZGlvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIHN0cmVhbUlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBgXCJDQU1FUkFcImAgb3IgYFwiU0NSRUVOXCJgLiAqdW5kZWZpbmVkKiBpZiBzdHJlYW0gaXMgYXVkaW8tb25seVxuICAgICAqL1xuICAgIHR5cGVPZlZpZGVvPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtTWFuYWdlciBvYmplY3QgKFtbUHVibGlzaGVyXV0gb3IgW1tTdWJzY3JpYmVyXV0pIGluIGNoYXJnZSBvZiBkaXNwbGF5aW5nIHRoaXMgc3RyZWFtIGluIHRoZSBET01cbiAgICAgKi9cbiAgICBzdHJlYW1NYW5hZ2VyOiBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNQZWVyOiBXZWJSdGNQZWVyO1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5ib3VuZFN0cmVhbU9wdHM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3BlZWNoRXZlbnQ6IGFueTtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlc3Npb246IFNlc3Npb24sIG9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zIHwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIHwge30pIHtcblxuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCdpZCcpKSB7XG4gICAgICAgICAgICAvLyBJbmJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBTdWJzY3JpYmVyXG4gICAgICAgICAgICB0aGlzLmluYm91bmRTdHJlYW1PcHRzID0gPEluYm91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICdTQ1JFRU4nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAnQ0FNRVJBJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMudHlwZU9mVmlkZW87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pc1NlbmRBdWRpbygpO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaXNTZW5kVmlkZW8oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gbWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWwoKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGluYm91bmQgb3B0aW9ucyB1bmRlZmluZWQgYW5kIG91dGJvdW5kIG9wdGlvbnMgZGVmaW5lZFxuICAgICAgICByZXR1cm4gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzICYmICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5nZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlcG9ydCA9PiByZXNvbHZlKHJlcG9ydCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpOiBSVENJY2VDYW5kaWRhdGVbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclNlbmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgdXNlck1lZGlhQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pc1NlbmRWaWRlbygpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3B1Ymxpc2hWaWRlbycsIHtcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW0sXG4gICAgICAgICAgICAgICAgICAgIGRvTG9vcGJhY2s6IHRoaXMuZGlzcGxheU15UmVtb3RlKCkgfHwgZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvQWN0aXZlOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiB0aGlzLmlzU2VuZFZpZGVvKCksXG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiAoKHRoaXMuaXNTZW5kVmlkZW8oKSkgPyAodGhpcy5pc1NlbmRTY3JlZW4oKSA/ICdTQ1JFRU4nIDogJ0NBTUVSQScpIDogJycpLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xXG4gICAgICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnRXJyb3Igb24gcHVibGlzaFZpZGVvOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0xvY2FsU3RyZWFtUHVibGlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlUGVlclN1Y2Nlc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKCkudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclJlY2VpdmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgb2ZmZXJDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5yZWN2QXVkaW8sXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMucmVjdlZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWQuIENvbnN0cmFpbnRzIG9mIGdlbmVyYXRlIFNEUCBvZmZlclwiLFxuICAgICAgICAgICAgICAgIG9mZmVyQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gc3Vic2NyaWJlIHRvICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3JlY2VpdmVWaWRlb0Zyb20nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gcmVjdlZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNmdWxseUVzdGFibGlzaGVkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclJlY3Zvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKVxuICAgICAgICAgICAgICAgIC50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbW90ZVBlZXJTdWNjZXNmdWxseUVzdGFibGlzaGVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gdGhpcy53ZWJSdGNQZWVyLnBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnUGVlciByZW1vdGUgc3RyZWFtJywgdGhpcy5tZWRpYVN0cmVhbSk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSAmJiAhIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAmJiB0aGlzLnNlc3Npb24uc3BlYWtpbmdFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMgPSBuZXcgV2ViUnRjU3RhdHModGhpcyk7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wV2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMud2ViUnRjU3RhdHMgJiYgdGhpcy53ZWJSdGNTdGF0cy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5zdG9wV2ViUnRjU3RhdHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SWNlU2VydmVyc0NvbmYoKTogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgcmV0dXJuVmFsdWU7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMgPT09ICdmcmVlaWNlJyA/XG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGB2aWRlb2AgZWxlbWVudCBwYXJhbWV0ZXIgZGlzcGxheSB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IGFyZVxuICAgICAqIFttYW5hZ2luZyB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd25dKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpXG4gICAgICpcbiAgICAgKiBDYWxsaW5nIHRoaXMgbWV0aG9kIHdpdGggYSB2aWRlbyBhbHJlYWR5IGFkZGVkIHRvIG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgY2F1c2UgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYmVcbiAgICAgKiBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBwcmV2aW91cyBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgdG8gYmUgYXNzb2NpYXRlZCB0byB0aGlzIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIDEgaWYgdGhlIHZpZGVvIHdhc24ndCBhc3NvY2lhdGVkIHRvIGFueSBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqIDAgaWYgdGhlIHZpZGVvIHdhcyBhbHJlYWR5IGFkZGVkIHRvIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXIuIC0xIGlmIHRoZSB2aWRlbyB3YXMgcHJldmlvdXNseSBhc3NvY2lhdGVkIHRvIGFueSBvdGhlclxuICAgICAqIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgb25lIGFuZCBwcm9wZXJseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKi9cbiAgICBhZGRWaWRlb0VsZW1lbnQodmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgLy8gSWYgdGhlIHZpZGVvIGVsZW1lbnQgaXMgYWxyZWFkeSBwYXJ0IG9mIHRoaXMgU3RyZWFtTWFuYWdlciBkbyBub3RoaW5nXG4gICAgICAgIGZvciAoY29uc3QgdiBvZiB0aGlzLnZpZGVvcykge1xuICAgICAgICAgICAgaWYgKHYudmlkZW8gPT09IHZpZGVvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmV0dXJuTnVtYmVyID0gMTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3Muc2xpY2UoKS5yZXZlcnNlKCkuZm9yRWFjaCgoc3RyZWFtTWFuYWdlclZpZGVvLCBpbmRleCwgdmlkZW9zKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgb25jYW5wbGF5IGV2ZW50IGxpc3RlbmVyIChvbmx5IE9wZW5WaWR1IGJyb3dzZXIgb25lLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICAgICAgaWYgKCEhc3RyZWFtTWFuYWdlclZpZGVvLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbW92ZSB2aWRlb3MgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyICh0aG9zZSBnZW5lcmF0ZWQgYnkgcGFzc2luZyBhIHZhbGlkIHRhcmdldEVsZW1lbnQgaW4gT3BlblZpZHUuaW5pdFB1Ymxpc2hlciBhbmQgU2Vzc2lvbi5zdWJzY3JpYmVcbiAgICAgICAgICAgICAgICAvLyBvciB0aG9zZSBjcmVhdGVkIGJ5IFN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KS4gVGhlc2UgYXJlIGFsc28gdGhlIHZpZGVvcyB0aGF0IHRyaWdnZXJlZCBhIHZpZGVvRWxlbWVudENyZWF0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucGFyZW50Tm9kZSEucmVtb3ZlQ2hpbGQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50RGVzdHJveWVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZSh2aWRlb3MubGVuZ3RoIC0gMSAtIGluZGV4LCAxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHNyY09iamVjdCBpbiBhbGwgdmlkZW9zIG1hbmFnZWQgYnkgdGhlIHVzZXJcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwcG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gY2FwdHVyZSBzb21lIGRlc2t0b3Agc2NyZWVuIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBoYXMgYmVlbiBjYWxsZWQgd2l0aCBwcm9wZXJ0aWVzIGB2aWRlb1NvdXJjZWAgYW5kIGBhdWRpb1NvdXJjZWAgb2ZcbiAgICAgKiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBwYXJhbWV0ZXIgYm90aCBzZXQgdG8gKmZhbHNlKiBvciAqbnVsbCpcbiAgICAgKi9cbiAgICBOT19JTlBVVF9TT1VSQ0VfU0VUID0gJ05PX0lOUFVUX1NPVVJDRV9TRVQnLFxuXG4gICAgLyoqXG4gICAgICogU29tZSBtZWRpYSBwcm9wZXJ0eSBvZiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBzdWNoIGFzIGBmcmFtZVJhdGVgIG9yIGByZXNvbHV0aW9uYCBpcyBub3Qgc3VwcG9ydGVkXG4gICAgICogYnkgdGhlIGlucHV0IGRldmljZXMgKHdoZW5ldmVyIGl0IGlzIHBvc3NpYmxlIHRoZXkgYXJlIGF1dG9tYXRpY2FsbHkgYWRqdXN0ZWQgdG8gdGhlIG1vc3Qgc2ltaWxhciB2YWx1ZSkuXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEID0gJ09QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuLyoqXG4gKiBTaW1wbGUgb2JqZWN0IHRvIGlkZW50aWZ5IHJ1bnRpbWUgZXJyb3JzIG9uIHRoZSBjbGllbnQgc2lkZVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHVFcnJvciB7XG5cbiAgICBuYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBIb3cgdGhlIHZpZGVvIHdpbGwgYmUgaW5zZXJ0ZWQgaW4gdGhlIERPTSBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuIFNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dIGFuZCBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXVxuICovXG5leHBvcnQgZW51bSBWaWRlb0luc2VydE1vZGUge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHRhcmdldCBlbGVtZW50IChhcyBuZXh0IHNpYmxpbmcpXG4gICAgICovXG4gICAgQUZURVIgPSAnQUZURVInLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGxhc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgQVBQRU5EID0gJ0FQUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYmVmb3JlIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgcHJldmlvdXMgc2libGluZylcbiAgICAgKi9cbiAgICBCRUZPUkUgPSAnQkVGT1JFJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBmaXJzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBQUkVQRU5EID0gJ1BSRVBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIHJlcGxhY2VzIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUkVQTEFDRSA9ICdSRVBMQUNFJ1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYGNvbm5lY3Rpb25DcmVhdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgY29ubmVjdGlvbkRlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgd2FzIGNyZWF0ZWQgb3IgZGVzdHJveWVkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZvciAnY29ubmVjdGlvbkRlc3Ryb3llZCcgZXZlbnQ6XG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3VyIHRoYXQgbWF5IGJlIHByZXZlbnRlZCBieSBjYWxsaW5nIFtbRXZlbnQucHJldmVudERlZmF1bHRdXVxuICAgICAqL1xuICAgIGNhbmNlbGFibGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0IHRoYXQgZGlzcGF0Y2hlZCB0aGUgZXZlbnRcbiAgICAgKi9cbiAgICB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHR5cGUgb2YgZXZlbnQuIFRoaXMgaXMgdGhlIHNhbWUgc3RyaW5nIHlvdSBwYXNzIGFzIGZpcnN0IHBhcmFtZXRlciB3aGVuIGNhbGxpbmcgbWV0aG9kIGBvbigpYCBvZiBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBbW0V2ZW50RGlzcGF0Y2hlcl1dIGludGVyZmFjZVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIHByaXZhdGUgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvdXI6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvdXIgPSAoKSA9PiB7IH07XG4gICAgICAgIHRoaXMuaGFzQmVlblByZXZlbnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHJlY29yZGluZ1N0YXJ0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGByZWNvcmRpbmdTdG9wcGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIElEIGdlbmVyYXRlZCBpbiBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlY29yZGluZyBuYW1lIHlvdSBzdXBwbGllZCB0byBvcGVudmlkdS1zZXJ2ZXIuIEZvciBleGFtcGxlLCB0byBuYW1lIHlvdXIgcmVjb3JkaW5nIGZpbGUgTVlfUkVDT1JESU5HOlxuICAgICAqIC0gV2l0aCAqKkFQSSBSRVNUKio6IFBPU1QgdG8gYC9hcGkvcmVjb3JkaW5ncy9zdGFydGAgcGFzc2luZyBKU09OIGJvZHkgYHtcInNlc3Npb25cIjpcInNlc3Npb25JZFwiLFwibmFtZVwiOlwiTVlfUkVDT1JESU5HXCJ9YFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LWphdmEtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIE1ZX1JFQ09SRElORylgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKE1ZX1JFQ09SRElORykuYnVpbGQoKSlgXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtbm9kZS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgTVlfUkVDT1JESU5HKWAgb3IgYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgbmV3IFJlY29yZGluZ1Byb3BlcnRpZXMuQnVpbGRlcigpLm5hbWUoTVlfUkVDT1JESU5HKS5idWlsZCgpKWBcbiAgICAgKlxuICAgICAqIElmIG5vIG5hbWUgaXMgc3VwcGxpZWQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSB1bmRlZmluZWQgYW5kIHRoZSByZWNvcmRlZCBmaWxlIHdpbGwgYmUgbmFtZWQgYWZ0ZXIgcHJvcGVydHkgW1tpZF1dXG4gICAgICovXG4gICAgbmFtZT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIGlmIChuYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogeW91IGhhdmUgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogeW91ciBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHRydWUsIHRhcmdldCwgJ3Nlc3Npb25EaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkNhbGxpbmcgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvdXIoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEZvciAnc3RyZWFtRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwidW5wdWJsaXNoXCI6IG1ldGhvZCBgU2Vzc2lvbi51bnB1Ymxpc2goKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogbWV0aG9kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcIm5ldHdvcmtEaXNjb25uZWN0XCI6IHRoZSB1c2VyJ3MgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ3N0cmVhbUNyZWF0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFB1Ymxpc2hlciwgdHlwZTogc3RyaW5nLCBzdHJlYW06IFN0cmVhbSwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgUHVibGlzaGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9jYWwgU3RyZWFtXG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW91ciB1cG9uICdcIiArIHRoaXMudHlwZSArIFwiJyBldmVudCBkaXNwYXRjaGVkIGJ5ICdQdWJsaXNoZXInXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHZpZGVvRWxlbWVudENyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuIFNlZVxuICogW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uLlxuICogLSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSB3aGVuZXZlciBhbiBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWRlb0VsZW1lbnRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGVsZW1lbnQgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBlbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQsIHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiZnVuY3Rpb24gTWFwcGVyKClcbntcbiAgdmFyIHNvdXJjZXMgPSB7fTtcblxuXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKVxuICB7XG4gICAgZm9yKHZhciBrZXkgaW4gc291cmNlcylcbiAgICB7XG4gICAgICB2YXIgc291cmNlID0gc291cmNlc1trZXldO1xuXG4gICAgICBmb3IodmFyIGtleTIgaW4gc291cmNlKVxuICAgICAgICBjYWxsYmFjayhzb3VyY2Vba2V5Ml0pO1xuICAgIH07XG4gIH07XG5cbiAgdGhpcy5nZXQgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBpZHNbaWRdO1xuICB9O1xuXG4gIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcblxuICAgIGRlbGV0ZSBpZHNbaWRdO1xuXG4gICAgLy8gQ2hlY2sgaXQncyBlbXB0eVxuICAgIGZvcih2YXIgaSBpbiBpZHMpe3JldHVybiBmYWxzZX1cblxuICAgIGRlbGV0ZSBzb3VyY2VzW3NvdXJjZV07XG4gIH07XG5cbiAgdGhpcy5zZXQgPSBmdW5jdGlvbih2YWx1ZSwgaWQsIHNvdXJjZSlcbiAge1xuICAgIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHNvdXJjZXNbc291cmNlXSA9IGlkcyA9IHt9O1xuXG4gICAgaWRzW2lkXSA9IHZhbHVlO1xuICB9O1xufTtcblxuXG5NYXBwZXIucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG57XG4gIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGlkLCBzb3VyY2UpO1xuICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICByZXR1cm4gdmFsdWU7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gTWFwcGVyO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBKc29uUnBjQ2xpZW50ICA9IHJlcXVpcmUoJy4vanNvbnJwY2NsaWVudCcpO1xuXG5cbmV4cG9ydHMuSnNvblJwY0NsaWVudCAgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uLycpO1xudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5EYXRlLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiArbmV3IERhdGU7XG59O1xuXG52YXIgUElOR19JTlRFUlZBTCA9IDUwMDA7XG5cbnZhciBSRUNPTk5FQ1RJTkcgPSAnUkVDT05ORUNUSU5HJztcbnZhciBDT05ORUNURUQgPSAnQ09OTkVDVEVEJztcbnZhciBESVNDT05ORUNURUQgPSAnRElTQ09OTkVDVEVEJztcblxudmFyIExvZ2dlciA9IGNvbnNvbGU7XG5cbi8qKlxuICpcbiAqIGhlYXJ0YmVhdDogaW50ZXJ2YWwgaW4gbXMgZm9yIGVhY2ggaGVhcnRiZWF0IG1lc3NhZ2UsXG4gKiBzZW5kQ2xvc2VNZXNzYWdlIDogdHJ1ZSAvIGZhbHNlLCBiZWZvcmUgY2xvc2luZyB0aGUgY29ubmVjdGlvbiwgaXQgc2VuZHMgYSBjbG9zZVNlc3Npb24gbWVzc2FnZVxuICogPHByZT5cbiAqIHdzIDoge1xuICogXHR1cmkgOiBVUkkgdG8gY29ubnRlY3QgdG8sXG4gKiAgdXNlU29ja0pTIDogdHJ1ZSAodXNlIFNvY2tKUykgLyBmYWxzZSAodXNlIFdlYlNvY2tldCkgYnkgZGVmYXVsdCxcbiAqIFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuICogXHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcbiAqIFx0b25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG4gKiBcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbiAqIFx0b25lcnJvciA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGVyZSBpcyBhbiBlcnJvclxuICogfSxcbiAqIHJwYyA6IHtcbiAqIFx0cmVxdWVzdFRpbWVvdXQgOiB0aW1lb3V0IGZvciBhIHJlcXVlc3QsXG4gKiBcdHNlc3Npb25TdGF0dXNDaGFuZ2VkOiBjYWxsYmFjayBtZXRob2QgZm9yIGNoYW5nZXMgaW4gc2Vzc2lvbiBzdGF0dXMsXG4gKiBcdG1lZGlhUmVuZWdvdGlhdGlvbjogbWVkaWFSZW5lZ290aWF0aW9uXG4gKiB9XG4gKiA8L3ByZT5cbiAqL1xuZnVuY3Rpb24gSnNvblJwY0NsaWVudChjb25maWd1cmF0aW9uKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgd3NDb25maWcgPSBjb25maWd1cmF0aW9uLndzO1xuXG4gICAgdmFyIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSAtMTtcblxuICAgIHZhciBwaW5nTmV4dE51bSA9IDA7XG4gICAgdmFyIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgdmFyIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgIHZhciBwaW5nSW50ZXJ2YWw7XG5cbiAgICB2YXIgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgdmFyIG9ucmVjb25uZWN0aW5nID0gd3NDb25maWcub25yZWNvbm5lY3Rpbmc7XG4gICAgdmFyIG9ucmVjb25uZWN0ZWQgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGVkO1xuICAgIHZhciBvbmNvbm5lY3RlZCA9IHdzQ29uZmlnLm9uY29ubmVjdGVkO1xuICAgIHZhciBvbmVycm9yID0gd3NDb25maWcub25lcnJvcjtcblxuICAgIGNvbmZpZ3VyYXRpb24ucnBjLnB1bGwgPSBmdW5jdGlvbihwYXJhbXMsIHJlcXVlc3QpIHtcbiAgICAgICAgcmVxdWVzdC5yZXBseShudWxsLCBcInB1c2hcIik7XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNUSU5HIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBSRUNPTk5FQ1RJTkcpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIFJFQ09OTkVDVElORyBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVElORyBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXR1cyA9IFJFQ09OTkVDVElORztcbiAgICAgICAgaWYgKG9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9ucmVjb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uY29ubmVjdGVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05DT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVzZVBpbmcoKTtcblxuICAgICAgICBpZiAob25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9ORVJST1IgLS0tLS0tLS0tLS1cIik7XG5cbiAgICAgICAgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgICAgIGlmIChvbmVycm9yKSB7XG4gICAgICAgICAgICBvbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKHdzQ29uZmlnKTtcblxuICAgIExvZ2dlci5kZWJ1ZygnQ29ubmVjdGluZyB3ZWJzb2NrZXQgdG8gVVJJOiAnICsgd3NDb25maWcudXJpKTtcblxuICAgIHZhciBycGNCdWlsZGVyT3B0aW9ucyA9IHtcbiAgICAgICAgcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5yZXF1ZXN0VGltZW91dCxcbiAgICAgICAgcGluZ19yZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLmhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0XG4gICAgfTtcblxuICAgIHZhciBycGMgPSBuZXcgUnBjQnVpbGRlcihScGNCdWlsZGVyLnBhY2tlcnMuSnNvblJQQywgcnBjQnVpbGRlck9wdGlvbnMsIHdzLFxuICAgICAgICBmdW5jdGlvbihyZXF1ZXN0KSB7XG5cbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVjZWl2ZWQgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IGNvbmZpZ3VyYXRpb24ucnBjW3JlcXVlc3QubWV0aG9kXTtcblxuICAgICAgICAgICAgICAgIGlmIChmdW5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWV0aG9kIFwiICsgcmVxdWVzdC5tZXRob2QgKyBcIiBub3QgcmVnaXN0ZXJlZCBpbiBjbGllbnRcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyhyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKCdFeGNlcHRpb24gcHJvY2Vzc2luZyByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAobWV0aG9kICE9PSAncGluZycpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVxdWVzdDogbWV0aG9kOicgKyBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgcnBjLmVuY29kZShtZXRob2QsIHBhcmFtcywgZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1I6XCIgKyBlcnJvci5tZXNzYWdlICsgXCIgaW4gUmVxdWVzdDogbWV0aG9kOlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyBcIiByZXF1ZXN0OlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1IgREFUQTpcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yLmRhdGEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdFRpbWUgPSByZXF1ZXN0VGltZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT0gdW5kZWZpbmVkICYmIHJlc3VsdC52YWx1ZSAhPT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVzcG9uc2U6ICcgKyBKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIm5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBcIiArIHBpbmdOZXh0TnVtICsgJyAob2xkPScgK1xuICAgICAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiArICcpJyk7XG4gICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBwaW5nTmV4dE51bTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZW5kUGluZygpIHtcbiAgICAgICAgaWYgKGVuYWJsZWRQaW5ncykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG51bGw7XG4gICAgICAgICAgICBpZiAocGluZ05leHROdW0gPT0gMCB8fCBwaW5nTmV4dE51bSA9PSBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbDogY29uZmlndXJhdGlvbi5oZWFydGJlYXQgfHwgUElOR19JTlRFUlZBTFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwaW5nTmV4dE51bSsrO1xuXG4gICAgICAgICAgICBzZWxmLnNlbmQoJ3BpbmcnLCBwYXJhbXMsIChmdW5jdGlvbihwaW5nTnVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJFcnJvciBpbiBwaW5nIHJlcXVlc3QgI1wiICsgcGluZ051bSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubWVzc2FnZSArIFwiKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaW5nTnVtID4gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZXJ2ZXIgZGlkIG5vdCByZXNwb25kIHRvIHBpbmcgbWVzc2FnZSAjXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5nTnVtICsgXCIuIFJlY29ubmVjdGluZy4uLiBcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKHBpbmdOZXh0TnVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUcnlpbmcgdG8gc2VuZCBwaW5nLCBidXQgcGluZyBpcyBub3QgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgKiBJZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0IGhhcyBhbnkgdmFsdWUsIHRoZSBwaW5nLXBvbmcgd2lsbCB3b3JrIHdpdGggdGhlIGludGVydmFsXG4gICAgKiBvZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0XG4gICAgKi9cbiAgICBmdW5jdGlvbiB1c2VQaW5nKCkge1xuICAgICAgICBpZiAoIXBpbmdQb25nU3RhcnRlZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgcGluZyAoaWYgY29uZmlndXJlZClcIilcbiAgICAgICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwaW5nSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzZW5kUGluZywgY29uZmlndXJhdGlvbi5oZWFydGJlYXQpO1xuICAgICAgICAgICAgICAgIHNlbmRQaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NpbmcganNvblJwY0NsaWVudCBleHBsaWNpdGx5IGJ5IGNsaWVudFwiKTtcblxuICAgICAgICBpZiAocGluZ0ludGVydmFsICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xlYXJpbmcgcGluZyBpbnRlcnZhbFwiKTtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGNvbmZpZ3VyYXRpb24uc2VuZENsb3NlTWVzc2FnZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VuZGluZyBjbG9zZSBtZXNzYWdlXCIpXG4gICAgICAgICAgICB0aGlzLnNlbmQoJ2Nsb3NlU2Vzc2lvbicsIG51bGwsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyBjbG9zZSBtZXNzYWdlOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcblx0XHRcdHdzLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIHdzLmZvcmNlQ2xvc2UobWlsbGlzKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlY29ubmVjdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpzb25ScGNDbGllbnQ7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gID0gcmVxdWlyZSgnLi93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cblxuZXhwb3J0cy5XZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb247IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxMy0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIEJyb3dzZXJXZWJTb2NrZXQgPSBnbG9iYWwuV2ViU29ja2V0IHx8IGdsb2JhbC5Nb3pXZWJTb2NrZXQ7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqIEdldCBlaXRoZXIgdGhlIGBXZWJTb2NrZXRgIG9yIGBNb3pXZWJTb2NrZXRgIGdsb2JhbHNcbiAqIGluIHRoZSBicm93c2VyIG9yIHRyeSB0byByZXNvbHZlIFdlYlNvY2tldC1jb21wYXRpYmxlXG4gKiBpbnRlcmZhY2UgZXhwb3NlZCBieSBgd3NgIGZvciBOb2RlLWxpa2UgZW52aXJvbm1lbnQuXG4gKi9cblxuLyp2YXIgV2ViU29ja2V0ID0gQnJvd3NlcldlYlNvY2tldDtcbmlmICghV2ViU29ja2V0ICYmIHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgV2ViU29ja2V0ID0gcmVxdWlyZSgnd3MnKTtcbiAgICB9IGNhdGNoIChlKSB7IH1cbn0qL1xuXG4vL3ZhciBTb2NrSlMgPSByZXF1aXJlKCdzb2NranMtY2xpZW50Jyk7XG5cbnZhciBNQVhfUkVUUklFUyA9IDIwMDA7IC8vIEZvcmV2ZXIuLi5cbnZhciBSRVRSWV9USU1FX01TID0gMzAwMDsgLy8gRklYTUU6IEltcGxlbWVudCBleHBvbmVudGlhbCB3YWl0IHRpbWVzLi4uXG5cbnZhciBDT05ORUNUSU5HID0gMDtcbnZhciBPUEVOID0gMTtcbnZhciBDTE9TSU5HID0gMjtcbnZhciBDTE9TRUQgPSAzO1xuXG4vKlxuY29uZmlnID0ge1xuXHRcdHVyaSA6IHdzVXJpLFxuXHRcdHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG5cdFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuXHRcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuXHRcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuXHRcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYobWljcm9zb2Z0RWRnZSkge1xuICAgICAgICBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzKWNhdGNoKG9uRmFpbHVyZSk7XG4gICAgfVxufSwgJ3Bhc3Mgc2Vjb25kIHBhcmFtZXRlciBvbmx5IGlmIHlvdSB3YW50IHN5c3RlbSBhdWRpbycpO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrLCBjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKSkge1xuICAgICAgICAvLyBtaWNyb3NvZnQgZWRnZSA9PiBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSBnZXRTY3JlZW5JZDsiLCIvLyBnbG9iYWwgdmFyaWFibGVzXG52YXIgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbnZhciBzb3VyY2VJZDtcbnZhciBzY3JlZW5DYWxsYmFjaztcbnZhciBpc0ZpcmVmb3ggPSB0eXBlb2Ygd2luZG93Lkluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJztcbnZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG52YXIgaXNDaHJvbWUgPSAhIXdpbmRvdy5jaHJvbWUgJiYgIWlzT3BlcmE7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG59KTtcblxuLy8gYW5kIHRoZSBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgcmVjZWl2ZWQgbWVzc2FnZXNcbmZ1bmN0aW9uIG9uTWVzc2FnZUNhbGxiYWNrKGRhdGEpIHtcbiAgICAvLyBcImNhbmNlbFwiIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgaWYgKGRhdGEgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgaWYgKHNjcmVlbkNhbGxiYWNrKVxuICAgICAgICAgICAgcmV0dXJuIHNjcmVlbkNhbGxiYWNrKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIG5vdGlmaWVkIGhpcyBwcmVzZW5jZVxuICAgIGlmIChkYXRhID09ICdydGNtdWx0aWNvbm5lY3Rpb24tZXh0ZW5zaW9uLWxvYWRlZCcpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnZGVza3RvcCc7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBzaGFyZWQgdGVtcCBzb3VyY2VJZFxuICAgIGlmIChkYXRhLnNvdXJjZUlkICYmIHNjcmVlbkNhbGxiYWNrKSB7XG4gICAgICAgIHNjcmVlbkNhbGxiYWNrKHNvdXJjZUlkID0gZGF0YS5zb3VyY2VJZCwgZGF0YS5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9PT0gdHJ1ZSk7XG4gICAgfVxufVxuXG4vLyB0aGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiBjaHJvbWUgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCAmIGVuYWJsZWQuXG5mdW5jdGlvbiBpc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZShjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spIHJldHVybjtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKSByZXR1cm4gY2FsbGJhY2sodHJ1ZSk7XG5cbiAgICAvLyBhc2sgZXh0ZW5zaW9uIGlmIGl0IGlzIGF2YWlsYWJsZVxuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXJlLXlvdS10aGVyZScsICcqJyk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICB9IGVsc2UgY2FsbGJhY2sodHJ1ZSk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldEN1c3RvbVNvdXJjZUlkKGFyciwgY2FsbGJhY2spIHtcbiAgICBpZiAoIWFyciB8fCAhYXJyLmZvckVhY2gpIHRocm93ICdcImFyclwiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkgYW5kIGl0IG11c3QgYmUgYW4gYXJyYXkuJztcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcblxuICAgIGlmIChzb3VyY2VJZCkgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcblxuICAgIHNjcmVlbkNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgd2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgJ2dldC1jdXN0b20tc291cmNlSWQnOiBhcnJcbiAgICB9LCAnKicpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWRXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXVkaW8tcGx1cy10YWInLCAnKicpO1xufVxuXG5mdW5jdGlvbiBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMoZXh0ZW5zaW9uaWQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCdub3QtY2hyb21lJyk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggIT0gMikge1xuICAgICAgICBjYWxsYmFjayA9IGV4dGVuc2lvbmlkO1xuICAgICAgICBleHRlbnNpb25pZCA9ICdsZmNnZmVwYWZub2JkbG9lY2NobmZhY2xpYmVuam9sZCc7IC8vIGRlZmF1bHQgZXh0ZW5zaW9uLWlkXG4gICAgfVxuICAgIHZhciBpbWFnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIGltYWdlLnNyYyA9ICdjaHJvbWUtZXh0ZW5zaW9uOi8vJyArIGV4dGVuc2lvbmlkICsgJy9pY29uLnBuZyc7XG4gICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xuICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICB9LCAyMDAwKTtcbiAgICB9O1xuICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKCdub3QtaW5zdGFsbGVkJyk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgdHJ1ZSk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gZXhwbGFpbnMgaG93IHRvIHVzZSBhYm92ZSBtZXRob2RzL29iamVjdHNcbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGNhbGxiYWNrLCBjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICBzb3VyY2VJZCA9ICcnO1xuICAgIHZhciBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMgPSB7XG4gICAgICAgIG1vek1lZGlhU291cmNlOiAnd2luZG93JyxcbiAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgfTtcbiAgICBpZiAoaXNGaXJlZm94KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzKTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCBkZWZpbmVzIGdldFVzZXJNZWRpYSBjb25zdHJhaW50c1xuICAgIC8vIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGNhcHR1cmUgY29udGVudCBvZiBzY3JlZW5cbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBjaHJvbWVNZWRpYVNvdXJjZSxcbiAgICAgICAgICAgIG1heFdpZHRoOiBzY3JlZW4ud2lkdGggPiAxOTIwID8gc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgIG1heEhlaWdodDogc2NyZWVuLmhlaWdodCA+IDEwODAgPyBzY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25hbDogW11cbiAgICB9O1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IHZlcmlmaWVzIGNocm9tZSBleHRlbnNpb24gYXZhaWxhYmlsaXR5XG4gICAgLy8gaWYgaW5zdGFsbGVkIGFuZCBhdmFpbGFibGUgdGhlbiBpdCB3aWxsIGludm9rZSBleHRlbnNpb24gQVBJXG4gICAgLy8gb3RoZXJ3aXNlIGl0IHdpbGwgZmFsbGJhY2sgdG8gY29tbWFuZC1saW5lIGJhc2VkIHNjcmVlbiBjYXB0dXJpbmcgQVBJXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJyAmJiAhc291cmNlSWQpIHtcbiAgICAgICAgaWYgKGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbykge1xuICAgICAgICAgICAgZ2V0U291cmNlSWRXaXRoQXVkaW8oZnVuY3Rpb24gKHNvdXJjZUlkLCBjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCBmcmVlaWNlID0gcmVxdWlyZSgnZnJlZWljZScpO1xuaW1wb3J0IHV1aWQgPSByZXF1aXJlKCd1dWlkJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24ge1xuICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgYXVkaW86IGJvb2xlYW4sXG4gICAgICAgIHZpZGVvOiBib29sZWFuXG4gICAgfTtcbiAgICBzaW11bGNhc3Q6IGJvb2xlYW47XG4gICAgb25pY2VjYW5kaWRhdGU6IChldmVudCkgPT4gdm9pZDtcbiAgICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZDtcbiAgICBtZWRpYVN0cmVhbT86IE1lZGlhU3RyZWFtO1xuICAgIG1vZGU/OiBzdHJpbmc7IC8vIHNlbmRvbmx5LCByZWNvbmx5LCBzZW5kcmVjdlxuICAgIGlkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlciB7XG5cbiAgICBwYzogUlRDUGVlckNvbm5lY3Rpb247XG4gICAgaWQ6IHN0cmluZztcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzID0gKCEhdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiYgdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMubGVuZ3RoID4gMCkgPyB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA6IGZyZWVpY2UoKTtcblxuICAgICAgICB0aGlzLnBjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHsgaWNlU2VydmVyczogdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgfSk7XG4gICAgICAgIHRoaXMuaWQgPSAhIWNvbmZpZ3VyYXRpb24uaWQgPyBjb25maWd1cmF0aW9uLmlkIDogdXVpZC52NCgpO1xuXG4gICAgICAgIHRoaXMucGMub25pY2VjYW5kaWRhdGUgPSBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSA9IGV2ZW50LmNhbmRpZGF0ZTtcbiAgICAgICAgICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ub25pY2VjYW5kaWRhdGUoZXZlbnQuY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5wYy5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKDxSVENJY2VDYW5kaWRhdGU+dGhpcy5pY2VDYW5kaWRhdGVMaXN0LnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIHRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QgdGFraW5nIGludG8gYWNjb3VudCB0aGVcbiAgICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICAgKiBwcm9jZXNzOiBnZW5lcmF0ZXMgdGhlIFNEUCBvZmZlciBhbmQgaW52b2tlcyB0aGUgb25zZHBvZmZlciBjYWxsYmFjay4gVGhpc1xuICAgICAqIGNhbGxiYWNrIGlzIGV4cGVjdGVkIHRvIHNlbmQgdGhlIFNEUCBvZmZlciwgaW4gb3JkZXIgdG8gb2J0YWluIGFuIFNEUFxuICAgICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICAgKi9cbiAgICBzdGFydCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdUaGUgcGVlciBjb25uZWN0aW9uIG9iamVjdCBpcyBpbiBcImNsb3NlZFwiIHN0YXRlLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBhbiBpbnZvY2F0aW9uIG9mIHRoZSBkaXNwb3NlIG1ldGhvZCBiZWZvcmUgYWNjZXB0aW5nIGluIHRoZSBkaWFsb2d1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRTdHJlYW0odGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gW0hhY2tdIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDM1NThcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9PT0gJ3NlbmRvbmx5JyAmJlxuICAgICAgICAgICAgICAgIChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS52ZXJzaW9uIS50b1N0cmluZygpLnN1YnN0cmluZygwLCAyKSA9PT0gJzM5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgZnJlZXMgdGhlIHJlc291cmNlcyB1c2VkIGJ5IFdlYlJ0Y1BlZXJcbiAgICAgKi9cbiAgICBkaXNwb3NlKCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIHRoaXMucGMuZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChzdHIgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVN0b3Aoc3RyKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAgICAgICAgICAgLy8gaWYodmlkZW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbSh2aWRlb1N0cmVhbSk7XG4gICAgICAgICAgICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogMSkgRnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIG9mZmVyLCBzZXRzIGl0IGFzIGxvY2FsIGRlc2NyaXB0aW9uIGFuZCByZXR1cm5zIHRoZSBvZmZlciBwYXJhbVxuICAgICAqIHRvIHNlbmQgdG8gT3BlblZpZHUgU2VydmVyICh3aWxsIGJlIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gb2Ygb3RoZXIgcGVlcilcbiAgICAgKi9cbiAgICBnZW5lcmF0ZU9mZmVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgb2ZmZXJBdWRpbywgb2ZmZXJWaWRlbyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICBvZmZlclZpZGVvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlclZpZGVvKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUlRDUGVlckNvbm5lY3Rpb24gY29uc3RyYWludHM6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuXG4gICAgICAgICAgICB0aGlzLnBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpO1xuICAgICAgICAgICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0xvY2FsIGRlc2NyaXB0aW9uIGlzIG5vdCBkZWZpbmVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDIpIEZ1bmN0aW9uIHRvIGludm9rZSB3aGVuIGEgU0RQIG9mZmVyIGlzIHJlY2VpdmVkLiBTZXRzIGl0IGFzIHJlbW90ZSBkZXNjcmlwdGlvbixcbiAgICAgKiBnZW5lcmF0ZXMgYW5kIGFuc3dlciBhbmQgcmV0dXJucyBpdCB0byBzZW5kIGl0IHRvIE9wZW5WaWR1IFNlcnZlclxuICAgICAqL1xuICAgIHByb2Nlc3NPZmZlcihzZHBPZmZlcjogc3RyaW5nKTogUHJvbWlzZTxDb25zdHJhaW5ET01TdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBPZmZlclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU0RQIG9mZmVyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuY3JlYXRlQW5zd2VyKCk7XG4gICAgICAgICAgICAgICAgfSkudGhlbihhbnN3ZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBhbnN3ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbERlc2NyaXB0aW9uID0gdGhpcy5wYy5sb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKDxzdHJpbmc+bG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDMpIEZ1bmN0aW9uIGludm9rZWQgd2hlbiBhIFNEUCBhbnN3ZXIgaXMgcmVjZWl2ZWQuIEZpbmFsIHN0ZXAgaW4gU0RQIG5lZ290aWF0aW9uLCB0aGUgcGVlclxuICAgICAqIGp1c3QgbmVlZHMgdG8gc2V0IHRoZSBhbnN3ZXIgYXMgaXRzIHJlbW90ZSBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIHByb2Nlc3NBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnUlRDUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZS5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdGFibGUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtU3RvcChzdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHtcbiAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclJlY3Zvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRyZWN2IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRyZWN2JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzRW5hYmxlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNJbnRlcnZhbElkOiBOb2RlSlMuVGltZXI7XG4gICAgcHJpdmF0ZSBzdGF0c0ludGVydmFsID0gMTtcbiAgICBwcml2YXRlIHN0YXRzOiBhbnkgPSB7XG4gICAgICAgIGluYm91bmQ6IHtcbiAgICAgICAgICAgIGF1ZGlvOiB7XG4gICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwLFxuICAgICAgICAgICAgICAgIGZyYW1lc0RlY29kZWQ6IDAsXG4gICAgICAgICAgICAgICAgbmFja0NvdW50OiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNFbmNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHsgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWJSdGMgc3RhdHMgZW5hYmxlZCBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGNvbnN0IGluc3RydW1lbnRhdGlvbiA9IEpTT04ucGFyc2UoZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgdGhpcy5zdGF0c0ludGVydmFsID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KGluc3RydW1lbnRhdGlvbikpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRzSW50ZXJ2YWwgKiAxMDAwKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIHN0b3BwZWQgZm9yIGRpc3Bvc2VkIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLFxuICAgICAgICAgICAgICAgIChzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxvY2FsQ2FuZGlkYXRlSWQsIHJlbW90ZUNhbmRpZGF0ZUlkLCBnb29nQ2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gc3RhdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAnbG9jYWxjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlc1tzdGF0LmlkXSA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0LnR5cGUgPT09ICdyZW1vdGVjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAnZ29vZ0NhbmRpZGF0ZVBhaXInICYmIChzdGF0Lmdvb2dBY3RpdmVDb25uZWN0aW9uID09PSAndHJ1ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVJZCA9IHN0YXQubG9jYWxDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzdGF0LnJlbW90ZUNhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaW5hbExvY2FsQ2FuZGlkYXRlID0gbG9jYWxDYW5kaWRhdGVzW2xvY2FsQ2FuZGlkYXRlSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZmluYWxMb2NhbENhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwQWRkcmVzcykgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZS5yYXcgPSAhIWNhbmRbMF0gPyBjYW5kWzBdLmNhbmRpZGF0ZSA6ICdFUlJPUjogQ2Fubm90IGZpbmQgbG9jYWwgY2FuZGlkYXRlIGluIGxpc3Qgb2Ygc2VudCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSBsb2NhbCBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSByZW1vdGVDYW5kaWRhdGVzW3JlbW90ZUNhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucG9ydE51bWJlcikgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIHJlbW90ZSBjYW5kaWRhdGUgaW4gbGlzdCBvZiByZWNlaXZlZCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgcmVtb3RlIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlOiBmaW5hbExvY2FsQ2FuZGlkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZTogZmluYWxSZW1vdGVDYW5kaWRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdTZWxlY3RlZCBJQ0UgY2FuZGlkYXRlIGluZm8gb25seSBhdmFpbGFibGUgZm9yIENocm9tZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBodHRwOiBYTUxIdHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgY29uc3QgdXJsOiBzdHJpbmcgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmh0dHBFbmRwb2ludDtcbiAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIHVybCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcblxuICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7IC8vIENhbGwgYSBmdW5jdGlvbiB3aGVuIHRoZSBzdGF0ZSBjaGFuZ2VzLlxuICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQgJiYgaHR0cC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2ViUnRjIHN0YXRzIHN1Y2Nlc3NmdWxseSBzZW50IHRvICcgKyB1cmwgKyAnIGZvciBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0dHAuc2VuZChqc29uKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmID0gKHN0YXRzKSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQucmVtb3RlSWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGppdCA9IHN0YXQuaml0dGVyICogMTAwMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6IGppdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IChzdGF0LnBhY2tldHNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogJ3BhY2tldHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQubmFja0NvdW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkID0gc3RhdC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lm5hY2tDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QgPSBzdGF0LnBhY2tldHNMb3N0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChzdGF0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgaW5ib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdvdXRib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ3NzcmMnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnYnl0ZXNSZWNlaXZlZCcgaW4gc3RhdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXQubWVkaWFUeXBlID09PSAnYXVkaW8nICYmICdhdWRpb091dHB1dExldmVsJyBpbiBzdGF0KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJyAmJiAncXBTdW0nIGluIHN0YXQpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5ib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBzdGF0Lmdvb2dKaXR0ZXJCdWZmZXJNcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQuZ29vZ05hY2tzU2VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2J5dGVzU2VudCcgaW4gc3RhdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG91dGJvdW5kLXJ0cFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSwgZiwgKGVycm9yKSA9PiB7IGNvbnNvbGUubG9nKGVycm9yKTsgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZSk7XG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG5cbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2Vba2V5XSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2gocmVwb3J0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHN1Y2Nlc3NDYiwgZmFpbHVyZUNiKSB7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhudWxsKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZhaWx1cmVDYik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0sIG51bGwsIGZhaWx1cmVDYik7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iXX0= diff --git a/openvidu-js-java/.classpath b/openvidu-js-java/.classpath index a5d95095..39abf1c5 100644 --- a/openvidu-js-java/.classpath +++ b/openvidu-js-java/.classpath @@ -28,5 +28,22 @@ + + + + + + + + + + + + + + + + + diff --git a/openvidu-js-java/.settings/org.eclipse.jdt.core.prefs b/openvidu-js-java/.settings/org.eclipse.jdt.core.prefs index 714351ae..5592a0a1 100644 --- a/openvidu-js-java/.settings/org.eclipse.jdt.core.prefs +++ b/openvidu-js-java/.settings/org.eclipse.jdt.core.prefs @@ -2,4 +2,6 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 diff --git a/openvidu-js-java/pom.xml b/openvidu-js-java/pom.xml index 62941e83..9cc3b854 100644 --- a/openvidu-js-java/pom.xml +++ b/openvidu-js-java/pom.xml @@ -4,7 +4,7 @@ io.openvidu openvidu-js-java - 2.0.0 + 2.2.0 jar openvidu-js-java @@ -95,7 +95,7 @@ io.openvidu openvidu-java-client - 2.0.0 + 2.2.0 diff --git a/openvidu-js-java/src/main/resources/static/index.html b/openvidu-js-java/src/main/resources/static/index.html index 8b3a64d0..2038b481 100644 --- a/openvidu-js-java/src/main/resources/static/index.html +++ b/openvidu-js-java/src/main/resources/static/index.html @@ -14,7 +14,7 @@ - + + + diff --git a/openvidu-mvc-node/package-lock.json b/openvidu-mvc-node/package-lock.json new file mode 100644 index 00000000..452913dd --- /dev/null +++ b/openvidu-mvc-node/package-lock.json @@ -0,0 +1,2543 @@ +{ + "name": "openvidu-mvc-node", + "version": "2.2.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.1", + "http-errors": "~1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "~2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "~1.6.15" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "crc": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", + "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha1-SY7A1JVlWrxvI81hho2SZGQHGqA=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.3", + "qs": "6.5.1", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=" + } + } + }, + "express-session": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz", + "integrity": "sha1-R7QWDIj0KrcP6KUI4xy/92dXqwo=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "crc": "3.4.4", + "debug": "2.6.9", + "depd": "~1.1.1", + "on-headers": "~1.0.1", + "parseurl": "~1.3.2", + "uid-safe": "~2.1.5", + "utils-merge": "1.0.1" + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha1-7r9O2EAHnIP0JJA4ydcDAIMBsQU=", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=" + } + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha1-o0kgUKXLm2NFBUHjnZeI0icng9s=" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha1-bzI/YKg9ERRvgx/xH9ZuL+VQO7g=", + "requires": { + "mime-db": "~1.33.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "openvidu-node-client": { + "version": "2.2.0", + "requires": { + "axios": "^0.18.0", + "buffer": "^5.1.0" + }, + "dependencies": { + "@types/events": { + "version": "1.2.0", + "bundled": true + }, + "@types/fs-extra": { + "version": "5.0.1", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "5.0.35", + "bundled": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/handlebars": { + "version": "4.0.36", + "bundled": true + }, + "@types/highlight.js": { + "version": "9.12.2", + "bundled": true + }, + "@types/lodash": { + "version": "4.14.104", + "bundled": true + }, + "@types/marked": { + "version": "0.3.0", + "bundled": true + }, + "@types/minimatch": { + "version": "3.0.3", + "bundled": true + }, + "@types/node": { + "version": "10.3.2", + "bundled": true + }, + "@types/shelljs": { + "version": "0.7.8", + "bundled": true, + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "align-text": { + "version": "0.1.4", + "bundled": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "bundled": true + }, + "ansi-regex": { + "version": "1.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "1.3.2", + "bundled": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "argparse": { + "version": "1.0.10", + "bundled": true, + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "bundled": true + } + } + }, + "arr-diff": { + "version": "2.0.0", + "bundled": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "bundled": true + }, + "array-find-index": { + "version": "1.0.2", + "bundled": true + }, + "array-unique": { + "version": "0.2.1", + "bundled": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true + }, + "async": { + "version": "1.5.2", + "bundled": true + }, + "async-each": { + "version": "1.0.1", + "bundled": true + }, + "autoprefixer-core": { + "version": "5.2.1", + "bundled": true, + "requires": { + "browserslist": "~0.4.0", + "caniuse-db": "^1.0.30000214", + "num2fraction": "^1.1.0", + "postcss": "~4.1.12" + } + }, + "axios": { + "version": "0.18.0", + "bundled": true, + "requires": { + "follow-redirects": "^1.3.0", + "is-buffer": "^1.1.5" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "bundled": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + } + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "base64-js": { + "version": "1.3.0", + "bundled": true + }, + "binary-extensions": { + "version": "1.11.0", + "bundled": true + }, + "body": { + "version": "5.1.0", + "bundled": true, + "requires": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "bundled": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "bundled": true, + "requires": { + "pako": "~0.2.0" + } + }, + "browserslist": { + "version": "0.4.0", + "bundled": true, + "requires": { + "caniuse-db": "^1.0.30000153" + } + }, + "buffer": { + "version": "5.1.0", + "bundled": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.0", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "bytes": { + "version": "1.0.0", + "bundled": true + }, + "camelcase": { + "version": "2.1.1", + "bundled": true + }, + "camelcase-keys": { + "version": "2.1.0", + "bundled": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caniuse-db": { + "version": "1.0.30000851", + "bundled": true + }, + "center-align": { + "version": "0.1.3", + "bundled": true, + "optional": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "2.4.1", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "1.7.0", + "bundled": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "cliui": { + "version": "2.1.0", + "bundled": true, + "optional": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "bundled": true, + "optional": true + } + } + }, + "coffeescript": { + "version": "1.10.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.1", + "bundled": true, + "requires": { + "color-name": "^1.1.1" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.1.2", + "bundled": true + }, + "commander": { + "version": "2.15.1", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "concat-stream": { + "version": "1.6.2", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "continuable-cache": { + "version": "0.3.1", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cross-spawn": { + "version": "0.2.9", + "bundled": true, + "requires": { + "lru-cache": "^2.5.0" + } + }, + "csproj2ts": { + "version": "1.1.0", + "bundled": true, + "requires": { + "es6-promise": "^4.1.1", + "lodash": "^4.17.4", + "semver": "^5.4.1", + "xml2js": "^0.4.19" + }, + "dependencies": { + "es6-promise": { + "version": "4.2.4", + "bundled": true + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "bundled": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "dargs": { + "version": "4.1.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "dateformat": { + "version": "1.0.12", + "bundled": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "detect-indent": { + "version": "4.0.0", + "bundled": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "diff": { + "version": "1.3.2", + "bundled": true + }, + "error": { + "version": "7.0.2", + "bundled": true, + "requires": { + "string-template": "~0.2.1", + "xtend": "~4.0.0" + } + }, + "error-ex": { + "version": "1.3.1", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es6-promise": { + "version": "2.3.0", + "bundled": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "esprima": { + "version": "2.7.3", + "bundled": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true + }, + "eventemitter2": { + "version": "0.4.14", + "bundled": true + }, + "exit": { + "version": "0.1.2", + "bundled": true + }, + "expand-brackets": { + "version": "0.1.5", + "bundled": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "bundled": true, + "requires": { + "fill-range": "^2.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "bundled": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "faye-websocket": { + "version": "0.10.0", + "bundled": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "figures": { + "version": "1.7.0", + "bundled": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-sync-cmp": { + "version": "0.1.1", + "bundled": true + }, + "filename-regex": { + "version": "2.0.1", + "bundled": true + }, + "fill-range": { + "version": "2.2.4", + "bundled": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "find-up": { + "version": "1.1.2", + "bundled": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "0.3.0", + "bundled": true, + "requires": { + "glob": "~5.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "bundled": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "follow-redirects": { + "version": "1.5.0", + "bundled": true, + "requires": { + "debug": "^3.1.0" + } + }, + "for-in": { + "version": "1.0.2", + "bundled": true + }, + "for-own": { + "version": "0.1.5", + "bundled": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "fs-extra": { + "version": "5.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gaze": { + "version": "1.1.3", + "bundled": true, + "requires": { + "globule": "^1.0.0" + } + }, + "get-stdin": { + "version": "4.0.1", + "bundled": true + }, + "getobject": { + "version": "0.1.0", + "bundled": true + }, + "glob": { + "version": "7.0.6", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "bundled": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "bundled": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "globule": { + "version": "1.2.1", + "bundled": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "grunt": { + "version": "1.0.3", + "bundled": true, + "requires": { + "coffeescript": "~1.10.0", + "dateformat": "~1.0.12", + "eventemitter2": "~0.4.13", + "exit": "~0.1.1", + "findup-sync": "~0.3.0", + "glob": "~7.0.0", + "grunt-cli": "~1.2.0", + "grunt-known-options": "~1.1.0", + "grunt-legacy-log": "~2.0.0", + "grunt-legacy-util": "~1.1.1", + "iconv-lite": "~0.4.13", + "js-yaml": "~3.5.2", + "minimatch": "~3.0.2", + "mkdirp": "~0.5.1", + "nopt": "~3.0.6", + "path-is-absolute": "~1.0.0", + "rimraf": "~2.6.2" + } + }, + "grunt-autoprefixer": { + "version": "3.0.4", + "bundled": true, + "requires": { + "autoprefixer-core": "^5.1.7", + "chalk": "~1.0.0", + "diff": "~1.3.0", + "postcss": "^4.1.11" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "chalk": { + "version": "1.0.0", + "bundled": true, + "requires": { + "ansi-styles": "^2.0.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^1.0.3", + "strip-ansi": "^2.0.1", + "supports-color": "^1.3.0" + } + }, + "supports-color": { + "version": "1.3.1", + "bundled": true + } + } + }, + "grunt-cli": { + "version": "1.2.0", + "bundled": true, + "requires": { + "findup-sync": "~0.3.0", + "grunt-known-options": "~1.1.0", + "nopt": "~3.0.6", + "resolve": "~1.1.0" + } + }, + "grunt-contrib-copy": { + "version": "1.0.0", + "bundled": true, + "requires": { + "chalk": "^1.1.1", + "file-sync-cmp": "^0.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + } + } + }, + "grunt-contrib-sass": { + "version": "1.0.0", + "bundled": true, + "requires": { + "async": "^0.9.0", + "chalk": "^1.0.0", + "cross-spawn": "^0.2.3", + "dargs": "^4.0.0", + "which": "^1.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "async": { + "version": "0.9.2", + "bundled": true + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + } + } + }, + "grunt-contrib-uglify": { + "version": "3.3.0", + "bundled": true, + "requires": { + "chalk": "^1.0.0", + "maxmin": "^1.1.0", + "uglify-js": "~3.3.0", + "uri-path": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + } + } + }, + "grunt-contrib-watch": { + "version": "1.1.0", + "bundled": true, + "requires": { + "async": "^2.6.0", + "gaze": "^1.1.0", + "lodash": "^4.17.10", + "tiny-lr": "^1.1.1" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "bundled": true, + "requires": { + "lodash": "^4.17.10" + } + } + } + }, + "grunt-known-options": { + "version": "1.1.0", + "bundled": true + }, + "grunt-legacy-log": { + "version": "2.0.0", + "bundled": true, + "requires": { + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.0.0", + "hooker": "~0.2.3", + "lodash": "~4.17.5" + } + }, + "grunt-legacy-log-utils": { + "version": "2.0.1", + "bundled": true, + "requires": { + "chalk": "~2.4.1", + "lodash": "~4.17.10" + } + }, + "grunt-legacy-util": { + "version": "1.1.1", + "bundled": true, + "requires": { + "async": "~1.5.2", + "exit": "~0.1.1", + "getobject": "~0.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.10", + "underscore.string": "~3.3.4", + "which": "~1.3.0" + } + }, + "grunt-string-replace": { + "version": "1.3.1", + "bundled": true, + "requires": { + "async": "^2.0.0", + "chalk": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "async": { + "version": "2.6.1", + "bundled": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + } + } + }, + "grunt-ts": { + "version": "6.0.0-beta.19", + "bundled": true, + "requires": { + "chokidar": "^1.6.1", + "csproj2ts": "^1.1.0", + "detect-indent": "^4.0.0", + "detect-newline": "^2.1.0", + "es6-promise": "~0.1.1", + "jsmin2": "^1.2.1", + "lodash": "^4.17.4", + "ncp": "0.5.1", + "rimraf": "2.2.6", + "semver": "^5.3.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "es6-promise": { + "version": "0.1.2", + "bundled": true + }, + "rimraf": { + "version": "2.2.6", + "bundled": true + } + } + }, + "gzip-size": { + "version": "1.0.0", + "bundled": true, + "requires": { + "browserify-zlib": "^0.1.4", + "concat-stream": "^1.4.1" + } + }, + "handlebars": { + "version": "4.0.11", + "bundled": true, + "requires": { + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" + }, + "dependencies": { + "uglify-js": { + "version": "2.8.29", + "bundled": true, + "optional": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "bundled": true, + "optional": true + } + } + } + } + }, + "has-ansi": { + "version": "1.0.3", + "bundled": true, + "requires": { + "ansi-regex": "^1.1.0", + "get-stdin": "^4.0.1" + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "highlight.js": { + "version": "9.12.0", + "bundled": true + }, + "hooker": { + "version": "0.2.3", + "bundled": true + }, + "hosted-git-info": { + "version": "2.6.0", + "bundled": true + }, + "http-parser-js": { + "version": "0.4.13", + "bundled": true + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.12", + "bundled": true + }, + "indent-string": { + "version": "2.1.0", + "bundled": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "interpret": { + "version": "1.1.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-binary-path": { + "version": "1.0.1", + "bundled": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-dotfile": { + "version": "1.0.3", + "bundled": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "bundled": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "bundled": true + }, + "is-extglob": { + "version": "1.0.0", + "bundled": true + }, + "is-finite": { + "version": "1.0.2", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "bundled": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "bundled": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "bundled": true + }, + "is-primitive": { + "version": "2.0.0", + "bundled": true + }, + "is-utf8": { + "version": "0.2.1", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isobject": { + "version": "2.1.0", + "bundled": true, + "requires": { + "isarray": "1.0.0" + } + }, + "js-base64": { + "version": "2.1.9", + "bundled": true + }, + "js-tokens": { + "version": "3.0.2", + "bundled": true + }, + "js-yaml": { + "version": "3.5.5", + "bundled": true, + "requires": { + "argparse": "^1.0.2", + "esprima": "^2.6.0" + } + }, + "jsmin2": { + "version": "1.2.1", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "kind-of": { + "version": "3.2.2", + "bundled": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lazy-cache": { + "version": "1.0.4", + "bundled": true, + "optional": true + }, + "livereload-js": { + "version": "2.3.0", + "bundled": true + }, + "load-json-file": { + "version": "1.1.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "bundled": true + }, + "longest": { + "version": "1.0.1", + "bundled": true + }, + "loud-rejection": { + "version": "1.6.0", + "bundled": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lru-cache": { + "version": "2.7.3", + "bundled": true + }, + "make-error": { + "version": "1.3.4", + "bundled": true + }, + "map-obj": { + "version": "1.0.1", + "bundled": true + }, + "marked": { + "version": "0.3.19", + "bundled": true + }, + "math-random": { + "version": "1.0.1", + "bundled": true + }, + "maxmin": { + "version": "1.1.0", + "bundled": true, + "requires": { + "chalk": "^1.0.0", + "figures": "^1.0.1", + "gzip-size": "^1.0.0", + "pretty-bytes": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + } + } + }, + "meow": { + "version": "3.7.0", + "bundled": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "micromatch": { + "version": "2.3.11", + "bundled": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "ncp": { + "version": "0.5.1", + "bundled": true + }, + "nopt": { + "version": "3.0.6", + "bundled": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "bundled": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "num2fraction": { + "version": "1.2.2", + "bundled": true + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "object.omit": { + "version": "2.0.1", + "bundled": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "bundled": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "bundled": true + } + } + }, + "pako": { + "version": "0.2.9", + "bundled": true + }, + "parse-glob": { + "version": "3.0.4", + "bundled": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "bundled": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-parse": { + "version": "1.0.5", + "bundled": true + }, + "path-type": { + "version": "1.1.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pinkie": { + "version": "2.0.4", + "bundled": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "postcss": { + "version": "4.1.16", + "bundled": true, + "requires": { + "es6-promise": "~2.3.0", + "js-base64": "~2.1.8", + "source-map": "~0.4.2" + } + }, + "preserve": { + "version": "0.2.0", + "bundled": true + }, + "pretty-bytes": { + "version": "1.0.4", + "bundled": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.1.0" + } + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "progress": { + "version": "2.0.0", + "bundled": true + }, + "qs": { + "version": "6.5.2", + "bundled": true + }, + "randomatic": { + "version": "3.0.0", + "bundled": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "bundled": true + }, + "kind-of": { + "version": "6.0.2", + "bundled": true + } + } + }, + "raw-body": { + "version": "1.1.7", + "bundled": true, + "requires": { + "bytes": "1", + "string_decoder": "0.10" + }, + "dependencies": { + "string_decoder": { + "version": "0.10.31", + "bundled": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "bundled": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "bundled": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.1.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" + } + }, + "rechoir": { + "version": "0.6.2", + "bundled": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "1.0.0", + "bundled": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "bundled": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "bundled": true + }, + "repeat-element": { + "version": "1.1.2", + "bundled": true + }, + "repeat-string": { + "version": "1.6.1", + "bundled": true + }, + "repeating": { + "version": "2.0.1", + "bundled": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "resolve": { + "version": "1.1.7", + "bundled": true + }, + "right-align": { + "version": "0.1.3", + "bundled": true, + "optional": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safe-json-parse": { + "version": "1.0.1", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "bundled": true + }, + "shelljs": { + "version": "0.8.2", + "bundled": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "source-map": { + "version": "0.4.4", + "bundled": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "source-map-support": { + "version": "0.5.6", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true + }, + "sprintf-js": { + "version": "1.1.1", + "bundled": true + }, + "string-template": { + "version": "0.2.1", + "bundled": true + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "2.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "bundled": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "bundled": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "supports-color": { + "version": "5.4.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tiny-lr": { + "version": "1.1.1", + "bundled": true, + "requires": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + } + }, + "trim-newlines": { + "version": "1.0.0", + "bundled": true + }, + "ts-node": { + "version": "6.1.0", + "bundled": true, + "requires": { + "arrify": "^1.0.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "bundled": true + } + } + }, + "tslib": { + "version": "1.9.2", + "bundled": true + }, + "tslint": { + "version": "5.10.0", + "bundled": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.12.1" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "bundled": true + }, + "esprima": { + "version": "4.0.0", + "bundled": true + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "js-yaml": { + "version": "3.12.0", + "bundled": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "resolve": { + "version": "1.7.1", + "bundled": true, + "requires": { + "path-parse": "^1.0.5" + } + } + } + }, + "tsutils": { + "version": "2.27.1", + "bundled": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "typedarray": { + "version": "0.0.6", + "bundled": true + }, + "typedoc": { + "version": "0.11.1", + "bundled": true, + "requires": { + "@types/fs-extra": "5.0.1", + "@types/handlebars": "4.0.36", + "@types/highlight.js": "9.12.2", + "@types/lodash": "4.14.104", + "@types/marked": "0.3.0", + "@types/minimatch": "3.0.3", + "@types/shelljs": "0.7.8", + "fs-extra": "^5.0.0", + "handlebars": "^4.0.6", + "highlight.js": "^9.0.0", + "lodash": "^4.17.5", + "marked": "^0.3.17", + "minimatch": "^3.0.0", + "progress": "^2.0.0", + "shelljs": "^0.8.1", + "typedoc-default-themes": "^0.5.0", + "typescript": "2.7.2" + }, + "dependencies": { + "typescript": { + "version": "2.7.2", + "bundled": true + } + } + }, + "typedoc-default-themes": { + "version": "0.5.0", + "bundled": true + }, + "typedoc-plugin-sourcefile-url": { + "version": "1.0.3", + "bundled": true + }, + "typescript": { + "version": "2.9.1", + "bundled": true + }, + "uglify-js": { + "version": "3.3.28", + "bundled": true, + "requires": { + "commander": "~2.15.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "underscore.string": { + "version": "3.3.4", + "bundled": true, + "requires": { + "sprintf-js": "^1.0.3", + "util-deprecate": "^1.0.2" + } + }, + "universalify": { + "version": "0.1.1", + "bundled": true + }, + "uri-path": { + "version": "1.0.0", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.3", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "websocket-driver": { + "version": "0.7.0", + "bundled": true, + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "bundled": true + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "bundled": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "bundled": true + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "xml2js": { + "version": "0.4.19", + "bundled": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "bundled": true + }, + "xtend": { + "version": "4.0.1", + "bundled": true + }, + "yargs": { + "version": "3.10.0", + "bundled": true, + "optional": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "bundled": true, + "optional": true + } + } + }, + "yn": { + "version": "2.0.0", + "bundled": true + } + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha1-NV8mJQWmIWRrMTCnKOtkfiIFU0E=", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": ">= 1.3.1 < 2" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha1-bsyh4PjBVtFBWXVZhI32RzCmu8E=", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha1-u3PURtonlhBu/MG2AaJT1sRr0Ic=" + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha1-Kz1cckDo/C5Y+Komnl7knAhXvTo=", + "requires": { + "random-bytes": "~1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + } + } +} diff --git a/openvidu-mvc-node/package.json b/openvidu-mvc-node/package.json index 98144d92..289606a8 100644 --- a/openvidu-mvc-node/package.json +++ b/openvidu-mvc-node/package.json @@ -1,6 +1,6 @@ { "name": "openvidu-mvc-node", - "version": "2.0.0", + "version": "2.2.0", "description": "", "main": "server.js", "scripts": { @@ -21,6 +21,6 @@ "ejs": "2.6.1", "express": "4.16.3", "express-session": "1.15.6", - "openvidu-node-client": "2.0.0" + "openvidu-node-client": "2.2.0" } } diff --git a/openvidu-mvc-node/public/openvidu-browser-2.1.0.js b/openvidu-mvc-node/public/openvidu-browser-2.1.0.js deleted file mode 100644 index 3f2f3477..00000000 --- a/openvidu-mvc-node/public/openvidu-browser-2.1.0.js +++ /dev/null @@ -1,10290 +0,0 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - // At least give some kind of context to the user - var err = new Error('Unhandled "error" event. (' + er + ')'); - err.context = er; - throw err; - } - return false; - } - - handler = events[type]; - - if (!handler) - return false; - - var isFn = typeof handler === 'function'; - len = arguments.length; - switch (len) { - // fast cases - case 1: - emitNone(handler, isFn, this); - break; - case 2: - emitOne(handler, isFn, this, arguments[1]); - break; - case 3: - emitTwo(handler, isFn, this, arguments[1], arguments[2]); - break; - case 4: - emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); - break; - // slower - default: - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - emitMany(handler, isFn, this, args); - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = target._events; - if (!events) { - events = target._events = objectCreate(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener) { - target.emit('newListener', type, - listener.listener ? listener.listener : listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (!existing) { - // Optimize the case of one listener. Don't need the extra array object. - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - } else { - // If we've already got an array, just append. - if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - } - - // Check for listener leak - if (!existing.warned) { - m = $getMaxListeners(target); - if (m && m > 0 && existing.length > m) { - existing.warned = true; - var w = new Error('Possible EventEmitter memory leak detected. ' + - existing.length + ' "' + String(type) + '" listeners ' + - 'added. Use emitter.setMaxListeners() to ' + - 'increase limit.'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - if (typeof console === 'object' && console.warn) { - console.warn('%s: %s', w.name, w.message); - } - } - } - } - - return target; -} - -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - switch (arguments.length) { - case 0: - return this.listener.call(this.target); - case 1: - return this.listener.call(this.target, arguments[0]); - case 2: - return this.listener.call(this.target, arguments[0], arguments[1]); - case 3: - return this.listener.call(this.target, arguments[0], arguments[1], - arguments[2]); - default: - var args = new Array(arguments.length); - for (var i = 0; i < args.length; ++i) - args[i] = arguments[i]; - this.listener.apply(this.target, args); - } - } -} - -function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; - var wrapped = bind.call(onceWrapper, state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -EventEmitter.prototype.once = function once(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - -// Emits a 'removeListener' event if and only if the listener was removed. -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - var list, events, position, i, originalListener; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = this._events; - if (!events) - return this; - - list = events[type]; - if (!list) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - position = -1; - - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else - spliceOne(list, position); - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener) - this.emit('removeListener', type, originalListener || listener); - } - - return this; - }; - -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - var listeners, events, i; - - events = this._events; - if (!events) - return this; - - // not listening for removeListener, no need to emit - if (!events.removeListener) { - if (arguments.length === 0) { - this._events = objectCreate(null); - this._eventsCount = 0; - } else if (events[type]) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else - delete events[type]; - } - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - var keys = objectKeys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = objectCreate(null); - this._eventsCount = 0; - return this; - } - - listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - var events = target._events; - - if (!events) - return []; - - var evlistener = events[type]; - if (!evlistener) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); -} - -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } -}; - -EventEmitter.prototype.listenerCount = listenerCount; -function listenerCount(type) { - var events = this._events; - - if (events) { - var evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener) { - return evlistener.length; - } - } - - return 0; -} - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; -}; - -// About 1.5x faster than the two-arg version of Array#splice(). -function spliceOne(list, index) { - for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) - list[i] = list[k]; - list.pop(); -} - -function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) - copy[i] = arr[i]; - return copy; -} - -function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; -} - -function objectCreatePolyfill(proto) { - var F = function() {}; - F.prototype = proto; - return new F; -} -function objectKeysPolyfill(obj) { - var keys = []; - for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { - keys.push(k); - } - return k; -} -function functionBindPolyfill(context) { - var fn = this; - return function () { - return fn.apply(context, arguments); - }; -} - -},{}],2:[function(require,module,exports){ -/* jshint node: true */ -'use strict'; - -var normalice = require('normalice'); - -/** - # freeice - - The `freeice` module is a simple way of getting random STUN or TURN server - for your WebRTC application. The list of servers (just STUN at this stage) - were sourced from this [gist](https://gist.github.com/zziuni/3741933). - - ## Example Use - - The following demonstrates how you can use `freeice` with - [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): - - <<< examples/quickconnect.js - - As the `freeice` module generates ice servers in a list compliant with the - WebRTC spec you will be able to use it with raw `RTCPeerConnection` - constructors and other WebRTC libraries. - - ## Hey, don't use my STUN/TURN server! - - If for some reason your free STUN or TURN server ends up in the - list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or - [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) - that is used in this module, you can feel - free to open an issue on this repository and those servers will be removed - within 24 hours (or sooner). This is the quickest and probably the most - polite way to have something removed (and provides us some visibility - if someone opens a pull request requesting that a server is added). - - ## Please add my server! - - If you have a server that you wish to add to the list, that's awesome! I'm - sure I speak on behalf of a whole pile of WebRTC developers who say thanks. - To get it into the list, feel free to either open a pull request or if you - find that process a bit daunting then just create an issue requesting - the addition of the server (make sure you provide all the details, and if - you have a Terms of Service then including that in the PR/issue would be - awesome). - - ## I know of a free server, can I add it? - - Sure, if you do your homework and make sure it is ok to use (I'm currently - in the process of reviewing the terms of those STUN servers included from - the original list). If it's ok to go, then please see the previous entry - for how to add it. - - ## Current List of Servers - - * current as at the time of last `README.md` file generation - - ### STUN - - <<< stun.json - - ### TURN - - <<< turn.json - -**/ - -var freeice = module.exports = function(opts) { - // if a list of servers has been provided, then use it instead of defaults - var servers = { - stun: (opts || {}).stun || require('./stun.json'), - turn: (opts || {}).turn || require('./turn.json') - }; - - var stunCount = (opts || {}).stunCount || 2; - var turnCount = (opts || {}).turnCount || 0; - var selected; - - function getServers(type, count) { - var out = []; - var input = [].concat(servers[type]); - var idx; - - while (input.length && out.length < count) { - idx = (Math.random() * input.length) | 0; - out = out.concat(input.splice(idx, 1)); - } - - return out.map(function(url) { - //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up - if ((typeof url !== 'string') && (! (url instanceof String))) { - return url; - } else { - return normalice(type + ':' + url); - } - }); - } - - // add stun servers - selected = [].concat(getServers('stun', stunCount)); - - if (turnCount) { - selected = selected.concat(getServers('turn', turnCount)); - } - - return selected; -}; - -},{"./stun.json":3,"./turn.json":4,"normalice":8}],3:[function(require,module,exports){ -module.exports=[ - "stun.l.google.com:19302", - "stun1.l.google.com:19302", - "stun2.l.google.com:19302", - "stun3.l.google.com:19302", - "stun4.l.google.com:19302", - "stun.ekiga.net", - "stun.ideasip.com", - "stun.schlund.de", - "stun.stunprotocol.org:3478", - "stun.voiparound.com", - "stun.voipbuster.com", - "stun.voipstunt.com", - "stun.voxgratia.org", - "stun.services.mozilla.com" -] - -},{}],4:[function(require,module,exports){ -module.exports=[] - -},{}],5:[function(require,module,exports){ -var WildEmitter = require('wildemitter'); - -function getMaxVolume (analyser, fftBins) { - var maxVolume = -Infinity; - analyser.getFloatFrequencyData(fftBins); - - for(var i=4, ii=fftBins.length; i < ii; i++) { - if (fftBins[i] > maxVolume && fftBins[i] < 0) { - maxVolume = fftBins[i]; - } - }; - - return maxVolume; -} - - -var audioContextType; -if (typeof window !== 'undefined') { - audioContextType = window.AudioContext || window.webkitAudioContext; -} -// use a single audio context due to hardware limits -var audioContext = null; -module.exports = function(stream, options) { - var harker = new WildEmitter(); - - - // make it not break in non-supported browsers - if (!audioContextType) return harker; - - //Config - var options = options || {}, - smoothing = (options.smoothing || 0.1), - interval = (options.interval || 50), - threshold = options.threshold, - play = options.play, - history = options.history || 10, - running = true; - - //Setup Audio Context - if (!audioContext) { - audioContext = new audioContextType(); - } - var sourceNode, fftBins, analyser; - - analyser = audioContext.createAnalyser(); - analyser.fftSize = 512; - analyser.smoothingTimeConstant = smoothing; - fftBins = new Float32Array(analyser.frequencyBinCount); - - if (stream.jquery) stream = stream[0]; - if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { - //Audio Tag - sourceNode = audioContext.createMediaElementSource(stream); - if (typeof play === 'undefined') play = true; - threshold = threshold || -50; - } else { - //WebRTC Stream - sourceNode = audioContext.createMediaStreamSource(stream); - threshold = threshold || -50; - } - - sourceNode.connect(analyser); - if (play) analyser.connect(audioContext.destination); - - harker.speaking = false; - - harker.suspend = function() { - audioContext.suspend(); - } - harker.resume = function() { - audioContext.resume(); - } - Object.defineProperty(harker, 'state', { get: function() { - return audioContext.state; - }}); - audioContext.onstatechange = function() { - harker.emit('state_change', audioContext.state); - } - - harker.setThreshold = function(t) { - threshold = t; - }; - - harker.setInterval = function(i) { - interval = i; - }; - - harker.stop = function() { - running = false; - harker.emit('volume_change', -100, threshold); - if (harker.speaking) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - analyser.disconnect(); - sourceNode.disconnect(); - }; - harker.speakingHistory = []; - for (var i = 0; i < history; i++) { - harker.speakingHistory.push(0); - } - - // Poll the analyser node to determine if speaking - // and emit events if changed - var looper = function() { - setTimeout(function() { - - //check if stop has been called - if(!running) { - return; - } - - var currentVolume = getMaxVolume(analyser, fftBins); - - harker.emit('volume_change', currentVolume, threshold); - - var history = 0; - if (currentVolume > threshold && !harker.speaking) { - // trigger quickly, short history - for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history >= 2) { - harker.speaking = true; - harker.emit('speaking'); - } - } else if (currentVolume < threshold && harker.speaking) { - for (var i = 0; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history == 0) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - } - harker.speakingHistory.shift(); - harker.speakingHistory.push(0 + (currentVolume > threshold)); - - looper(); - }, interval); - }; - looper(); - - - return harker; -} - -},{"wildemitter":24}],6:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],7:[function(require,module,exports){ -/*! - * @name JavaScript/NodeJS Merge v1.2.0 - * @author yeikos - * @repository https://github.com/yeikos/js.merge - - * Copyright 2014 yeikos - MIT license - * https://raw.github.com/yeikos/js.merge/master/LICENSE - */ - -;(function(isNode) { - - /** - * Merge one or more objects - * @param bool? clone - * @param mixed,... arguments - * @return object - */ - - var Public = function(clone) { - - return merge(clone === true, false, arguments); - - }, publicName = 'merge'; - - /** - * Merge two or more objects recursively - * @param bool? clone - * @param mixed,... arguments - * @return object - */ - - Public.recursive = function(clone) { - - return merge(clone === true, true, arguments); - - }; - - /** - * Clone the input removing any reference - * @param mixed input - * @return mixed - */ - - Public.clone = function(input) { - - var output = input, - type = typeOf(input), - index, size; - - if (type === 'array') { - - output = []; - size = input.length; - - for (index=0;index 1) { - url = parts[1]; - parts = parts[0].split(':'); - - // add the output credential and username - output.username = parts[0]; - output.credential = (input || {}).credential || parts[1] || ''; - } - - output.url = protocol + url; - output.urls = [ output.url ]; - - return output; -}; - -},{}],9:[function(require,module,exports){ -(function (global){ -/*! - * Platform.js - * Copyright 2014-2018 Benjamin Tan - * Copyright 2011-2013 John-David Dalton - * Available under MIT license - */ -;(function() { - 'use strict'; - - /** Used to determine if values are of the language type `Object`. */ - var objectTypes = { - 'function': true, - 'object': true - }; - - /** Used as a reference to the global object. */ - var root = (objectTypes[typeof window] && window) || this; - - /** Backup possible global object. */ - var oldRoot = root; - - /** Detect free variable `exports`. */ - var freeExports = objectTypes[typeof exports] && exports; - - /** Detect free variable `module`. */ - var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; - - /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ - var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; - if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { - root = freeGlobal; - } - - /** - * Used as the maximum length of an array-like object. - * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) - * for more details. - */ - var maxSafeInteger = Math.pow(2, 53) - 1; - - /** Regular expression to detect Opera. */ - var reOpera = /\bOpera/; - - /** Possible global object. */ - var thisBinding = this; - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** Used to check for own properties of an object. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Used to resolve the internal `[[Class]]` of values. */ - var toString = objectProto.toString; - - /*--------------------------------------------------------------------------*/ - - /** - * Capitalizes a string value. - * - * @private - * @param {string} string The string to capitalize. - * @returns {string} The capitalized string. - */ - function capitalize(string) { - string = String(string); - return string.charAt(0).toUpperCase() + string.slice(1); - } - - /** - * A utility function to clean up the OS name. - * - * @private - * @param {string} os The OS name to clean up. - * @param {string} [pattern] A `RegExp` pattern matching the OS name. - * @param {string} [label] A label for the OS. - */ - function cleanupOS(os, pattern, label) { - // Platform tokens are defined at: - // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - var data = { - '10.0': '10', - '6.4': '10 Technical Preview', - '6.3': '8.1', - '6.2': '8', - '6.1': 'Server 2008 R2 / 7', - '6.0': 'Server 2008 / Vista', - '5.2': 'Server 2003 / XP 64-bit', - '5.1': 'XP', - '5.01': '2000 SP1', - '5.0': '2000', - '4.0': 'NT', - '4.90': 'ME' - }; - // Detect Windows version from platform tokens. - if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && - (data = data[/[\d.]+$/.exec(os)])) { - os = 'Windows ' + data; - } - // Correct character case and cleanup string. - os = String(os); - - if (pattern && label) { - os = os.replace(RegExp(pattern, 'i'), label); - } - - os = format( - os.replace(/ ce$/i, ' CE') - .replace(/\bhpw/i, 'web') - .replace(/\bMacintosh\b/, 'Mac OS') - .replace(/_PowerPC\b/i, ' OS') - .replace(/\b(OS X) [^ \d]+/i, '$1') - .replace(/\bMac (OS X)\b/, '$1') - .replace(/\/(\d)/, ' $1') - .replace(/_/g, '.') - .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') - .replace(/\bx86\.64\b/gi, 'x86_64') - .replace(/\b(Windows Phone) OS\b/, '$1') - .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') - .split(' on ')[0] - ); - - return os; - } - - /** - * An iteration utility for arrays and objects. - * - * @private - * @param {Array|Object} object The object to iterate over. - * @param {Function} callback The function called per iteration. - */ - function each(object, callback) { - var index = -1, - length = object ? object.length : 0; - - if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { - while (++index < length) { - callback(object[index], index, object); - } - } else { - forOwn(object, callback); - } - } - - /** - * Trim and conditionally capitalize string values. - * - * @private - * @param {string} string The string to format. - * @returns {string} The formatted string. - */ - function format(string) { - string = trim(string); - return /^(?:webOS|i(?:OS|P))/.test(string) - ? string - : capitalize(string); - } - - /** - * Iterates over an object's own properties, executing the `callback` for each. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} callback The function executed per own property. - */ - function forOwn(object, callback) { - for (var key in object) { - if (hasOwnProperty.call(object, key)) { - callback(object[key], key, object); - } - } - } - - /** - * Gets the internal `[[Class]]` of a value. - * - * @private - * @param {*} value The value. - * @returns {string} The `[[Class]]`. - */ - function getClassOf(value) { - return value == null - ? capitalize(value) - : toString.call(value).slice(8, -1); - } - - /** - * Host objects can return type values that are different from their actual - * data type. The objects we are concerned with usually return non-primitive - * types of "object", "function", or "unknown". - * - * @private - * @param {*} object The owner of the property. - * @param {string} property The property to check. - * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. - */ - function isHostType(object, property) { - var type = object != null ? typeof object[property] : 'number'; - return !/^(?:boolean|number|string|undefined)$/.test(type) && - (type == 'object' ? !!object[property] : true); - } - - /** - * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. - * - * @private - * @param {string} string The string to qualify. - * @returns {string} The qualified string. - */ - function qualify(string) { - return String(string).replace(/([ -])(?!$)/g, '$1?'); - } - - /** - * A bare-bones `Array#reduce` like utility function. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {*} The accumulated result. - */ - function reduce(array, callback) { - var accumulator = null; - each(array, function(value, index) { - accumulator = callback(accumulator, value, index, array); - }); - return accumulator; - } - - /** - * Removes leading and trailing whitespace from a string. - * - * @private - * @param {string} string The string to trim. - * @returns {string} The trimmed string. - */ - function trim(string) { - return String(string).replace(/^ +| +$/g, ''); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Creates a new platform object. - * - * @memberOf platform - * @param {Object|string} [ua=navigator.userAgent] The user agent string or - * context object. - * @returns {Object} A platform object. - */ - function parse(ua) { - - /** The environment context object. */ - var context = root; - - /** Used to flag when a custom context is provided. */ - var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; - - // Juggle arguments. - if (isCustomContext) { - context = ua; - ua = null; - } - - /** Browser navigator object. */ - var nav = context.navigator || {}; - - /** Browser user agent string. */ - var userAgent = nav.userAgent || ''; - - ua || (ua = userAgent); - - /** Used to flag when `thisBinding` is the [ModuleScope]. */ - var isModuleScope = isCustomContext || thisBinding == oldRoot; - - /** Used to detect if browser is like Chrome. */ - var likeChrome = isCustomContext - ? !!nav.likeChrome - : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); - - /** Internal `[[Class]]` value shortcuts. */ - var objectClass = 'Object', - airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', - enviroClass = isCustomContext ? objectClass : 'Environment', - javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), - phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; - - /** Detect Java environments. */ - var java = /\bJava/.test(javaClass) && context.java; - - /** Detect Rhino. */ - var rhino = java && getClassOf(context.environment) == enviroClass; - - /** A character to represent alpha. */ - var alpha = java ? 'a' : '\u03b1'; - - /** A character to represent beta. */ - var beta = java ? 'b' : '\u03b2'; - - /** Browser document object. */ - var doc = context.document || {}; - - /** - * Detect Opera browser (Presto-based). - * http://www.howtocreate.co.uk/operaStuff/operaObject.html - * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini - */ - var opera = context.operamini || context.opera; - - /** Opera `[[Class]]`. */ - var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) - ? operaClass - : (opera = null); - - /*------------------------------------------------------------------------*/ - - /** Temporary variable used over the script's lifetime. */ - var data; - - /** The CPU architecture. */ - var arch = ua; - - /** Platform description array. */ - var description = []; - - /** Platform alpha/beta indicator. */ - var prerelease = null; - - /** A flag to indicate that environment features should be used to resolve the platform. */ - var useFeatures = ua == userAgent; - - /** The browser/environment version. */ - var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); - - /** A flag to indicate if the OS ends with "/ Version" */ - var isSpecialCasedOS; - - /* Detectable layout engines (order is important). */ - var layout = getLayout([ - { 'label': 'EdgeHTML', 'pattern': 'Edge' }, - 'Trident', - { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, - 'iCab', - 'Presto', - 'NetFront', - 'Tasman', - 'KHTML', - 'Gecko' - ]); - - /* Detectable browser names (order is important). */ - var name = getName([ - 'Adobe AIR', - 'Arora', - 'Avant Browser', - 'Breach', - 'Camino', - 'Electron', - 'Epiphany', - 'Fennec', - 'Flock', - 'Galeon', - 'GreenBrowser', - 'iCab', - 'Iceweasel', - 'K-Meleon', - 'Konqueror', - 'Lunascape', - 'Maxthon', - { 'label': 'Microsoft Edge', 'pattern': 'Edge' }, - 'Midori', - 'Nook Browser', - 'PaleMoon', - 'PhantomJS', - 'Raven', - 'Rekonq', - 'RockMelt', - { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' }, - 'SeaMonkey', - { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Sleipnir', - 'SlimBrowser', - { 'label': 'SRWare Iron', 'pattern': 'Iron' }, - 'Sunrise', - 'Swiftfox', - 'Waterfox', - 'WebPositive', - 'Opera Mini', - { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, - 'Opera', - { 'label': 'Opera', 'pattern': 'OPR' }, - 'Chrome', - { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, - { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, - { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' }, - { 'label': 'IE', 'pattern': 'IEMobile' }, - { 'label': 'IE', 'pattern': 'MSIE' }, - 'Safari' - ]); - - /* Detectable products (order is important). */ - var product = getProduct([ - { 'label': 'BlackBerry', 'pattern': 'BB10' }, - 'BlackBerry', - { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, - { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, - { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, - { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, - { 'label': 'Galaxy S5', 'pattern': 'SM-G900' }, - { 'label': 'Galaxy S6', 'pattern': 'SM-G920' }, - { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' }, - { 'label': 'Galaxy S7', 'pattern': 'SM-G930' }, - { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' }, - 'Google TV', - 'Lumia', - 'iPad', - 'iPod', - 'iPhone', - 'Kindle', - { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Nexus', - 'Nook', - 'PlayBook', - 'PlayStation Vita', - 'PlayStation', - 'TouchPad', - 'Transformer', - { 'label': 'Wii U', 'pattern': 'WiiU' }, - 'Wii', - 'Xbox One', - { 'label': 'Xbox 360', 'pattern': 'Xbox' }, - 'Xoom' - ]); - - /* Detectable manufacturers. */ - var manufacturer = getManufacturer({ - 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, - 'Archos': {}, - 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, - 'Asus': { 'Transformer': 1 }, - 'Barnes & Noble': { 'Nook': 1 }, - 'BlackBerry': { 'PlayBook': 1 }, - 'Google': { 'Google TV': 1, 'Nexus': 1 }, - 'HP': { 'TouchPad': 1 }, - 'HTC': {}, - 'LG': {}, - 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, - 'Motorola': { 'Xoom': 1 }, - 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, - 'Nokia': { 'Lumia': 1 }, - 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, - 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 } - }); - - /* Detectable operating systems (order is important). */ - var os = getOS([ - 'Windows Phone', - 'Android', - 'CentOS', - { 'label': 'Chrome OS', 'pattern': 'CrOS' }, - 'Debian', - 'Fedora', - 'FreeBSD', - 'Gentoo', - 'Haiku', - 'Kubuntu', - 'Linux Mint', - 'OpenBSD', - 'Red Hat', - 'SuSE', - 'Ubuntu', - 'Xubuntu', - 'Cygwin', - 'Symbian OS', - 'hpwOS', - 'webOS ', - 'webOS', - 'Tablet OS', - 'Tizen', - 'Linux', - 'Mac OS X', - 'Macintosh', - 'Mac', - 'Windows 98;', - 'Windows ' - ]); - - /*------------------------------------------------------------------------*/ - - /** - * Picks the layout engine from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected layout engine. - */ - function getLayout(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the manufacturer from an array of guesses. - * - * @private - * @param {Array} guesses An object of guesses. - * @returns {null|string} The detected manufacturer. - */ - function getManufacturer(guesses) { - return reduce(guesses, function(result, value, key) { - // Lookup the manufacturer by product or scan the UA for the manufacturer. - return result || ( - value[product] || - value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || - RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) - ) && key; - }); - } - - /** - * Picks the browser name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected browser name. - */ - function getName(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the OS name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected OS name. - */ - function getOS(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) - )) { - result = cleanupOS(result, pattern, guess.label || guess); - } - return result; - }); - } - - /** - * Picks the product name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected product name. - */ - function getProduct(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || - RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) || - RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) - )) { - // Split by forward slash and append product version if needed. - if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { - result[0] += ' ' + result[1]; - } - // Correct character case and cleanup string. - guess = guess.label || guess; - result = format(result[0] - .replace(RegExp(pattern, 'i'), guess) - .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') - .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); - } - return result; - }); - } - - /** - * Resolves the version using an array of UA patterns. - * - * @private - * @param {Array} patterns An array of UA patterns. - * @returns {null|string} The detected version. - */ - function getVersion(patterns) { - return reduce(patterns, function(result, pattern) { - return result || (RegExp(pattern + - '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; - }); - } - - /** - * Returns `platform.description` when the platform object is coerced to a string. - * - * @name toString - * @memberOf platform - * @returns {string} Returns `platform.description` if available, else an empty string. - */ - function toStringPlatform() { - return this.description || ''; - } - - /*------------------------------------------------------------------------*/ - - // Convert layout to an array so we can add extra details. - layout && (layout = [layout]); - - // Detect product names that contain their manufacturer's name. - if (manufacturer && !product) { - product = getProduct([manufacturer]); - } - // Clean up Google TV. - if ((data = /\bGoogle TV\b/.exec(product))) { - product = data[0]; - } - // Detect simulators. - if (/\bSimulator\b/i.test(ua)) { - product = (product ? product + ' ' : '') + 'Simulator'; - } - // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. - if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { - description.push('running in Turbo/Uncompressed mode'); - } - // Detect IE Mobile 11. - if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) { - data = parse(ua.replace(/like iPhone OS/, '')); - manufacturer = data.manufacturer; - product = data.product; - } - // Detect iOS. - else if (/^iP/.test(product)) { - name || (name = 'Safari'); - os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) - ? ' ' + data[1].replace(/_/g, '.') - : ''); - } - // Detect Kubuntu. - else if (name == 'Konqueror' && !/buntu/i.test(os)) { - os = 'Kubuntu'; - } - // Detect Android browsers. - else if ((manufacturer && manufacturer != 'Google' && - ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) || - (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) { - name = 'Android Browser'; - os = /\bAndroid\b/.test(os) ? os : 'Android'; - } - // Detect Silk desktop/accelerated modes. - else if (name == 'Silk') { - if (!/\bMobi/i.test(ua)) { - os = 'Android'; - description.unshift('desktop mode'); - } - if (/Accelerated *= *true/i.test(ua)) { - description.unshift('accelerated'); - } - } - // Detect PaleMoon identifying as Firefox. - else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { - description.push('identifying as Firefox ' + data[1]); - } - // Detect Firefox OS and products running Firefox. - else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { - os || (os = 'Firefox OS'); - product || (product = data[1]); - } - // Detect false positives for Firefox/Safari. - else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { - // Escape the `/` for Firefox 1. - if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { - // Clear name of false positives. - name = null; - } - // Reassign a generic name. - if ((data = product || manufacturer || os) && - (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { - name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; - } - } - // Add Chrome version to description for Electron. - else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) { - description.push('Chromium ' + data); - } - // Detect non-Opera (Presto-based) versions (order is important). - if (!version) { - version = getVersion([ - '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))', - 'Version', - qualify(name), - '(?:Firefox|Minefield|NetFront)' - ]); - } - // Detect stubborn layout engines. - if ((data = - layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || - /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || - /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || - !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || - layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' - )) { - layout = [data]; - } - // Detect Windows Phone 7 desktop mode. - if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { - name += ' Mobile'; - os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); - description.unshift('desktop mode'); - } - // Detect Windows Phone 8.x desktop mode. - else if (/\bWPDesktop\b/i.test(ua)) { - name = 'IE Mobile'; - os = 'Windows Phone 8.x'; - description.unshift('desktop mode'); - version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); - } - // Detect IE 11 identifying as other browsers. - else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { - if (name) { - description.push('identifying as ' + name + (version ? ' ' + version : '')); - } - name = 'IE'; - version = data[1]; - } - // Leverage environment features. - if (useFeatures) { - // Detect server-side environments. - // Rhino has a global function while others have a global object. - if (isHostType(context, 'global')) { - if (java) { - data = java.lang.System; - arch = data.getProperty('os.arch'); - os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); - } - if (rhino) { - try { - version = context.require('ringo/engine').version.join('.'); - name = 'RingoJS'; - } catch(e) { - if ((data = context.system) && data.global.system == context.system) { - name = 'Narwhal'; - os || (os = data[0].os || null); - } - } - if (!name) { - name = 'Rhino'; - } - } - else if ( - typeof context.process == 'object' && !context.process.browser && - (data = context.process) - ) { - if (typeof data.versions == 'object') { - if (typeof data.versions.electron == 'string') { - description.push('Node ' + data.versions.node); - name = 'Electron'; - version = data.versions.electron; - } else if (typeof data.versions.nw == 'string') { - description.push('Chromium ' + version, 'Node ' + data.versions.node); - name = 'NW.js'; - version = data.versions.nw; - } - } - if (!name) { - name = 'Node.js'; - arch = data.arch; - os = data.platform; - version = /[\d.]+/.exec(data.version); - version = version ? version[0] : null; - } - } - } - // Detect Adobe AIR. - else if (getClassOf((data = context.runtime)) == airRuntimeClass) { - name = 'Adobe AIR'; - os = data.flash.system.Capabilities.os; - } - // Detect PhantomJS. - else if (getClassOf((data = context.phantom)) == phantomClass) { - name = 'PhantomJS'; - version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); - } - // Detect IE compatibility modes. - else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { - // We're in compatibility mode when the Trident version + 4 doesn't - // equal the document mode. - version = [version, doc.documentMode]; - if ((data = +data[1] + 4) != version[1]) { - description.push('IE ' + version[1] + ' mode'); - layout && (layout[1] = ''); - version[1] = data; - } - version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; - } - // Detect IE 11 masking as other browsers. - else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) { - description.push('masking as ' + name + ' ' + version); - name = 'IE'; - version = '11.0'; - layout = ['Trident']; - os = 'Windows'; - } - os = os && format(os); - } - // Detect prerelease phases. - if (version && (data = - /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || - /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || - /\bMinefield\b/i.test(ua) && 'a' - )) { - prerelease = /b/i.test(data) ? 'beta' : 'alpha'; - version = version.replace(RegExp(data + '\\+?$'), '') + - (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); - } - // Detect Firefox Mobile. - if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) { - name = 'Firefox Mobile'; - } - // Obscure Maxthon's unreliable version. - else if (name == 'Maxthon' && version) { - version = version.replace(/\.[\d.]+/, '.x'); - } - // Detect Xbox 360 and Xbox One. - else if (/\bXbox\b/i.test(product)) { - if (product == 'Xbox 360') { - os = null; - } - if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { - description.unshift('mobile mode'); - } - } - // Add mobile postfix. - else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && - (os == 'Windows CE' || /Mobi/i.test(ua))) { - name += ' Mobile'; - } - // Detect IE platform preview. - else if (name == 'IE' && useFeatures) { - try { - if (context.external === null) { - description.unshift('platform preview'); - } - } catch(e) { - description.unshift('embedded'); - } - } - // Detect BlackBerry OS version. - // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp - else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = - (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || - version - )) { - data = [data, /BB10/.test(ua)]; - os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; - version = null; - } - // Detect Opera identifying/masking itself as another browser. - // http://www.opera.com/support/kb/view/843/ - else if (this != forOwn && product != 'Wii' && ( - (useFeatures && opera) || - (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || - (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || - (name == 'IE' && ( - (os && !/^Win/.test(os) && version > 5.5) || - /\bWindows XP\b/.test(os) && version > 8 || - version == 8 && !/\bTrident\b/.test(ua) - )) - ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { - // When "identifying", the UA contains both Opera and the other browser's name. - data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); - if (reOpera.test(name)) { - if (/\bIE\b/.test(data) && os == 'Mac OS') { - os = null; - } - data = 'identify' + data; - } - // When "masking", the UA contains only the other browser's name. - else { - data = 'mask' + data; - if (operaClass) { - name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); - } else { - name = 'Opera'; - } - if (/\bIE\b/.test(data)) { - os = null; - } - if (!useFeatures) { - version = null; - } - } - layout = ['Presto']; - description.push(data); - } - // Detect WebKit Nightly and approximate Chrome/Safari versions. - if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - // Correct build number for numeric comparison. - // (e.g. "532.5" becomes "532.05") - data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; - // Nightly builds are postfixed with a "+". - if (name == 'Safari' && data[1].slice(-1) == '+') { - name = 'WebKit Nightly'; - prerelease = 'alpha'; - version = data[1].slice(0, -1); - } - // Clear incorrect browser versions. - else if (version == data[1] || - version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - version = null; - } - // Use the full Chrome version when available. - data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]; - // Detect Blink layout engine. - if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { - layout = ['Blink']; - } - // Detect JavaScriptCore. - // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi - if (!useFeatures || (!likeChrome && !data[1])) { - layout && (layout[1] = 'like Safari'); - data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8'); - } else { - layout && (layout[1] = 'like Chrome'); - data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); - } - // Add the postfix of ".x" or "+" for approximate versions. - layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); - // Obscure version for some Safari 1-2 releases. - if (name == 'Safari' && (!version || parseInt(version) > 45)) { - version = data; - } - } - // Detect Opera desktop modes. - if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { - name += ' '; - description.unshift('desktop mode'); - if (data == 'zvav') { - name += 'Mini'; - version = null; - } else { - name += 'Mobile'; - } - os = os.replace(RegExp(' *' + data + '$'), ''); - } - // Detect Chrome desktop mode. - else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { - description.unshift('desktop mode'); - name = 'Chrome Mobile'; - version = null; - - if (/\bOS X\b/.test(os)) { - manufacturer = 'Apple'; - os = 'iOS 4.3+'; - } else { - os = null; - } - } - // Strip incorrect OS versions. - if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && - ua.indexOf('/' + data + '-') > -1) { - os = trim(os.replace(data, '')); - } - // Add layout engine. - if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( - /Browser|Lunascape|Maxthon/.test(name) || - name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || - /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) { - // Don't add layout details to description if they are falsey. - (data = layout[layout.length - 1]) && description.push(data); - } - // Combine contextual information. - if (description.length) { - description = ['(' + description.join('; ') + ')']; - } - // Append manufacturer to description. - if (manufacturer && product && product.indexOf(manufacturer) < 0) { - description.push('on ' + manufacturer); - } - // Append product to description. - if (product) { - description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); - } - // Parse the OS into an object. - if (os) { - data = / ([\d.+]+)$/.exec(os); - isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; - os = { - 'architecture': 32, - 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, - 'version': data ? data[1] : null, - 'toString': function() { - var version = this.version; - return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); - } - }; - } - // Add browser/OS architecture. - if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { - if (os) { - os.architecture = 64; - os.family = os.family.replace(RegExp(' *' + data), ''); - } - if ( - name && (/\bWOW64\b/i.test(ua) || - (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) - ) { - description.unshift('32-bit'); - } - } - // Chrome 39 and above on OS X is always 64-bit. - else if ( - os && /^OS X/.test(os.family) && - name == 'Chrome' && parseFloat(version) >= 39 - ) { - os.architecture = 64; - } - - ua || (ua = null); - - /*------------------------------------------------------------------------*/ - - /** - * The platform object. - * - * @name platform - * @type Object - */ - var platform = {}; - - /** - * The platform description. - * - * @memberOf platform - * @type string|null - */ - platform.description = ua; - - /** - * The name of the browser's layout engine. - * - * The list of common layout engines include: - * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit" - * - * @memberOf platform - * @type string|null - */ - platform.layout = layout && layout[0]; - - /** - * The name of the product's manufacturer. - * - * The list of manufacturers include: - * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry", - * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo", - * "Nokia", "Samsung" and "Sony" - * - * @memberOf platform - * @type string|null - */ - platform.manufacturer = manufacturer; - - /** - * The name of the browser/environment. - * - * The list of common browser names include: - * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE", - * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk", - * "Opera Mini" and "Opera" - * - * Mobile versions of some browsers have "Mobile" appended to their name: - * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile" - * - * @memberOf platform - * @type string|null - */ - platform.name = name; - - /** - * The alpha/beta release indicator. - * - * @memberOf platform - * @type string|null - */ - platform.prerelease = prerelease; - - /** - * The name of the product hosting the browser. - * - * The list of common products include: - * - * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle", - * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer" - * - * @memberOf platform - * @type string|null - */ - platform.product = product; - - /** - * The browser's user agent string. - * - * @memberOf platform - * @type string|null - */ - platform.ua = ua; - - /** - * The browser/environment version. - * - * @memberOf platform - * @type string|null - */ - platform.version = name && version; - - /** - * The name of the operating system. - * - * @memberOf platform - * @type Object - */ - platform.os = os || { - - /** - * The CPU architecture the OS is built for. - * - * @memberOf platform.os - * @type number|null - */ - 'architecture': null, - - /** - * The family of the OS. - * - * Common values include: - * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", - * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", - * "Android", "iOS" and "Windows Phone" - * - * @memberOf platform.os - * @type string|null - */ - 'family': null, - - /** - * The version of the OS. - * - * @memberOf platform.os - * @type string|null - */ - 'version': null, - - /** - * Returns the OS string. - * - * @memberOf platform.os - * @returns {string} The OS string. - */ - 'toString': function() { return 'null'; } - }; - - platform.parse = parse; - platform.toString = toStringPlatform; - - if (platform.version) { - description.unshift(version); - } - if (platform.name) { - description.unshift(name); - } - if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { - description.push(product ? '(' + os + ')' : 'on ' + os); - } - if (description.length) { - platform.description = description.join(' '); - } - return platform; - } - - /*--------------------------------------------------------------------------*/ - - // Export platform. - var platform = parse(); - - // Some AMD build optimizers, like r.js, check for condition patterns like the following: - if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose platform on the global object to prevent errors when platform is - // loaded by a script tag in the presence of an AMD loader. - // See http://requirejs.org/docs/errors.html#mismatch for more details. - root.platform = platform; - - // Define as an anonymous module so platform can be aliased through path mapping. - define(function() { - return platform; - }); - } - // Check for `exports` after `define` in case a build optimizer adds an `exports` object. - else if (freeExports && freeModule) { - // Export for CommonJS support. - forOwn(platform, function(value, key) { - freeExports[key] = value; - }); - } - else { - // Export to the global object. - root.platform = platform; - } -}.call(this)); - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],10:[function(require,module,exports){ -var grammar = module.exports = { - v: [{ - name: 'version', - reg: /^(\d*)$/ - }], - o: [{ //o=- 20518 0 IN IP4 203.0.113.1 - // NB: sessionId will be a String in most cases because it is huge - name: 'origin', - reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, - names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], - format: "%s %s %d %s IP%d %s" - }], - // default parsing of these only (though some of these feel outdated) - s: [{ name: 'name' }], - i: [{ name: 'description' }], - u: [{ name: 'uri' }], - e: [{ name: 'email' }], - p: [{ name: 'phone' }], - z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly.. - r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly - //k: [{}], // outdated thing ignored - t: [{ //t=0 0 - name: 'timing', - reg: /^(\d*) (\d*)/, - names: ['start', 'stop'], - format: "%d %d" - }], - c: [{ //c=IN IP4 10.47.197.26 - name: 'connection', - reg: /^IN IP(\d) (\S*)/, - names: ['version', 'ip'], - format: "IN IP%d %s" - }], - b: [{ //b=AS:4000 - push: 'bandwidth', - reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, - names: ['type', 'limit'], - format: "%s:%s" - }], - m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31 - // NB: special - pushes to session - // TODO: rtp/fmtp should be filtered by the payloads found here? - reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/, - names: ['type', 'port', 'protocol', 'payloads'], - format: "%s %d %s %s" - }], - a: [ - { //a=rtpmap:110 opus/48000/2 - push: 'rtp', - reg: /^rtpmap:(\d*) ([\w\-]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, - names: ['payload', 'codec', 'rate', 'encoding'], - format: function (o) { - return (o.encoding) ? - "rtpmap:%d %s/%s/%s": - o.rate ? - "rtpmap:%d %s/%s": - "rtpmap:%d %s"; - } - }, - { - //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 - //a=fmtp:111 minptime=10; useinbandfec=1 - push: 'fmtp', - reg: /^fmtp:(\d*) ([\S| ]*)/, - names: ['payload', 'config'], - format: "fmtp:%d %s" - }, - { //a=control:streamid=0 - name: 'control', - reg: /^control:(.*)/, - format: "control:%s" - }, - { //a=rtcp:65179 IN IP4 193.84.77.194 - name: 'rtcp', - reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, - names: ['port', 'netType', 'ipVer', 'address'], - format: function (o) { - return (o.address != null) ? - "rtcp:%d %s IP%d %s": - "rtcp:%d"; - } - }, - { //a=rtcp-fb:98 trr-int 100 - push: 'rtcpFbTrrInt', - reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, - names: ['payload', 'value'], - format: "rtcp-fb:%d trr-int %d" - }, - { //a=rtcp-fb:98 nack rpsi - push: 'rtcpFb', - reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, - names: ['payload', 'type', 'subtype'], - format: function (o) { - return (o.subtype != null) ? - "rtcp-fb:%s %s %s": - "rtcp-fb:%s %s"; - } - }, - { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset - //a=extmap:1/recvonly URI-gps-string - push: 'ext', - reg: /^extmap:([\w_\/]*) (\S*)(?: (\S*))?/, - names: ['value', 'uri', 'config'], // value may include "/direction" suffix - format: function (o) { - return (o.config != null) ? - "extmap:%s %s %s": - "extmap:%s %s"; - } - }, - { - //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 - push: 'crypto', - reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, - names: ['id', 'suite', 'config', 'sessionConfig'], - format: function (o) { - return (o.sessionConfig != null) ? - "crypto:%d %s %s %s": - "crypto:%d %s %s"; - } - }, - { //a=setup:actpass - name: 'setup', - reg: /^setup:(\w*)/, - format: "setup:%s" - }, - { //a=mid:1 - name: 'mid', - reg: /^mid:([^\s]*)/, - format: "mid:%s" - }, - { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a - name: 'msid', - reg: /^msid:(.*)/, - format: "msid:%s" - }, - { //a=ptime:20 - name: 'ptime', - reg: /^ptime:(\d*)/, - format: "ptime:%d" - }, - { //a=maxptime:60 - name: 'maxptime', - reg: /^maxptime:(\d*)/, - format: "maxptime:%d" - }, - { //a=sendrecv - name: 'direction', - reg: /^(sendrecv|recvonly|sendonly|inactive)/ - }, - { //a=ice-lite - name: 'icelite', - reg: /^(ice-lite)/ - }, - { //a=ice-ufrag:F7gI - name: 'iceUfrag', - reg: /^ice-ufrag:(\S*)/, - format: "ice-ufrag:%s" - }, - { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g - name: 'icePwd', - reg: /^ice-pwd:(\S*)/, - format: "ice-pwd:%s" - }, - { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 - name: 'fingerprint', - reg: /^fingerprint:(\S*) (\S*)/, - names: ['type', 'hash'], - format: "fingerprint:%s %s" - }, - { - //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host - //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 - //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 - //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 - //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 - push:'candidates', - reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?/, - names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation'], - format: function (o) { - var str = "candidate:%s %d %s %d %s %d typ %s"; - - str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v"; - - // NB: candidate has three optional chunks, so %void middles one if it's missing - str += (o.tcptype != null) ? " tcptype %s" : "%v"; - - if (o.generation != null) { - str += " generation %d"; - } - return str; - } - }, - { //a=end-of-candidates (keep after the candidates line for readability) - name: 'endOfCandidates', - reg: /^(end-of-candidates)/ - }, - { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... - name: 'remoteCandidates', - reg: /^remote-candidates:(.*)/, - format: "remote-candidates:%s" - }, - { //a=ice-options:google-ice - name: 'iceOptions', - reg: /^ice-options:(\S*)/, - format: "ice-options:%s" - }, - { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 - push: "ssrcs", - reg: /^ssrc:(\d*) ([\w_]*):(.*)/, - names: ['id', 'attribute', 'value'], - format: "ssrc:%d %s:%s" - }, - { //a=ssrc-group:FEC 1 2 - push: "ssrcGroups", - reg: /^ssrc-group:(\w*) (.*)/, - names: ['semantics', 'ssrcs'], - format: "ssrc-group:%s %s" - }, - { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV - name: "msidSemantic", - reg: /^msid-semantic:\s?(\w*) (\S*)/, - names: ['semantic', 'token'], - format: "msid-semantic: %s %s" // space after ":" is not accidental - }, - { //a=group:BUNDLE audio video - push: 'groups', - reg: /^group:(\w*) (.*)/, - names: ['type', 'mids'], - format: "group:%s %s" - }, - { //a=rtcp-mux - name: 'rtcpMux', - reg: /^(rtcp-mux)/ - }, - { //a=rtcp-rsize - name: 'rtcpRsize', - reg: /^(rtcp-rsize)/ - }, - { // any a= that we don't understand is kepts verbatim on media.invalid - push: 'invalid', - names: ["value"] - } - ] -}; - -// set sensible defaults to avoid polluting the grammar with boring details -Object.keys(grammar).forEach(function (key) { - var objs = grammar[key]; - objs.forEach(function (obj) { - if (!obj.reg) { - obj.reg = /(.*)/; - } - if (!obj.format) { - obj.format = "%s"; - } - }); -}); - -},{}],11:[function(require,module,exports){ -var parser = require('./parser'); -var writer = require('./writer'); - -exports.write = writer; -exports.parse = parser.parse; -exports.parseFmtpConfig = parser.parseFmtpConfig; -exports.parsePayloads = parser.parsePayloads; -exports.parseRemoteCandidates = parser.parseRemoteCandidates; - -},{"./parser":12,"./writer":13}],12:[function(require,module,exports){ -var toIntIfInt = function (v) { - return String(Number(v)) === v ? Number(v) : v; -}; - -var attachProperties = function (match, location, names, rawName) { - if (rawName && !names) { - location[rawName] = toIntIfInt(match[1]); - } - else { - for (var i = 0; i < names.length; i += 1) { - if (match[i+1] != null) { - location[names[i]] = toIntIfInt(match[i+1]); - } - } - } -}; - -var parseReg = function (obj, location, content) { - var needsBlank = obj.name && obj.names; - if (obj.push && !location[obj.push]) { - location[obj.push] = []; - } - else if (needsBlank && !location[obj.name]) { - location[obj.name] = {}; - } - var keyLocation = obj.push ? - {} : // blank object that will be pushed - needsBlank ? location[obj.name] : location; // otherwise, named location or root - - attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name); - - if (obj.push) { - location[obj.push].push(keyLocation); - } -}; - -var grammar = require('./grammar'); -var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/); - -exports.parse = function (sdp) { - var session = {} - , media = [] - , location = session; // points at where properties go under (one of the above) - - // parse lines we understand - sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) { - var type = l[0]; - var content = l.slice(2); - if (type === 'm') { - media.push({rtp: [], fmtp: []}); - location = media[media.length-1]; // point at latest media line - } - - for (var j = 0; j < (grammar[type] || []).length; j += 1) { - var obj = grammar[type][j]; - if (obj.reg.test(content)) { - return parseReg(obj, location, content); - } - } - }); - - session.media = media; // link it up - return session; -}; - -var fmtpReducer = function (acc, expr) { - var s = expr.split('='); - if (s.length === 2) { - acc[s[0]] = toIntIfInt(s[1]); - } - return acc; -}; - -exports.parseFmtpConfig = function (str) { - return str.split(/\;\s?/).reduce(fmtpReducer, {}); -}; - -exports.parsePayloads = function (str) { - return str.split(' ').map(Number); -}; - -exports.parseRemoteCandidates = function (str) { - var candidates = []; - var parts = str.split(' ').map(toIntIfInt); - for (var i = 0; i < parts.length; i += 3) { - candidates.push({ - component: parts[i], - ip: parts[i + 1], - port: parts[i + 2] - }); - } - return candidates; -}; - -},{"./grammar":10}],13:[function(require,module,exports){ -var grammar = require('./grammar'); - -// customized util.format - discards excess arguments and can void middle ones -var formatRegExp = /%[sdv%]/g; -var format = function (formatStr) { - var i = 1; - var args = arguments; - var len = args.length; - return formatStr.replace(formatRegExp, function (x) { - if (i >= len) { - return x; // missing argument - } - var arg = args[i]; - i += 1; - switch (x) { - case '%%': - return '%'; - case '%s': - return String(arg); - case '%d': - return Number(arg); - case '%v': - return ''; - } - }); - // NB: we discard excess arguments - they are typically undefined from makeLine -}; - -var makeLine = function (type, obj, location) { - var str = obj.format instanceof Function ? - (obj.format(obj.push ? location : location[obj.name])) : - obj.format; - - var args = [type + '=' + str]; - if (obj.names) { - for (var i = 0; i < obj.names.length; i += 1) { - var n = obj.names[i]; - if (obj.name) { - args.push(location[obj.name][n]); - } - else { // for mLine and push attributes - args.push(location[obj.names[i]]); - } - } - } - else { - args.push(location[obj.name]); - } - return format.apply(null, args); -}; - -// RFC specified order -// TODO: extend this with all the rest -var defaultOuterOrder = [ - 'v', 'o', 's', 'i', - 'u', 'e', 'p', 'c', - 'b', 't', 'r', 'z', 'a' -]; -var defaultInnerOrder = ['i', 'c', 'b', 'a']; - - -module.exports = function (session, opts) { - opts = opts || {}; - // ensure certain properties exist - if (session.version == null) { - session.version = 0; // "v=0" must be there (only defined version atm) - } - if (session.name == null) { - session.name = " "; // "s= " must be there if no meaningful name set - } - session.media.forEach(function (mLine) { - if (mLine.payloads == null) { - mLine.payloads = ""; - } - }); - - var outerOrder = opts.outerOrder || defaultOuterOrder; - var innerOrder = opts.innerOrder || defaultInnerOrder; - var sdp = []; - - // loop through outerOrder for matching properties on session - outerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in session && session[obj.name] != null) { - sdp.push(makeLine(type, obj, session)); - } - else if (obj.push in session && session[obj.push] != null) { - session[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - - // then for each media line, follow the innerOrder - session.media.forEach(function (mLine) { - sdp.push(makeLine('m', grammar.m[0], mLine)); - - innerOrder.forEach(function (type) { - grammar[type].forEach(function (obj) { - if (obj.name in mLine && mLine[obj.name] != null) { - sdp.push(makeLine(type, obj, mLine)); - } - else if (obj.push in mLine && mLine[obj.push] != null) { - mLine[obj.push].forEach(function (el) { - sdp.push(makeLine(type, obj, el)); - }); - } - }); - }); - }); - - return sdp.join('\r\n') + '\r\n'; -}; - -},{"./grammar":10}],14:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -module.exports = function arrayEquals(array) { - // if the other array is a falsy value, return - if (!array) - return false; - - // compare lengths - can save a lot of time - if (this.length != array.length) - return false; - - for (var i = 0, l = this.length; i < l; i++) { - // Check if we have nested arrays - if (this[i] instanceof Array && array[i] instanceof Array) { - // recurse into the nested arrays - if (!arrayEquals.apply(this[i], [array[i]])) - return false; - } else if (this[i] != array[i]) { - // Warning - two different object instances will never be equal: - // {x:20} != {x:20} - return false; - } - } - return true; -}; - - -},{}],15:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -exports.Interop = require('./interop'); - -},{"./interop":16}],16:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* global RTCSessionDescription */ -/* global RTCIceCandidate */ -/* jshint -W097 */ -"use strict"; - -var transform = require('./transform'); -var arrayEquals = require('./array-equals'); - -function Interop() { - - /** - * This map holds the most recent Unified Plan offer/answer SDP that was - * converted to Plan B, with the SDP type ('offer' or 'answer') as keys and - * the SDP string as values. - * - * @type {{}} - */ - this.cache = { - mlB2UMap : {}, - mlU2BMap : {} - }; -} - -module.exports = Interop; - -/** - * Changes the candidate args to match with the related Unified Plan - */ -Interop.prototype.candidateToUnifiedPlan = function(candidate) { - var cand = new RTCIceCandidate(candidate); - - cand.sdpMLineIndex = this.cache.mlB2UMap[cand.sdpMLineIndex]; - /* TODO: change sdpMid to (audio|video)-SSRC */ - - return cand; -}; - -/** - * Changes the candidate args to match with the related Plan B - */ -Interop.prototype.candidateToPlanB = function(candidate) { - var cand = new RTCIceCandidate(candidate); - - if (cand.sdpMid.indexOf('audio') === 0) { - cand.sdpMid = 'audio'; - } else if (cand.sdpMid.indexOf('video') === 0) { - cand.sdpMid = 'video'; - } else { - throw new Error('candidate with ' + cand.sdpMid + ' not allowed'); - } - - cand.sdpMLineIndex = this.cache.mlU2BMap[cand.sdpMLineIndex]; - - return cand; -}; - -/** - * Returns the index of the first m-line with the given media type and with a - * direction which allows sending, in the last Unified Plan description with - * type "answer" converted to Plan B. Returns {null} if there is no saved - * answer, or if none of its m-lines with the given type allow sending. - * @param type the media type ("audio" or "video"). - * @returns {*} - */ -Interop.prototype.getFirstSendingIndexFromAnswer = function(type) { - if (!this.cache.answer) { - return null; - } - - var session = transform.parse(this.cache.answer); - if (session && session.media && Array.isArray(session.media)){ - for (var i = 0; i < session.media.length; i++) { - if (session.media[i].type == type && - (!session.media[i].direction /* default to sendrecv */ || - session.media[i].direction === 'sendrecv' || - session.media[i].direction === 'sendonly')){ - return i; - } - } - } - - return null; -}; - -/** - * This method transforms a Unified Plan SDP to an equivalent Plan B SDP. A - * PeerConnection wrapper transforms the SDP to Plan B before passing it to the - * application. - * - * @param desc - * @returns {*} - */ -Interop.prototype.toPlanB = function(desc) { - var self = this; - //#region Preliminary input validation. - - if (typeof desc !== 'object' || desc === null || - typeof desc.sdp !== 'string') { - console.warn('An empty description was passed as an argument.'); - return desc; - } - - // Objectify the SDP for easier manipulation. - var session = transform.parse(desc.sdp); - - // If the SDP contains no media, there's nothing to transform. - if (typeof session.media === 'undefined' || - !Array.isArray(session.media) || session.media.length === 0) { - console.warn('The description has no media.'); - return desc; - } - - // Try some heuristics to "make sure" this is a Unified Plan SDP. Plan B - // SDP has a video, an audio and a data "channel" at most. - if (session.media.length <= 3 && session.media.every(function(m) { - return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; - })) { - console.warn('This description does not look like Unified Plan.'); - return desc; - } - - //#endregion - - // HACK https://bugzilla.mozilla.org/show_bug.cgi?id=1113443 - var sdp = desc.sdp; - var rewrite = false; - for (var i = 0; i < session.media.length; i++) { - var uLine = session.media[i]; - uLine.rtp.forEach(function(rtp) { - if (rtp.codec === 'NULL') - { - rewrite = true; - var offer = transform.parse(self.cache.offer); - rtp.codec = offer.media[i].rtp[0].codec; - } - }); - } - if (rewrite) { - sdp = transform.write(session); - } - - // Unified Plan SDP is our "precious". Cache it for later use in the Plan B - // -> Unified Plan transformation. - this.cache[desc.type] = sdp; - - //#region Convert from Unified Plan to Plan B. - - // We rebuild the session.media array. - var media = session.media; - session.media = []; - - // Associative array that maps channel types to channel objects for fast - // access to channel objects by their type, e.g. type2bl['audio']->channel - // obj. - var type2bl = {}; - - // Used to build the group:BUNDLE value after the channels construction - // loop. - var types = []; - - media.forEach(function(uLine) { - // rtcp-mux is required in the Plan B SDP. - if ((typeof uLine.rtcpMux !== 'string' || - uLine.rtcpMux !== 'rtcp-mux') && - uLine.direction !== 'inactive') { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'without the rtcp-mux attribute were found.'); - } - - // If we don't have a channel for this uLine.type OR the selected is - // inactive, then select this uLine as the channel basis. - if (typeof type2bl[uLine.type] === 'undefined' || - type2bl[uLine.type].direction === 'inactive') { - type2bl[uLine.type] = uLine; - } - - if (uLine.protocol != type2bl[uLine.type].protocol) { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'have different protocols and this library does not have ' + - 'support for that'); - } - - if (uLine.payloads != type2bl[uLine.type].payloads) { - throw new Error('Cannot convert to Plan B because m-lines ' + - 'have different payloads and this library does not have ' + - 'support for that'); - } - - }); - - // Implode the Unified Plan m-lines/tracks into Plan B channels. - media.forEach(function(uLine) { - if (uLine.type === 'application') { - session.media.push(uLine); - types.push(uLine.mid); - return; - } - - // Add sources to the channel and handle a=msid. - if (typeof uLine.sources === 'object') { - Object.keys(uLine.sources).forEach(function(ssrc) { - if (typeof type2bl[uLine.type].sources !== 'object') - type2bl[uLine.type].sources = {}; - - // Assign the sources to the channel. - type2bl[uLine.type].sources[ssrc] = - uLine.sources[ssrc]; - - if (typeof uLine.msid !== 'undefined') { - // In Plan B the msid is an SSRC attribute. Also, we don't - // care about the obsolete label and mslabel attributes. - // - // Note that it is not guaranteed that the uLine will - // have an msid. recvonly channels in particular don't have - // one. - type2bl[uLine.type].sources[ssrc].msid = - uLine.msid; - } - // NOTE ssrcs in ssrc groups will share msids, as - // draft-uberti-rtcweb-plan-00 mandates. - }); - } - - // Add ssrc groups to the channel. - if (typeof uLine.ssrcGroups !== 'undefined' && - Array.isArray(uLine.ssrcGroups)) { - - // Create the ssrcGroups array, if it's not defined. - if (typeof type2bl[uLine.type].ssrcGroups === 'undefined' || - !Array.isArray(type2bl[uLine.type].ssrcGroups)) { - type2bl[uLine.type].ssrcGroups = []; - } - - type2bl[uLine.type].ssrcGroups = - type2bl[uLine.type].ssrcGroups.concat( - uLine.ssrcGroups); - } - - if (type2bl[uLine.type] === uLine) { - // Plan B mids are in ['audio', 'video', 'data'] - uLine.mid = uLine.type; - - // Plan B doesn't support/need the bundle-only attribute. - delete uLine.bundleOnly; - - // In Plan B the msid is an SSRC attribute. - delete uLine.msid; - - if (uLine.type == media[0].type) { - types.unshift(uLine.type); - // Add the channel to the new media array. - session.media.unshift(uLine); - } else { - types.push(uLine.type); - // Add the channel to the new media array. - session.media.push(uLine); - } - } - }); - - if (typeof session.groups !== 'undefined') { - // We regenerate the BUNDLE group with the new mids. - session.groups.some(function(group) { - if (group.type === 'BUNDLE') { - group.mids = types.join(' '); - return true; - } - }); - } - - // msid semantic - session.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - var resStr = transform.write(session); - - return new RTCSessionDescription({ - type: desc.type, - sdp: resStr - }); - - //#endregion -}; - -/* follow rules defined in RFC4145 */ -function addSetupAttr(uLine) { - if (typeof uLine.setup === 'undefined') { - return; - } - - if (uLine.setup === "active") { - uLine.setup = "passive"; - } else if (uLine.setup === "passive") { - uLine.setup = "active"; - } -} - -/** - * This method transforms a Plan B SDP to an equivalent Unified Plan SDP. A - * PeerConnection wrapper transforms the SDP to Unified Plan before passing it - * to FF. - * - * @param desc - * @returns {*} - */ -Interop.prototype.toUnifiedPlan = function(desc) { - var self = this; - //#region Preliminary input validation. - - if (typeof desc !== 'object' || desc === null || - typeof desc.sdp !== 'string') { - console.warn('An empty description was passed as an argument.'); - return desc; - } - - var session = transform.parse(desc.sdp); - - // If the SDP contains no media, there's nothing to transform. - if (typeof session.media === 'undefined' || - !Array.isArray(session.media) || session.media.length === 0) { - console.warn('The description has no media.'); - return desc; - } - - // Try some heuristics to "make sure" this is a Plan B SDP. Plan B SDP has - // a video, an audio and a data "channel" at most. - if (session.media.length > 3 || !session.media.every(function(m) { - return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; - })) { - console.warn('This description does not look like Plan B.'); - return desc; - } - - // Make sure this Plan B SDP can be converted to a Unified Plan SDP. - var mids = []; - session.media.forEach(function(m) { - mids.push(m.mid); - }); - - var hasBundle = false; - if (typeof session.groups !== 'undefined' && - Array.isArray(session.groups)) { - hasBundle = session.groups.every(function(g) { - return g.type !== 'BUNDLE' || - arrayEquals.apply(g.mids.sort(), [mids.sort()]); - }); - } - - if (!hasBundle) { - var mustBeBundle = false; - - session.media.forEach(function(m) { - if (m.direction !== 'inactive') { - mustBeBundle = true; - } - }); - - if (mustBeBundle) { - throw new Error("Cannot convert to Unified Plan because m-lines that" + - " are not bundled were found."); - } - } - - //#endregion - - - //#region Convert from Plan B to Unified Plan. - - // Unfortunately, a Plan B offer/answer doesn't have enough information to - // rebuild an equivalent Unified Plan offer/answer. - // - // For example, if this is a local answer (in Unified Plan style) that we - // convert to Plan B prior to handing it over to the application (the - // PeerConnection wrapper called us, for instance, after a successful - // createAnswer), we want to remember the m-line at which we've seen the - // (local) SSRC. That's because when the application wants to do call the - // SLD method, forcing us to do the inverse transformation (from Plan B to - // Unified Plan), we need to know to which m-line to assign the (local) - // SSRC. We also need to know all the other m-lines that the original - // answer had and include them in the transformed answer as well. - // - // Another example is if this is a remote offer that we convert to Plan B - // prior to giving it to the application, we want to remember the mid at - // which we've seen the (remote) SSRC. - // - // In the iteration that follows, we use the cached Unified Plan (if it - // exists) to assign mids to ssrcs. - - var type; - if (desc.type === 'answer') { - type = 'offer'; - } else if (desc.type === 'offer') { - type = 'answer'; - } else { - throw new Error("Type '" + desc.type + "' not supported."); - } - - var cached; - if (typeof this.cache[type] !== 'undefined') { - cached = transform.parse(this.cache[type]); - } - - var recvonlySsrcs = { - audio: {}, - video: {} - }; - - // A helper map that sends mids to m-line objects. We use it later to - // rebuild the Unified Plan style session.media array. - var mid2ul = {}; - var bIdx = 0; - var uIdx = 0; - - var sources2ul = {}; - - var candidates; - var iceUfrag; - var icePwd; - var fingerprint; - var payloads = {}; - var rtcpFb = {}; - var rtp = {}; - - session.media.forEach(function(bLine) { - if ((typeof bLine.rtcpMux !== 'string' || - bLine.rtcpMux !== 'rtcp-mux') && - bLine.direction !== 'inactive') { - throw new Error("Cannot convert to Unified Plan because m-lines " + - "without the rtcp-mux attribute were found."); - } - - if (bLine.type === 'application') { - mid2ul[bLine.mid] = bLine; - return; - } - - // With rtcp-mux and bundle all the channels should have the same ICE - // stuff. - var sources = bLine.sources; - var ssrcGroups = bLine.ssrcGroups; - var port = bLine.port; - - /* Chrome adds different candidates even using bundle, so we concat the candidates list */ - if (typeof bLine.candidates != 'undefined') { - if (typeof candidates != 'undefined') { - candidates = candidates.concat(bLine.candidates); - } else { - candidates = bLine.candidates; - } - } - - if ((typeof iceUfrag != 'undefined') && (typeof bLine.iceUfrag != 'undefined') && (iceUfrag != bLine.iceUfrag)) { - throw new Error("Only BUNDLE supported, iceUfrag must be the same for all m-lines.\n" + - "\tLast iceUfrag: " + iceUfrag + "\n" + - "\tNew iceUfrag: " + bLine.iceUfrag - ); - } - - if (typeof bLine.iceUfrag != 'undefined') { - iceUfrag = bLine.iceUfrag; - } - - if ((typeof icePwd != 'undefined') && (typeof bLine.icePwd != 'undefined') && (icePwd != bLine.icePwd)) { - throw new Error("Only BUNDLE supported, icePwd must be the same for all m-lines.\n" + - "\tLast icePwd: " + icePwd + "\n" + - "\tNew icePwd: " + bLine.icePwd - ); - } - - if (typeof bLine.icePwd != 'undefined') { - icePwd = bLine.icePwd; - } - - if ((typeof fingerprint != 'undefined') && (typeof bLine.fingerprint != 'undefined') && - (fingerprint.type != bLine.fingerprint.type || fingerprint.hash != bLine.fingerprint.hash)) { - throw new Error("Only BUNDLE supported, fingerprint must be the same for all m-lines.\n" + - "\tLast fingerprint: " + JSON.stringify(fingerprint) + "\n" + - "\tNew fingerprint: " + JSON.stringify(bLine.fingerprint) - ); - } - - if (typeof bLine.fingerprint != 'undefined') { - fingerprint = bLine.fingerprint; - } - - payloads[bLine.type] = bLine.payloads; - rtcpFb[bLine.type] = bLine.rtcpFb; - rtp[bLine.type] = bLine.rtp; - - // inverted ssrc group map - var ssrc2group = {}; - if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) { - ssrcGroups.forEach(function (ssrcGroup) { - // XXX This might brake if an SSRC is in more than one group - // for some reason. - if (typeof ssrcGroup.ssrcs !== 'undefined' && - Array.isArray(ssrcGroup.ssrcs)) { - ssrcGroup.ssrcs.forEach(function (ssrc) { - if (typeof ssrc2group[ssrc] === 'undefined') { - ssrc2group[ssrc] = []; - } - - ssrc2group[ssrc].push(ssrcGroup); - }); - } - }); - } - - // ssrc to m-line index. - var ssrc2ml = {}; - - if (typeof sources === 'object') { - - // We'll use the "bLine" object as a prototype for each new "mLine" - // that we create, but first we need to clean it up a bit. - delete bLine.sources; - delete bLine.ssrcGroups; - delete bLine.candidates; - delete bLine.iceUfrag; - delete bLine.icePwd; - delete bLine.fingerprint; - delete bLine.port; - delete bLine.mid; - - // Explode the Plan B channel sources with one m-line per source. - Object.keys(sources).forEach(function(ssrc) { - - // The (unified) m-line for this SSRC. We either create it from - // scratch or, if it's a grouped SSRC, we re-use a related - // mline. In other words, if the source is grouped with another - // source, put the two together in the same m-line. - var uLine; - - // We assume here that we are the answerer in the O/A, so any - // offers which we translate come from the remote side, while - // answers are local. So the check below is to make that we - // handle receive-only SSRCs in a special way only if they come - // from the remote side. - if (desc.type==='offer') { - // We want to detect SSRCs which are used by a remote peer - // in an m-line with direction=recvonly (i.e. they are - // being used for RTCP only). - // This information would have gotten lost if the remote - // peer used Unified Plan and their local description was - // translated to Plan B. So we use the lack of an MSID - // attribute to deduce a "receive only" SSRC. - if (!sources[ssrc].msid) { - recvonlySsrcs[bLine.type][ssrc] = sources[ssrc]; - // Receive-only SSRCs must not create new m-lines. We - // will assign them to an existing m-line later. - return; - } - } - - if (typeof ssrc2group[ssrc] !== 'undefined' && - Array.isArray(ssrc2group[ssrc])) { - ssrc2group[ssrc].some(function (ssrcGroup) { - // ssrcGroup.ssrcs *is* an Array, no need to check - // again here. - return ssrcGroup.ssrcs.some(function (related) { - if (typeof ssrc2ml[related] === 'object') { - uLine = ssrc2ml[related]; - return true; - } - }); - }); - } - - if (typeof uLine === 'object') { - // the m-line already exists. Just add the source. - uLine.sources[ssrc] = sources[ssrc]; - delete sources[ssrc].msid; - } else { - // Use the "bLine" as a prototype for the "uLine". - uLine = Object.create(bLine); - ssrc2ml[ssrc] = uLine; - - if (typeof sources[ssrc].msid !== 'undefined') { - // Assign the msid of the source to the m-line. Note - // that it is not guaranteed that the source will have - // msid. In particular "recvonly" sources don't have an - // msid. Note that "recvonly" is a term only defined - // for m-lines. - uLine.msid = sources[ssrc].msid; - delete sources[ssrc].msid; - } - - // We assign one SSRC per media line. - uLine.sources = {}; - uLine.sources[ssrc] = sources[ssrc]; - uLine.ssrcGroups = ssrc2group[ssrc]; - - // Use the cached Unified Plan SDP (if it exists) to assign - // SSRCs to mids. - if (typeof cached !== 'undefined' && - typeof cached.media !== 'undefined' && - Array.isArray(cached.media)) { - - cached.media.forEach(function (m) { - if (typeof m.sources === 'object') { - Object.keys(m.sources).forEach(function (s) { - if (s === ssrc) { - uLine.mid = m.mid; - } - }); - } - }); - } - - if (typeof uLine.mid === 'undefined') { - - // If this is an SSRC that we see for the first time - // assign it a new mid. This is typically the case when - // this method is called to transform a remote - // description for the first time or when there is a - // new SSRC in the remote description because a new - // peer has joined the conference. Local SSRCs should - // have already been added to the map in the toPlanB - // method. - // - // Because FF generates answers in Unified Plan style, - // we MUST already have a cached answer with all the - // local SSRCs mapped to some m-line/mid. - - uLine.mid = [bLine.type, '-', ssrc].join(''); - } - - // Include the candidates in the 1st media line. - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - uLine.port = port; - - mid2ul[uLine.mid] = uLine; - sources2ul[uIdx] = uLine.sources; - - self.cache.mlU2BMap[uIdx] = bIdx; - if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { - self.cache.mlB2UMap[bIdx] = uIdx; - } - uIdx++; - } - }); - } else { - var uLine = bLine; - - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - uLine.port = port; - - mid2ul[uLine.mid] = uLine; - - self.cache.mlU2BMap[uIdx] = bIdx; - if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { - self.cache.mlB2UMap[bIdx] = uIdx; - } - } - - bIdx++; - }); - - // Rebuild the media array in the right order and add the missing mLines - // (missing from the Plan B SDP). - session.media = []; - mids = []; // reuse - - if (desc.type === 'answer') { - - // The media lines in the answer must match the media lines in the - // offer. The order is important too. Here we assume that Firefox is - // the answerer, so we merely have to use the reconstructed (unified) - // answer to update the cached (unified) answer accordingly. - // - // In the general case, one would have to use the cached (unified) - // offer to find the m-lines that are missing from the reconstructed - // answer, potentially grabbing them from the cached (unified) answer. - // One has to be careful with this approach because inactive m-lines do - // not always have an mid, making it tricky (impossible?) to find where - // exactly and which m-lines are missing from the reconstructed answer. - - for (var i = 0; i < cached.media.length; i++) { - var uLine = cached.media[i]; - - delete uLine.msid; - delete uLine.sources; - delete uLine.ssrcGroups; - - if (typeof sources2ul[i] === 'undefined') { - if (!uLine.direction - || uLine.direction === 'sendrecv') - uLine.direction = 'recvonly'; - else if (uLine.direction === 'sendonly') - uLine.direction = 'inactive'; - } else { - if (!uLine.direction - || uLine.direction === 'sendrecv') - uLine.direction = 'sendrecv'; - else if (uLine.direction === 'recvonly') - uLine.direction = 'sendonly'; - } - - uLine.sources = sources2ul[i]; - uLine.candidates = candidates; - uLine.iceUfrag = iceUfrag; - uLine.icePwd = icePwd; - uLine.fingerprint = fingerprint; - - uLine.rtp = rtp[uLine.type]; - uLine.payloads = payloads[uLine.type]; - uLine.rtcpFb = rtcpFb[uLine.type]; - - session.media.push(uLine); - - if (typeof uLine.mid === 'string') { - // inactive lines don't/may not have an mid. - mids.push(uLine.mid); - } - } - } else { - - // SDP offer/answer (and the JSEP spec) forbids removing an m-section - // under any circumstances. If we are no longer interested in sending a - // track, we just remove the msid and ssrc attributes and set it to - // either a=recvonly (as the reofferer, we must use recvonly if the - // other side was previously sending on the m-section, but we can also - // leave the possibility open if it wasn't previously in use), or - // a=inactive. - - if (typeof cached !== 'undefined' && - typeof cached.media !== 'undefined' && - Array.isArray(cached.media)) { - cached.media.forEach(function(uLine) { - mids.push(uLine.mid); - if (typeof mid2ul[uLine.mid] !== 'undefined') { - session.media.push(mid2ul[uLine.mid]); - } else { - delete uLine.msid; - delete uLine.sources; - delete uLine.ssrcGroups; - - if (!uLine.direction - || uLine.direction === 'sendrecv') { - uLine.direction = 'sendonly'; - } - if (!uLine.direction - || uLine.direction === 'recvonly') { - uLine.direction = 'inactive'; - } - - addSetupAttr (uLine); - session.media.push(uLine); - } - }); - } - - // Add all the remaining (new) m-lines of the transformed SDP. - Object.keys(mid2ul).forEach(function(mid) { - if (mids.indexOf(mid) === -1) { - mids.push(mid); - if (mid2ul[mid].direction === 'recvonly') { - // This is a remote recvonly channel. Add its SSRC to the - // appropriate sendrecv or sendonly channel. - // TODO(gp) what if we don't have sendrecv/sendonly - // channel? - - var done = false; - - session.media.some(function (uLine) { - if ((uLine.direction === 'sendrecv' || - uLine.direction === 'sendonly') && - uLine.type === mid2ul[mid].type) { - // mid2ul[mid] shouldn't have any ssrc-groups - Object.keys(mid2ul[mid].sources).forEach( - function (ssrc) { - uLine.sources[ssrc] = - mid2ul[mid].sources[ssrc]; - }); - - done = true; - return true; - } - }); - - if (!done) { - session.media.push(mid2ul[mid]); - } - } else { - session.media.push(mid2ul[mid]); - } - } - }); - } - - // After we have constructed the Plan Unified m-lines we can figure out - // where (in which m-line) to place the 'recvonly SSRCs'. - // Note: we assume here that we are the answerer in the O/A, so any offers - // which we translate come from the remote side, while answers are local - // (and so our last local description is cached as an 'answer'). - ["audio", "video"].forEach(function (type) { - if (!session || !session.media || !Array.isArray(session.media)) - return; - - var idx = null; - if (Object.keys(recvonlySsrcs[type]).length > 0) { - idx = self.getFirstSendingIndexFromAnswer(type); - if (idx === null){ - // If this is the first offer we receive, we don't have a - // cached answer. Assume that we will be sending media using - // the first m-line for each media type. - - for (var i = 0; i < session.media.length; i++) { - if (session.media[i].type === type) { - idx = i; - break; - } - } - } - } - - if (idx && session.media.length > idx) { - var mLine = session.media[idx]; - Object.keys(recvonlySsrcs[type]).forEach(function(ssrc) { - if (mLine.sources && mLine.sources[ssrc]) { - console.warn("Replacing an existing SSRC."); - } - if (!mLine.sources) { - mLine.sources = {}; - } - - mLine.sources[ssrc] = recvonlySsrcs[type][ssrc]; - }); - } - }); - - if (typeof session.groups !== 'undefined') { - // We regenerate the BUNDLE group (since we regenerated the mids) - session.groups.some(function(group) { - if (group.type === 'BUNDLE') { - group.mids = mids.join(' '); - return true; - } - }); - } - - // msid semantic - session.msidSemantic = { - semantic: 'WMS', - token: '*' - }; - - var resStr = transform.write(session); - - // Cache the transformed SDP (Unified Plan) for later re-use in this - // function. - this.cache[desc.type] = resStr; - - return new RTCSessionDescription({ - type: desc.type, - sdp: resStr - }); - - //#endregion -}; - -},{"./array-equals":14,"./transform":17}],17:[function(require,module,exports){ -/* Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var transform = require('sdp-transform'); - -exports.write = function(session, opts) { - - if (typeof session !== 'undefined' && - typeof session.media !== 'undefined' && - Array.isArray(session.media)) { - - session.media.forEach(function (mLine) { - // expand sources to ssrcs - if (typeof mLine.sources !== 'undefined' && - Object.keys(mLine.sources).length !== 0) { - mLine.ssrcs = []; - Object.keys(mLine.sources).forEach(function (ssrc) { - var source = mLine.sources[ssrc]; - Object.keys(source).forEach(function (attribute) { - mLine.ssrcs.push({ - id: ssrc, - attribute: attribute, - value: source[attribute] - }); - }); - }); - delete mLine.sources; - } - - // join ssrcs in ssrc groups - if (typeof mLine.ssrcGroups !== 'undefined' && - Array.isArray(mLine.ssrcGroups)) { - mLine.ssrcGroups.forEach(function (ssrcGroup) { - if (typeof ssrcGroup.ssrcs !== 'undefined' && - Array.isArray(ssrcGroup.ssrcs)) { - ssrcGroup.ssrcs = ssrcGroup.ssrcs.join(' '); - } - }); - } - }); - } - - // join group mids - if (typeof session !== 'undefined' && - typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { - - session.groups.forEach(function (g) { - if (typeof g.mids !== 'undefined' && Array.isArray(g.mids)) { - g.mids = g.mids.join(' '); - } - }); - } - - return transform.write(session, opts); -}; - -exports.parse = function(sdp) { - var session = transform.parse(sdp); - - if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && - Array.isArray(session.media)) { - - session.media.forEach(function (mLine) { - // group sources attributes by ssrc - if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) { - mLine.sources = {}; - mLine.ssrcs.forEach(function (ssrc) { - if (!mLine.sources[ssrc.id]) - mLine.sources[ssrc.id] = {}; - mLine.sources[ssrc.id][ssrc.attribute] = ssrc.value; - }); - - delete mLine.ssrcs; - } - - // split ssrcs in ssrc groups - if (typeof mLine.ssrcGroups !== 'undefined' && - Array.isArray(mLine.ssrcGroups)) { - mLine.ssrcGroups.forEach(function (ssrcGroup) { - if (typeof ssrcGroup.ssrcs === 'string') { - ssrcGroup.ssrcs = ssrcGroup.ssrcs.split(' '); - } - }); - } - }); - } - // split group mids - if (typeof session !== 'undefined' && - typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { - - session.groups.forEach(function (g) { - if (typeof g.mids === 'string') { - g.mids = g.mids.split(' '); - } - }); - } - - return session; -}; - - -},{"sdp-transform":11}],18:[function(require,module,exports){ -/*! - * UAParser.js v0.7.18 - * Lightweight JavaScript-based User-Agent string parser - * https://github.com/faisalman/ua-parser-js - * - * Copyright © 2012-2016 Faisal Salman - * Dual licensed under GPLv2 or MIT - */ - -(function (window, undefined) { - - 'use strict'; - - ////////////// - // Constants - ///////////// - - - var LIBVERSION = '0.7.18', - EMPTY = '', - UNKNOWN = '?', - FUNC_TYPE = 'function', - UNDEF_TYPE = 'undefined', - OBJ_TYPE = 'object', - STR_TYPE = 'string', - MAJOR = 'major', // deprecated - MODEL = 'model', - NAME = 'name', - TYPE = 'type', - VENDOR = 'vendor', - VERSION = 'version', - ARCHITECTURE= 'architecture', - CONSOLE = 'console', - MOBILE = 'mobile', - TABLET = 'tablet', - SMARTTV = 'smarttv', - WEARABLE = 'wearable', - EMBEDDED = 'embedded'; - - - /////////// - // Helper - ////////// - - - var util = { - extend : function (regexes, extensions) { - var margedRegexes = {}; - for (var i in regexes) { - if (extensions[i] && extensions[i].length % 2 === 0) { - margedRegexes[i] = extensions[i].concat(regexes[i]); - } else { - margedRegexes[i] = regexes[i]; - } - } - return margedRegexes; - }, - has : function (str1, str2) { - if (typeof str1 === "string") { - return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; - } else { - return false; - } - }, - lowerize : function (str) { - return str.toLowerCase(); - }, - major : function (version) { - return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g,'').split(".")[0] : undefined; - }, - trim : function (str) { - return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); - } - }; - - - /////////////// - // Map helper - ////////////// - - - var mapper = { - - rgx : function (ua, arrays) { - - //var result = {}, - var i = 0, j, k, p, q, matches, match;//, args = arguments; - - /*// construct object barebones - for (p = 0; p < args[1].length; p++) { - q = args[1][p]; - result[typeof q === OBJ_TYPE ? q[0] : q] = undefined; - }*/ - - // loop through all regexes maps - while (i < arrays.length && !matches) { - - var regex = arrays[i], // even sequence (0,2,4,..) - props = arrays[i + 1]; // odd sequence (1,3,5,..) - j = k = 0; - - // try matching uastring with regexes - while (j < regex.length && !matches) { - - matches = regex[j++].exec(ua); - - if (!!matches) { - for (p = 0; p < props.length; p++) { - match = matches[++k]; - q = props[p]; - // check if given property is actually array - if (typeof q === OBJ_TYPE && q.length > 0) { - if (q.length == 2) { - if (typeof q[1] == FUNC_TYPE) { - // assign modified match - this[q[0]] = q[1].call(this, match); - } else { - // assign given value, ignore regex match - this[q[0]] = q[1]; - } - } else if (q.length == 3) { - // check whether function or regex - if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { - // call function (usually string mapper) - this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; - } else { - // sanitize match using given regex - this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; - } - } else if (q.length == 4) { - this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; - } - } else { - this[q] = match ? match : undefined; - } - } - } - } - i += 2; - } - // console.log(this); - //return this; - }, - - str : function (str, map) { - - for (var i in map) { - // check if array - if (typeof map[i] === OBJ_TYPE && map[i].length > 0) { - for (var j = 0; j < map[i].length; j++) { - if (util.has(map[i][j], str)) { - return (i === UNKNOWN) ? undefined : i; - } - } - } else if (util.has(map[i], str)) { - return (i === UNKNOWN) ? undefined : i; - } - } - return str; - } - }; - - - /////////////// - // String map - ////////////// - - - var maps = { - - browser : { - oldsafari : { - version : { - '1.0' : '/8', - '1.2' : '/1', - '1.3' : '/3', - '2.0' : '/412', - '2.0.2' : '/416', - '2.0.3' : '/417', - '2.0.4' : '/419', - '?' : '/' - } - } - }, - - device : { - amazon : { - model : { - 'Fire Phone' : ['SD', 'KF'] - } - }, - sprint : { - model : { - 'Evo Shift 4G' : '7373KT' - }, - vendor : { - 'HTC' : 'APA', - 'Sprint' : 'Sprint' - } - } - }, - - os : { - windows : { - version : { - 'ME' : '4.90', - 'NT 3.11' : 'NT3.51', - 'NT 4.0' : 'NT4.0', - '2000' : 'NT 5.0', - 'XP' : ['NT 5.1', 'NT 5.2'], - 'Vista' : 'NT 6.0', - '7' : 'NT 6.1', - '8' : 'NT 6.2', - '8.1' : 'NT 6.3', - '10' : ['NT 6.4', 'NT 10.0'], - 'RT' : 'ARM' - } - } - } - }; - - - ////////////// - // Regex map - ///////////// - - - var regexes = { - - browser : [[ - - // Presto based - /(opera\smini)\/([\w\.-]+)/i, // Opera Mini - /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet - /(opera).+version\/([\w\.]+)/i, // Opera > 9.80 - /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 - ], [NAME, VERSION], [ - - /(opios)[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0 - ], [[NAME, 'Opera Mini'], VERSION], [ - - /\s(opr)\/([\w\.]+)/i // Opera Webkit - ], [[NAME, 'Opera'], VERSION], [ - - // Mixed - /(kindle)\/([\w\.]+)/i, // Kindle - /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]*)/i, - // Lunascape/Maxthon/Netfront/Jasmine/Blazer - - // Trident based - /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i, - // Avant/IEMobile/SlimBrowser/Baidu - /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer - - // Webkit/KHTML based - /(rekonq)\/([\w\.]*)/i, // Rekonq - /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark)\/([\w\.-]+)/i - // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser - ], [NAME, VERSION], [ - - /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11 - ], [[NAME, 'IE'], VERSION], [ - - /(edge|edgios|edgea)\/((\d+)?[\w\.]+)/i // Microsoft Edge - ], [[NAME, 'Edge'], VERSION], [ - - /(yabrowser)\/([\w\.]+)/i // Yandex - ], [[NAME, 'Yandex'], VERSION], [ - - /(puffin)\/([\w\.]+)/i // Puffin - ], [[NAME, 'Puffin'], VERSION], [ - - /((?:[\s\/])uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i - // UCBrowser - ], [[NAME, 'UCBrowser'], VERSION], [ - - /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon - ], [[NAME, /_/g, ' '], VERSION], [ - - /(micromessenger)\/([\w\.]+)/i // WeChat - ], [[NAME, 'WeChat'], VERSION], [ - - /(qqbrowserlite)\/([\w\.]+)/i // QQBrowserLite - ], [NAME, VERSION], [ - - /(QQ)\/([\d\.]+)/i // QQ, aka ShouQ - ], [NAME, VERSION], [ - - /m?(qqbrowser)[\/\s]?([\w\.]+)/i // QQBrowser - ], [NAME, VERSION], [ - - /(BIDUBrowser)[\/\s]?([\w\.]+)/i // Baidu Browser - ], [NAME, VERSION], [ - - /(2345Explorer)[\/\s]?([\w\.]+)/i // 2345 Browser - ], [NAME, VERSION], [ - - /(MetaSr)[\/\s]?([\w\.]+)/i // SouGouBrowser - ], [NAME], [ - - /(LBBROWSER)/i // LieBao Browser - ], [NAME], [ - - /xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser - ], [VERSION, [NAME, 'MIUI Browser']], [ - - /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android - ], [VERSION, [NAME, 'Facebook']], [ - - /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless - ], [VERSION, [NAME, 'Chrome Headless']], [ - - /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView - ], [[NAME, /(.+)/, '$1 WebView'], VERSION], [ - - /((?:oculus|samsung)browser)\/([\w\.]+)/i - ], [[NAME, /(.+(?:g|us))(.+)/, '$1 $2'], VERSION], [ // Oculus / Samsung Browser - - /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)*/i // Android Browser - ], [VERSION, [NAME, 'Android Browser']], [ - - /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i - // Chrome/OmniWeb/Arora/Tizen/Nokia - ], [NAME, VERSION], [ - - /(dolfin)\/([\w\.]+)/i // Dolphin - ], [[NAME, 'Dolphin'], VERSION], [ - - /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS - ], [[NAME, 'Chrome'], VERSION], [ - - /(coast)\/([\w\.]+)/i // Opera Coast - ], [[NAME, 'Opera Coast'], VERSION], [ - - /fxios\/([\w\.-]+)/i // Firefox for iOS - ], [VERSION, [NAME, 'Firefox']], [ - - /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari - ], [VERSION, [NAME, 'Mobile Safari']], [ - - /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile - ], [VERSION, NAME], [ - - /webkit.+?(gsa)\/([\w\.]+).+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Google Search Appliance on iOS - ], [[NAME, 'GSA'], VERSION], [ - - /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 - ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [ - - /(konqueror)\/([\w\.]+)/i, // Konqueror - /(webkit|khtml)\/([\w\.]+)/i - ], [NAME, VERSION], [ - - // Gecko based - /(navigator|netscape)\/([\w\.-]+)/i // Netscape - ], [[NAME, 'Netscape'], VERSION], [ - /(swiftfox)/i, // Swiftfox - /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i, - // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror - /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([\w\.-]+)$/i, - - // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix - /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla - - // Other - /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i, - // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir - /(links)\s\(([\w\.]+)/i, // Links - /(gobrowser)\/?([\w\.]*)/i, // GoBrowser - /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser - /(mosaic)[\/\s]([\w\.]+)/i // Mosaic - ], [NAME, VERSION] - - /* ///////////////////// - // Media players BEGIN - //////////////////////// - - , [ - - /(apple(?:coremedia|))\/((\d+)[\w\._]+)/i, // Generic Apple CoreMedia - /(coremedia) v((\d+)[\w\._]+)/i - ], [NAME, VERSION], [ - - /(aqualung|lyssna|bsplayer)\/((\d+)?[\w\.-]+)/i // Aqualung/Lyssna/BSPlayer - ], [NAME, VERSION], [ - - /(ares|ossproxy)\s((\d+)[\w\.-]+)/i // Ares/OSSProxy - ], [NAME, VERSION], [ - - /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/((\d+)[\w\.-]+)/i, - // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC - // NSPlayer/PSP-InternetRadioPlayer/Videos - /(clementine|music player daemon)\s((\d+)[\w\.-]+)/i, // Clementine/MPD - /(lg player|nexplayer)\s((\d+)[\d\.]+)/i, - /player\/(nexplayer|lg player)\s((\d+)[\w\.-]+)/i // NexPlayer/LG Player - ], [NAME, VERSION], [ - /(nexplayer)\s((\d+)[\w\.-]+)/i // Nexplayer - ], [NAME, VERSION], [ - - /(flrp)\/((\d+)[\w\.-]+)/i // Flip Player - ], [[NAME, 'Flip Player'], VERSION], [ - - /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i - // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit - ], [NAME], [ - - /(gstreamer) souphttpsrc (?:\([^\)]+\)){0,1} libsoup\/((\d+)[\w\.-]+)/i - // Gstreamer - ], [NAME, VERSION], [ - - /(htc streaming player)\s[\w_]+\s\/\s((\d+)[\d\.]+)/i, // HTC Streaming Player - /(java|python-urllib|python-requests|wget|libcurl)\/((\d+)[\w\.-_]+)/i, - // Java/urllib/requests/wget/cURL - /(lavf)((\d+)[\d\.]+)/i // Lavf (FFMPEG) - ], [NAME, VERSION], [ - - /(htc_one_s)\/((\d+)[\d\.]+)/i // HTC One S - ], [[NAME, /_/g, ' '], VERSION], [ - - /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+){0,1})/i - // MPlayer SVN - ], [NAME, VERSION], [ - - /(mplayer)(?:\s|\/|[unkow-]+)((\d+)[\w\.-]+)/i // MPlayer - ], [NAME, VERSION], [ - - /(mplayer)/i, // MPlayer (no other info) - /(yourmuze)/i, // YourMuze - /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime - ], [NAME], [ - - /(nero (?:home|scout))\/((\d+)[\w\.-]+)/i // Nero Home/Nero Scout - ], [NAME, VERSION], [ - - /(nokia\d+)\/((\d+)[\w\.-]+)/i // Nokia - ], [NAME, VERSION], [ - - /\s(songbird)\/((\d+)[\w\.-]+)/i // Songbird/Philips-Songbird - ], [NAME, VERSION], [ - - /(winamp)3 version ((\d+)[\w\.-]+)/i, // Winamp - /(winamp)\s((\d+)[\w\.-]+)/i, - /(winamp)mpeg\/((\d+)[\w\.-]+)/i - ], [NAME, VERSION], [ - - /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) - // inlight radio - ], [NAME], [ - - /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/((\d+)[\w\.-]+)/i - // QuickTime/RealMedia/RadioApp/RadioClientApplication/ - // SoundTap/Totem/Stagefright/Streamium - ], [NAME, VERSION], [ - - /(smp)((\d+)[\d\.]+)/i // SMP - ], [NAME, VERSION], [ - - /(vlc) media player - version ((\d+)[\w\.]+)/i, // VLC Videolan - /(vlc)\/((\d+)[\w\.-]+)/i, - /(xbmc|gvfs|xine|xmms|irapp)\/((\d+)[\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp - /(foobar2000)\/((\d+)[\d\.]+)/i, // Foobar2000 - /(itunes)\/((\d+)[\d\.]+)/i // iTunes - ], [NAME, VERSION], [ - - /(wmplayer)\/((\d+)[\w\.-]+)/i, // Windows Media Player - /(windows-media-player)\/((\d+)[\w\.-]+)/i - ], [[NAME, /-/g, ' '], VERSION], [ - - /windows\/((\d+)[\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i - // Windows Media Server - ], [VERSION, [NAME, 'Windows']], [ - - /(com\.riseupradioalarm)\/((\d+)[\d\.]*)/i // RiseUP Radio Alarm - ], [NAME, VERSION], [ - - /(rad.io)\s((\d+)[\d\.]+)/i, // Rad.io - /(radio.(?:de|at|fr))\s((\d+)[\d\.]+)/i - ], [[NAME, 'rad.io'], VERSION] - - ////////////////////// - // Media players END - ////////////////////*/ - - ], - - cpu : [[ - - /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 - ], [[ARCHITECTURE, 'amd64']], [ - - /(ia32(?=;))/i // IA32 (quicktime) - ], [[ARCHITECTURE, util.lowerize]], [ - - /((?:i[346]|x)86)[;\)]/i // IA32 - ], [[ARCHITECTURE, 'ia32']], [ - - // PocketPC mistakenly identified as PowerPC - /windows\s(ce|mobile);\sppc;/i - ], [[ARCHITECTURE, 'arm']], [ - - /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC - ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [ - - /(sun4\w)[;\)]/i // SPARC - ], [[ARCHITECTURE, 'sparc']], [ - - /((?:avr32|ia64(?=;))|68k(?=\))|arm(?:64|(?=v\d+;))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)/i - // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC - ], [[ARCHITECTURE, util.lowerize]] - ], - - device : [[ - - /\((ipad|playbook);[\w\s\);-]+(rim|apple)/i // iPad/PlayBook - ], [MODEL, VENDOR, [TYPE, TABLET]], [ - - /applecoremedia\/[\w\.]+ \((ipad)/ // iPad - ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ - - /(apple\s{0,1}tv)/i // Apple TV - ], [[MODEL, 'Apple TV'], [VENDOR, 'Apple']], [ - - /(archos)\s(gamepad2?)/i, // Archos - /(hp).+(touchpad)/i, // HP TouchPad - /(hp).+(tablet)/i, // HP Tablet - /(kindle)\/([\w\.]+)/i, // Kindle - /\s(nook)[\w\s]+build\/(\w+)/i, // Nook - /(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /(kf[A-z]+)\sbuild\/.+silk\//i // Kindle Fire HD - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ - /(sd|kf)[0349hijorstuw]+\sbuild\/.+silk\//i // Fire Phone - ], [[MODEL, mapper.str, maps.device.amazon.model], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ - - /\((ip[honed|\s\w*]+);.+(apple)/i // iPod/iPhone - ], [MODEL, VENDOR, [TYPE, MOBILE]], [ - /\((ip[honed|\s\w*]+);/i // iPod/iPhone - ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ - - /(blackberry)[\s-]?(\w+)/i, // BlackBerry - /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]*)/i, - // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron - /(hp)\s([\w\s]+\w)/i, // HP iPAQ - /(asus)-?(\w+)/i // Asus - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /\(bb10;\s(\w+)/i // BlackBerry 10 - ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ - // Asus Tablets - /android.+(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7|padfone)/i - ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [ - - /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony - /(sony)?(?:sgp.+)\sbuild\//i - ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [ - /android.+\s([c-g]\d{4}|so[-l]\w+)\sbuild\//i - ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - - /\s(ouya)\s/i, // Ouya - /(nintendo)\s([wids3u]+)/i // Nintendo - ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ - - /android.+;\s(shield)\sbuild/i // Nvidia - ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ - - /(playstation\s[34portablevi]+)/i // Playstation - ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ - - /(sprint\s(\w+))/i // Sprint Phones - ], [[VENDOR, mapper.str, maps.device.sprint.vendor], [MODEL, mapper.str, maps.device.sprint.model], [TYPE, MOBILE]], [ - - /(lenovo)\s?(S(?:5000|6000)+(?:[-][\w+]))/i // Lenovo tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC - /(zte)-(\w*)/i, // ZTE - /(alcatel|geeksphone|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]*)/i - // Alcatel/GeeksPhone/Lenovo/Nexian/Panasonic/Sony - ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ - - /(nexus\s9)/i // HTC Nexus 9 - ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ - - /d\/huawei([\w\s-]+)[;\)]/i, - /(nexus\s6p)/i // Huawei - ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ - - /(microsoft);\s(lumia[\s\w]+)/i // Microsoft Lumia - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /[\s\(;](xbox(?:\sone)?)[\s\);]/i // Microsoft Xbox - ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [ - /(kin\.[onetw]{3})/i // Microsoft Kin - ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ - - // Motorola - /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?:?(\s4g)?)[\w\s]+build\//i, - /mot[\s-]?(\w*)/i, - /(XT\d{3,4}) build\//i, - /(nexus\s6)/i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ - /android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i - ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [ - - /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices - ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ - - /hbbtv.+maple;(\d+)/i - ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [ - - /\(dtv[\);].+(aquos)/i // Sharp - ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [ - - /android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10))/i, - /((SM-T\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung - /smart-tv.+(samsung)/i - ], [VENDOR, [TYPE, SMARTTV], MODEL], [ - /((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+))/i, - /(sam[sung]*)[\s-]*(\w+-?[\w-]*)/i, - /sec-((sgh\w+))/i - ], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [ - - /sie-(\w*)/i // Siemens - ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ - - /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia - /(nokia)[\s_-]?([\w-]*)/i - ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [ - - /android\s3\.[\s\w;-]{10}(a\d{3})/i // Acer - ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ - - /android.+([vl]k\-?\d{3})\s+build/i // LG Tablet - ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [ - /android\s3\.[\s\w;-]{10}(lg?)-([06cv9]{3,4})/i // LG Tablet - ], [[VENDOR, 'LG'], MODEL, [TYPE, TABLET]], [ - /(lg) netcast\.tv/i // LG SmartTV - ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ - /(nexus\s[45])/i, // LG - /lg[e;\s\/-]+(\w*)/i, - /android.+lg(\-?[\d\w]+)\s+build/i - ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [ - - /android.+(ideatab[a-z0-9\-\s]+)/i // Lenovo - ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ - - /linux;.+((jolla));/i // Jolla - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /((pebble))app\/[\d\.]+\s/i // Pebble - ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ - - /android.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - - /crkey/i // Google Chromecast - ], [[MODEL, 'Chromecast'], [VENDOR, 'Google']], [ - - /android.+;\s(glass)\s\d/i // Google Glass - ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [ - - /android.+;\s(pixel c)\s/i // Google Pixel C - ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ - - /android.+;\s(pixel xl|pixel)\s/i // Google Pixel - ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ - - /android.+;\s(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models - /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi - /android.+(mi[\s\-_]*(?:one|one[\s_]plus|note lte)?[\s_]*(?:\d?\w?)[\s_]*(?:plus)?)\s+build/i, // Xiaomi Mi - /android.+(redmi[\s\-_]*(?:note)?(?:[\s_]*[\w\s]+))\s+build/i // Redmi Phones - ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ - /android.+(mi[\s\-_]*(?:pad)(?:[\s_]*[\w\s]+))\s+build/i // Mi Pad tablets - ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ - /android.+;\s(m[1-5]\snote)\sbuild/i // Meizu Tablet - ], [MODEL, [VENDOR, 'Meizu'], [TYPE, TABLET]], [ - - /android.+a000(1)\s+build/i, // OnePlus - /android.+oneplus\s(a\d{4})\s+build/i - ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(RCT[\d\w]+)\s+build/i // RCA Tablets - ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ - - /android.+[;\/\s]+(Venue[\d\s]{2,7})\s+build/i // Dell Venue Tablets - ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Q[T|M][\d\w]+)\s+build/i // Verizon Tablet - ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ - - /android.+[;\/]\s+(Barnes[&\s]+Noble\s+|BN[RT])(V?.*)\s+build/i // Barnes & Noble Tablet - ], [[VENDOR, 'Barnes & Noble'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s+(TM\d{3}.*\b)\s+build/i // Barnes & Noble Tablet - ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ - - /android.+;\s(k88)\sbuild/i // ZTE K Series Tablet - ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(gen\d{3})\s+build.*49h/i // Swiss GEN Mobile - ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(zur\d{3})\s+build/i // Swiss ZUR Tablet - ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((Zeki)?TB.*\b)\s+build/i // Zeki Tablets - ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ - - /(android).+[;\/]\s+([YR]\d{2})\s+build/i, - /android.+[;\/]\s+(Dragon[\-\s]+Touch\s+|DT)(\w{5})\sbuild/i // Dragon Touch Tablet - ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*(NS-?\w{0,9})\sbuild/i // Insignia Tablets - ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*((NX|Next)-?\w{0,9})\s+build/i // NextBook Tablets - ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Xtreme\_)?(V(1[045]|2[015]|30|40|60|7[05]|90))\s+build/i - ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones - - /android.+[;\/]\s*(LVTEL\-)?(V1[12])\s+build/i // LvTel Phones - ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ - - /android.+[;\/]\s*(V(100MD|700NA|7011|917G).*\b)\s+build/i // Envizen Tablets - ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Le[\s\-]+Pan)[\s\-]+(\w{1,9})\s+build/i // Le Pan Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Trio[\s\-]*.*)\s+build/i // MachSpeed Tablets - ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ - - /android.+[;\/]\s*(Trinity)[\-\s]*(T\d{3})\s+build/i // Trinity Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /android.+[;\/]\s*TU_(1491)\s+build/i // Rotor Tablets - ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ - - /android.+(KS(.+))\s+build/i // Amazon Kindle Tablets - ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ - - /android.+(Gigaset)[\s\-]+(Q\w{1,9})\s+build/i // Gigaset Tablets - ], [VENDOR, MODEL, [TYPE, TABLET]], [ - - /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet - /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile - ], [[TYPE, util.lowerize], VENDOR, MODEL], [ - - /(android[\w\.\s\-]{0,9});.+build/i // Generic Android Device - ], [MODEL, [VENDOR, 'Generic']] - - - /*////////////////////////// - // TODO: move to string map - //////////////////////////// - - /(C6603)/i // Sony Xperia Z C6603 - ], [[MODEL, 'Xperia Z C6603'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - /(C6903)/i // Sony Xperia Z 1 - ], [[MODEL, 'Xperia Z 1'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ - - /(SM-G900[F|H])/i // Samsung Galaxy S5 - ], [[MODEL, 'Galaxy S5'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G7102)/i // Samsung Galaxy Grand 2 - ], [[MODEL, 'Galaxy Grand 2'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G530H)/i // Samsung Galaxy Grand Prime - ], [[MODEL, 'Galaxy Grand Prime'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-G313HZ)/i // Samsung Galaxy V - ], [[MODEL, 'Galaxy V'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-T805)/i // Samsung Galaxy Tab S 10.5 - ], [[MODEL, 'Galaxy Tab S 10.5'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ - /(SM-G800F)/i // Samsung Galaxy S5 Mini - ], [[MODEL, 'Galaxy S5 Mini'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ - /(SM-T311)/i // Samsung Galaxy Tab 3 8.0 - ], [[MODEL, 'Galaxy Tab 3 8.0'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ - - /(T3C)/i // Advan Vandroid T3C - ], [MODEL, [VENDOR, 'Advan'], [TYPE, TABLET]], [ - /(ADVAN T1J\+)/i // Advan Vandroid T1J+ - ], [[MODEL, 'Vandroid T1J+'], [VENDOR, 'Advan'], [TYPE, TABLET]], [ - /(ADVAN S4A)/i // Advan Vandroid S4A - ], [[MODEL, 'Vandroid S4A'], [VENDOR, 'Advan'], [TYPE, MOBILE]], [ - - /(V972M)/i // ZTE V972M - ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [ - - /(i-mobile)\s(IQ\s[\d\.]+)/i // i-mobile IQ - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /(IQ6.3)/i // i-mobile IQ IQ 6.3 - ], [[MODEL, 'IQ 6.3'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ - /(i-mobile)\s(i-style\s[\d\.]+)/i // i-mobile i-STYLE - ], [VENDOR, MODEL, [TYPE, MOBILE]], [ - /(i-STYLE2.1)/i // i-mobile i-STYLE 2.1 - ], [[MODEL, 'i-STYLE 2.1'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ - - /(mobiistar touch LAI 512)/i // mobiistar touch LAI 512 - ], [[MODEL, 'Touch LAI 512'], [VENDOR, 'mobiistar'], [TYPE, MOBILE]], [ - - ///////////// - // END TODO - ///////////*/ - - ], - - engine : [[ - - /windows.+\sedge\/([\w\.]+)/i // EdgeHTML - ], [VERSION, [NAME, 'EdgeHTML']], [ - - /(presto)\/([\w\.]+)/i, // Presto - /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m - /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links - /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab - ], [NAME, VERSION], [ - - /rv\:([\w\.]{1,9}).+(gecko)/i // Gecko - ], [VERSION, NAME] - ], - - os : [[ - - // Windows based - /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes) - ], [NAME, VERSION], [ - /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT - /(windows\sphone(?:\sos)*)[\s\/]?([\d\.\s\w]*)/i, // Windows Phone - /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i - ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ - /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i - ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ - - // Mobile/Embedded OS - /\((bb)(10);/i // BlackBerry 10 - ], [[NAME, 'BlackBerry'], VERSION], [ - /(blackberry)\w*\/?([\w\.]*)/i, // Blackberry - /(tizen)[\/\s]([\w\.]+)/i, // Tizen - /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]*)/i, - // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki - /linux;.+(sailfish);/i // Sailfish OS - ], [NAME, VERSION], [ - /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]*)/i // Symbian - ], [[NAME, 'Symbian'], VERSION], [ - /\((series40);/i // Series 40 - ], [NAME], [ - /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS - ], [[NAME, 'Firefox OS'], VERSION], [ - - // Console - /(nintendo|playstation)\s([wids34portablevu]+)/i, // Nintendo/Playstation - - // GNU/Linux based - /(mint)[\/\s\(]?(\w*)/i, // Mint - /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux - /(joli|[kxln]?ubuntu|debian|suse|opensuse|gentoo|(?=\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?(?!chrom)([\w\.-]*)/i, - // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware - // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus - /(hurd|linux)\s?([\w\.]*)/i, // Hurd/Linux - /(gnu)\s?([\w\.]*)/i // GNU - ], [NAME, VERSION], [ - - /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS - ], [[NAME, 'Chromium OS'], VERSION],[ - - // Solaris - /(sunos)\s?([\w\.\d]*)/i // Solaris - ], [[NAME, 'Solaris'], VERSION], [ - - // BSD based - /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]*)/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly - ], [NAME, VERSION],[ - - /(haiku)\s(\w+)/i // Haiku - ], [NAME, VERSION],[ - - /cfnetwork\/.+darwin/i, - /ip[honead]{2,4}(?:.*os\s([\w]+)\slike\smac|;\sopera)/i // iOS - ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ - - /(mac\sos\sx)\s?([\w\s\.]*)/i, - /(macintosh|mac(?=_powerpc)\s)/i // Mac OS - ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ - - // Other - /((?:open)?solaris)[\/\s-]?([\w\.]*)/i, // Solaris - /(aix)\s((\d)(?=\.|\)|\s)[\w\.])*/i, // AIX - /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i, - // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS - /(unix)\s?([\w\.]*)/i // UNIX - ], [NAME, VERSION] - ] - }; - - - ///////////////// - // Constructor - //////////////// - /* - var Browser = function (name, version) { - this[NAME] = name; - this[VERSION] = version; - }; - var CPU = function (arch) { - this[ARCHITECTURE] = arch; - }; - var Device = function (vendor, model, type) { - this[VENDOR] = vendor; - this[MODEL] = model; - this[TYPE] = type; - }; - var Engine = Browser; - var OS = Browser; - */ - var UAParser = function (uastring, extensions) { - - if (typeof uastring === 'object') { - extensions = uastring; - uastring = undefined; - } - - if (!(this instanceof UAParser)) { - return new UAParser(uastring, extensions).getResult(); - } - - var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); - var rgxmap = extensions ? util.extend(regexes, extensions) : regexes; - //var browser = new Browser(); - //var cpu = new CPU(); - //var device = new Device(); - //var engine = new Engine(); - //var os = new OS(); - - this.getBrowser = function () { - var browser = { name: undefined, version: undefined }; - mapper.rgx.call(browser, ua, rgxmap.browser); - browser.major = util.major(browser.version); // deprecated - return browser; - }; - this.getCPU = function () { - var cpu = { architecture: undefined }; - mapper.rgx.call(cpu, ua, rgxmap.cpu); - return cpu; - }; - this.getDevice = function () { - var device = { vendor: undefined, model: undefined, type: undefined }; - mapper.rgx.call(device, ua, rgxmap.device); - return device; - }; - this.getEngine = function () { - var engine = { name: undefined, version: undefined }; - mapper.rgx.call(engine, ua, rgxmap.engine); - return engine; - }; - this.getOS = function () { - var os = { name: undefined, version: undefined }; - mapper.rgx.call(os, ua, rgxmap.os); - return os; - }; - this.getResult = function () { - return { - ua : this.getUA(), - browser : this.getBrowser(), - engine : this.getEngine(), - os : this.getOS(), - device : this.getDevice(), - cpu : this.getCPU() - }; - }; - this.getUA = function () { - return ua; - }; - this.setUA = function (uastring) { - ua = uastring; - //browser = new Browser(); - //cpu = new CPU(); - //device = new Device(); - //engine = new Engine(); - //os = new OS(); - return this; - }; - return this; - }; - - UAParser.VERSION = LIBVERSION; - UAParser.BROWSER = { - NAME : NAME, - MAJOR : MAJOR, // deprecated - VERSION : VERSION - }; - UAParser.CPU = { - ARCHITECTURE : ARCHITECTURE - }; - UAParser.DEVICE = { - MODEL : MODEL, - VENDOR : VENDOR, - TYPE : TYPE, - CONSOLE : CONSOLE, - MOBILE : MOBILE, - SMARTTV : SMARTTV, - TABLET : TABLET, - WEARABLE: WEARABLE, - EMBEDDED: EMBEDDED - }; - UAParser.ENGINE = { - NAME : NAME, - VERSION : VERSION - }; - UAParser.OS = { - NAME : NAME, - VERSION : VERSION - }; - //UAParser.Utils = util; - - /////////// - // Export - ////////// - - - // check js environment - if (typeof(exports) !== UNDEF_TYPE) { - // nodejs env - if (typeof module !== UNDEF_TYPE && module.exports) { - exports = module.exports = UAParser; - } - // TODO: test!!!!!!!! - /* - if (require && require.main === module && process) { - // cli - var jsonize = function (arr) { - var res = []; - for (var i in arr) { - res.push(new UAParser(arr[i]).getResult()); - } - process.stdout.write(JSON.stringify(res, null, 2) + '\n'); - }; - if (process.stdin.isTTY) { - // via args - jsonize(process.argv.slice(2)); - } else { - // via pipe - var str = ''; - process.stdin.on('readable', function() { - var read = process.stdin.read(); - if (read !== null) { - str += read; - } - }); - process.stdin.on('end', function () { - jsonize(str.replace(/\n$/, '').split('\n')); - }); - } - } - */ - exports.UAParser = UAParser; - } else { - // requirejs env (optional) - if (typeof(define) === FUNC_TYPE && define.amd) { - define(function () { - return UAParser; - }); - } else if (window) { - // browser env - window.UAParser = UAParser; - } - } - - // jQuery/Zepto specific (optional) - // Note: - // In AMD env the global scope should be kept clean, but jQuery is an exception. - // jQuery always exports to global scope, unless jQuery.noConflict(true) is used, - // and we should catch that. - var $ = window && (window.jQuery || window.Zepto); - if (typeof $ !== UNDEF_TYPE) { - var parser = new UAParser(); - $.ua = parser.getResult(); - $.ua.get = function () { - return parser.getUA(); - }; - $.ua.set = function (uastring) { - parser.setUA(uastring); - var result = parser.getResult(); - for (var prop in result) { - $.ua[prop] = result[prop]; - } - }; - } - -})(typeof window === 'object' ? window : this); - -},{}],19:[function(require,module,exports){ -var v1 = require('./v1'); -var v4 = require('./v4'); - -var uuid = v4; -uuid.v1 = v1; -uuid.v4 = v4; - -module.exports = uuid; - -},{"./v1":22,"./v4":23}],20:[function(require,module,exports){ -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = []; -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1); -} - -function bytesToUuid(buf, offset) { - var i = offset || 0; - var bth = byteToHex; - return bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]]; -} - -module.exports = bytesToUuid; - -},{}],21:[function(require,module,exports){ -// Unique ID creation requires a high quality random # generator. In the -// browser this is a little complicated due to unknown quality of Math.random() -// and inconsistent support for the `crypto` API. We do the best we can via -// feature-detection - -// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. -var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) || - (typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto)); -if (getRandomValues) { - // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto - var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef - - module.exports = function whatwgRNG() { - getRandomValues(rnds8); - return rnds8; - }; -} else { - // Math.random()-based (RNG) - // - // If all else fails, use Math.random(). It's fast, but is of unspecified - // quality. - var rnds = new Array(16); - - module.exports = function mathRNG() { - for (var i = 0, r; i < 16; i++) { - if ((i & 0x03) === 0) r = Math.random() * 0x100000000; - rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; - } - - return rnds; - }; -} - -},{}],22:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); - -// **`v1()` - Generate time-based UUID** -// -// Inspired by https://github.com/LiosK/UUID.js -// and http://docs.python.org/library/uuid.html - -var _nodeId; -var _clockseq; - -// Previous uuid creation time -var _lastMSecs = 0; -var _lastNSecs = 0; - -// See https://github.com/broofa/node-uuid for API details -function v1(options, buf, offset) { - var i = buf && offset || 0; - var b = buf || []; - - options = options || {}; - var node = options.node || _nodeId; - var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; - - // node and clockseq need to be initialized to random values if they're not - // specified. We do this lazily to minimize issues related to insufficient - // system entropy. See #189 - if (node == null || clockseq == null) { - var seedBytes = rng(); - if (node == null) { - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - node = _nodeId = [ - seedBytes[0] | 0x01, - seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] - ]; - } - if (clockseq == null) { - // Per 4.2.2, randomize (14 bit) clockseq - clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; - } - } - - // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); - - // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; - - // Time since last uuid creation (in msecs) - var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; - - // Per 4.2.1.2, Bump clockseq on clock regression - if (dt < 0 && options.clockseq === undefined) { - clockseq = clockseq + 1 & 0x3fff; - } - - // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { - nsecs = 0; - } - - // Per 4.2.1.2 Throw error if too many uuids are requested - if (nsecs >= 10000) { - throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; - - // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - msecs += 12219292800000; - - // `time_low` - var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; - - // `time_mid` - var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; - - // `time_high_and_version` - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - b[i++] = tmh >>> 16 & 0xff; - - // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - b[i++] = clockseq >>> 8 | 0x80; - - // `clock_seq_low` - b[i++] = clockseq & 0xff; - - // `node` - for (var n = 0; n < 6; ++n) { - b[i + n] = node[n]; - } - - return buf ? buf : bytesToUuid(b); -} - -module.exports = v1; - -},{"./lib/bytesToUuid":20,"./lib/rng":21}],23:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); - -function v4(options, buf, offset) { - var i = buf && offset || 0; - - if (typeof(options) == 'string') { - buf = options === 'binary' ? new Array(16) : null; - options = null; - } - options = options || {}; - - var rnds = options.random || (options.rng || rng)(); - - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = (rnds[6] & 0x0f) | 0x40; - rnds[8] = (rnds[8] & 0x3f) | 0x80; - - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ++ii) { - buf[i + ii] = rnds[ii]; - } - } - - return buf || bytesToUuid(rnds); -} - -module.exports = v4; - -},{"./lib/bytesToUuid":20,"./lib/rng":21}],24:[function(require,module,exports){ -/* -WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based -on @visionmedia's Emitter from UI Kit. - -Why? I wanted it standalone. - -I also wanted support for wildcard emitters like this: - -emitter.on('*', function (eventName, other, event, payloads) { - -}); - -emitter.on('somenamespace*', function (eventName, payloads) { - -}); - -Please note that callbacks triggered by wildcard registered events also get -the event name as the first argument. -*/ - -module.exports = WildEmitter; - -function WildEmitter() { } - -WildEmitter.mixin = function (constructor) { - var prototype = constructor.prototype || constructor; - - prototype.isWildEmitter= true; - - // Listen on the given `event` with `fn`. Store a group name if present. - prototype.on = function (event, groupName, fn) { - this.callbacks = this.callbacks || {}; - var hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - func._groupName = group; - (this.callbacks[event] = this.callbacks[event] || []).push(func); - return this; - }; - - // Adds an `event` listener that will be invoked a single - // time then automatically removed. - prototype.once = function (event, groupName, fn) { - var self = this, - hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - function on() { - self.off(event, on); - func.apply(this, arguments); - } - this.on(event, group, on); - return this; - }; - - // Unbinds an entire group - prototype.releaseGroup = function (groupName) { - this.callbacks = this.callbacks || {}; - var item, i, len, handlers; - for (item in this.callbacks) { - handlers = this.callbacks[item]; - for (i = 0, len = handlers.length; i < len; i++) { - if (handlers[i]._groupName === groupName) { - //console.log('removing'); - // remove it and shorten the array we're looping through - handlers.splice(i, 1); - i--; - len--; - } - } - } - return this; - }; - - // Remove the given callback for `event` or all - // registered callbacks. - prototype.off = function (event, fn) { - this.callbacks = this.callbacks || {}; - var callbacks = this.callbacks[event], - i; - - if (!callbacks) return this; - - // remove all handlers - if (arguments.length === 1) { - delete this.callbacks[event]; - return this; - } - - // remove specific handler - i = callbacks.indexOf(fn); - callbacks.splice(i, 1); - if (callbacks.length === 0) { - delete this.callbacks[event]; - } - return this; - }; - - /// Emit `event` with the given args. - // also calls any `*` handlers - prototype.emit = function (event) { - this.callbacks = this.callbacks || {}; - var args = [].slice.call(arguments, 1), - callbacks = this.callbacks[event], - specialCallbacks = this.getWildcardCallbacks(event), - i, - len, - item, - listeners; - - if (callbacks) { - listeners = callbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, args); - } - } - - if (specialCallbacks) { - len = specialCallbacks.length; - listeners = specialCallbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, [event].concat(args)); - } - } - - return this; - }; - - // Helper for for finding special wildcard event handlers that match the event - prototype.getWildcardCallbacks = function (eventName) { - this.callbacks = this.callbacks || {}; - var item, - split, - result = []; - - for (item in this.callbacks) { - split = item.split('*'); - if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { - result = result.concat(this.callbacks[item]); - } - } - return result; - }; - -}; - -WildEmitter.mixin(WildEmitter); - -},{}],25:[function(require,module,exports){ -/*! - * EventEmitter v5.2.4 - git.io/ee - * Unlicense - http://unlicense.org/ - * Oliver Caldwell - http://oli.me.uk/ - * @preserve - */ - -;(function (exports) { - 'use strict'; - - /** - * Class for managing events. - * Can be extended to provide event functionality in other classes. - * - * @class EventEmitter Manages event registering and emitting. - */ - function EventEmitter() {} - - // Shortcuts to improve speed and size - var proto = EventEmitter.prototype; - var originalGlobalValue = exports.EventEmitter; - - /** - * Finds the index of the listener for the event in its storage array. - * - * @param {Function[]} listeners Array of listeners to search through. - * @param {Function} listener Method to look for. - * @return {Number} Index of the specified listener, -1 if not found - * @api private - */ - function indexOfListener(listeners, listener) { - var i = listeners.length; - while (i--) { - if (listeners[i].listener === listener) { - return i; - } - } - - return -1; - } - - /** - * Alias a method while keeping the context correct, to allow for overwriting of target method. - * - * @param {String} name The name of the target method. - * @return {Function} The aliased method - * @api private - */ - function alias(name) { - return function aliasClosure() { - return this[name].apply(this, arguments); - }; - } - - /** - * Returns the listener array for the specified event. - * Will initialise the event object and listener arrays if required. - * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. - * Each property in the object response is an array of listener functions. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Function[]|Object} All listener functions for the event. - */ - proto.getListeners = function getListeners(evt) { - var events = this._getEvents(); - var response; - var key; - - // Return a concatenated array of all matching events if - // the selector is a regular expression. - if (evt instanceof RegExp) { - response = {}; - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - response[key] = events[key]; - } - } - } - else { - response = events[evt] || (events[evt] = []); - } - - return response; - }; - - /** - * Takes a list of listener objects and flattens it into a list of listener functions. - * - * @param {Object[]} listeners Raw listener objects. - * @return {Function[]} Just the listener functions. - */ - proto.flattenListeners = function flattenListeners(listeners) { - var flatListeners = []; - var i; - - for (i = 0; i < listeners.length; i += 1) { - flatListeners.push(listeners[i].listener); - } - - return flatListeners; - }; - - /** - * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Object} All listener functions for an event in an object. - */ - proto.getListenersAsObject = function getListenersAsObject(evt) { - var listeners = this.getListeners(evt); - var response; - - if (listeners instanceof Array) { - response = {}; - response[evt] = listeners; - } - - return response || listeners; - }; - - function isValidListener (listener) { - if (typeof listener === 'function' || listener instanceof RegExp) { - return true - } else if (listener && typeof listener === 'object') { - return isValidListener(listener.listener) - } else { - return false - } - } - - /** - * Adds a listener function to the specified event. - * The listener will not be added if it is a duplicate. - * If the listener returns true then it will be removed after it is called. - * If you pass a regular expression as the event name then the listener will be added to all events that match it. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListener = function addListener(evt, listener) { - if (!isValidListener(listener)) { - throw new TypeError('listener must be a function'); - } - - var listeners = this.getListenersAsObject(evt); - var listenerIsWrapped = typeof listener === 'object'; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { - listeners[key].push(listenerIsWrapped ? listener : { - listener: listener, - once: false - }); - } - } - - return this; - }; - - /** - * Alias of addListener - */ - proto.on = alias('addListener'); - - /** - * Semi-alias of addListener. It will add a listener that will be - * automatically removed after its first execution. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addOnceListener = function addOnceListener(evt, listener) { - return this.addListener(evt, { - listener: listener, - once: true - }); - }; - - /** - * Alias of addOnceListener. - */ - proto.once = alias('addOnceListener'); - - /** - * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. - * You need to tell it what event names should be matched by a regex. - * - * @param {String} evt Name of the event to create. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvent = function defineEvent(evt) { - this.getListeners(evt); - return this; - }; - - /** - * Uses defineEvent to define multiple events. - * - * @param {String[]} evts An array of event names to define. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvents = function defineEvents(evts) { - for (var i = 0; i < evts.length; i += 1) { - this.defineEvent(evts[i]); - } - return this; - }; - - /** - * Removes a listener function from the specified event. - * When passed a regular expression as the event name, it will remove the listener from all events that match it. - * - * @param {String|RegExp} evt Name of the event to remove the listener from. - * @param {Function} listener Method to remove from the event. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListener = function removeListener(evt, listener) { - var listeners = this.getListenersAsObject(evt); - var index; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key)) { - index = indexOfListener(listeners[key], listener); - - if (index !== -1) { - listeners[key].splice(index, 1); - } - } - } - - return this; - }; - - /** - * Alias of removeListener - */ - proto.off = alias('removeListener'); - - /** - * Adds listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. - * You can also pass it a regular expression to add the array of listeners to all events that match it. - * Yeah, this function does quite a bit. That's probably a bad thing. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListeners = function addListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(false, evt, listeners); - }; - - /** - * Removes listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be removed. - * You can also pass it a regular expression to remove the listeners from all events that match it. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListeners = function removeListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(true, evt, listeners); - }; - - /** - * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. - * The first argument will determine if the listeners are removed (true) or added (false). - * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be added/removed. - * You can also pass it a regular expression to manipulate the listeners of all events that match it. - * - * @param {Boolean} remove True if you want to remove listeners, false if you want to add. - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add/remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { - var i; - var value; - var single = remove ? this.removeListener : this.addListener; - var multiple = remove ? this.removeListeners : this.addListeners; - - // If evt is an object then pass each of its properties to this method - if (typeof evt === 'object' && !(evt instanceof RegExp)) { - for (i in evt) { - if (evt.hasOwnProperty(i) && (value = evt[i])) { - // Pass the single listener straight through to the singular method - if (typeof value === 'function') { - single.call(this, i, value); - } - else { - // Otherwise pass back to the multiple function - multiple.call(this, i, value); - } - } - } - } - else { - // So evt must be a string - // And listeners must be an array of listeners - // Loop over it and pass each one to the multiple method - i = listeners.length; - while (i--) { - single.call(this, evt, listeners[i]); - } - } - - return this; - }; - - /** - * Removes all listeners from a specified event. - * If you do not specify an event then all listeners will be removed. - * That means every event will be emptied. - * You can also pass a regex to remove all events that match it. - * - * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeEvent = function removeEvent(evt) { - var type = typeof evt; - var events = this._getEvents(); - var key; - - // Remove different things depending on the state of evt - if (type === 'string') { - // Remove all listeners for the specified event - delete events[evt]; - } - else if (evt instanceof RegExp) { - // Remove all events matching the regex. - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - delete events[key]; - } - } - } - else { - // Remove all listeners in all events - delete this._events; - } - - return this; - }; - - /** - * Alias of removeEvent. - * - * Added to mirror the node API. - */ - proto.removeAllListeners = alias('removeEvent'); - - /** - * Emits an event of your choice. - * When emitted, every listener attached to that event will be executed. - * If you pass the optional argument array then those arguments will be passed to every listener upon execution. - * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. - * So they will not arrive within the array on the other side, they will be separate. - * You can also pass a regular expression to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {Array} [args] Optional array of arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emitEvent = function emitEvent(evt, args) { - var listenersMap = this.getListenersAsObject(evt); - var listeners; - var listener; - var i; - var key; - var response; - - for (key in listenersMap) { - if (listenersMap.hasOwnProperty(key)) { - listeners = listenersMap[key].slice(0); - - for (i = 0; i < listeners.length; i++) { - // If the listener returns true then it shall be removed from the event - // The function is executed either with a basic call or an apply if there is an args array - listener = listeners[i]; - - if (listener.once === true) { - this.removeListener(evt, listener.listener); - } - - response = listener.listener.apply(this, args || []); - - if (response === this._getOnceReturnValue()) { - this.removeListener(evt, listener.listener); - } - } - } - } - - return this; - }; - - /** - * Alias of emitEvent - */ - proto.trigger = alias('emitEvent'); - - /** - * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. - * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {...*} Optional additional arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emit = function emit(evt) { - var args = Array.prototype.slice.call(arguments, 1); - return this.emitEvent(evt, args); - }; - - /** - * Sets the current value to check against when executing listeners. If a - * listeners return value matches the one set here then it will be removed - * after execution. This value defaults to true. - * - * @param {*} value The new value to check for when executing listeners. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.setOnceReturnValue = function setOnceReturnValue(value) { - this._onceReturnValue = value; - return this; - }; - - /** - * Fetches the current value to check against when executing listeners. If - * the listeners return value matches this one then it should be removed - * automatically. It will return true by default. - * - * @return {*|Boolean} The current value to check for or the default, true. - * @api private - */ - proto._getOnceReturnValue = function _getOnceReturnValue() { - if (this.hasOwnProperty('_onceReturnValue')) { - return this._onceReturnValue; - } - else { - return true; - } - }; - - /** - * Fetches the events object and creates one if required. - * - * @return {Object} The events storage object. - * @api private - */ - proto._getEvents = function _getEvents() { - return this._events || (this._events = {}); - }; - - /** - * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. - * - * @return {Function} Non conflicting EventEmitter class. - */ - EventEmitter.noConflict = function noConflict() { - exports.EventEmitter = originalGlobalValue; - return EventEmitter; - }; - - // Expose the class either via AMD, CommonJS or the global object - if (typeof define === 'function' && define.amd) { - define(function () { - return EventEmitter; - }); - } - else if (typeof module === 'object' && module.exports){ - module.exports = EventEmitter; - } - else { - exports.EventEmitter = EventEmitter; - } -}(this || {})); - -},{}],26:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var OpenVidu_1 = require("./OpenVidu/OpenVidu"); -if (window) { - window['OpenVidu'] = OpenVidu_1.OpenVidu; -} - -},{"./OpenVidu/OpenVidu":29}],27:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Stream_1 = require("./Stream"); -var Connection = (function () { - function Connection(session, opts) { - this.session = session; - this.disposed = false; - var msg = "'Connection' created "; - if (!!opts) { - msg += "(remote) with 'connectionId' [" + opts.id + ']'; - } - else { - msg += '(local)'; - } - console.info(msg); - this.options = opts; - if (!!opts) { - this.connectionId = opts.id; - if (opts.metadata) { - this.data = opts.metadata; - } - if (opts.streams) { - this.initRemoteStreams(opts.streams); - } - } - this.creationTime = new Date().getTime(); - } - Connection.prototype.sendIceCandidate = function (candidate) { - console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate)); - this.session.openvidu.sendRequest('onIceCandidate', { - endpointName: this.connectionId, - candidate: candidate.candidate, - sdpMid: candidate.sdpMid, - sdpMLineIndex: candidate.sdpMLineIndex - }, function (error, response) { - if (error) { - console.error('Error sending ICE candidate: ' - + JSON.stringify(error)); - } - }); - }; - Connection.prototype.initRemoteStreams = function (options) { - var _this = this; - options.forEach(function (opts) { - var streamOptions = { - id: opts.id, - connection: _this, - frameRate: opts.frameRate, - recvAudio: opts.audioActive, - recvVideo: opts.videoActive, - typeOfVideo: opts.typeOfVideo - }; - var stream = new Stream_1.Stream(_this.session, streamOptions); - _this.addStream(stream); - }); - console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); - }; - Connection.prototype.addStream = function (stream) { - stream.connection = this; - this.stream = stream; - }; - Connection.prototype.removeStream = function (streamId) { - delete this.stream; - }; - Connection.prototype.dispose = function () { - if (!!this.stream) { - delete this.stream; - } - this.disposed = true; - }; - return Connection; -}()); -exports.Connection = Connection; - -},{"./Stream":32}],28:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState"); -var LocalRecorder = (function () { - function LocalRecorder(stream) { - this.stream = stream; - this.chunks = []; - this.count = 0; - this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; - this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; - this.state = LocalRecorderState_1.LocalRecorderState.READY; - } - LocalRecorder.prototype.record = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (typeof MediaRecorder === 'undefined') { - console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); - throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); - } - if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) { - throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); - } - console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'"); - if (typeof MediaRecorder.isTypeSupported === 'function') { - var options = void 0; - if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { - options = { mimeType: 'video/webm;codecs=vp9' }; - } - else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { - options = { mimeType: 'video/webm;codecs=h264' }; - } - else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { - options = { mimeType: 'video/webm;codecs=vp8' }; - } - console.log('Using mimeType ' + options.mimeType); - _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options); - } - else { - console.warn('isTypeSupported is not supported, using default codecs for browser'); - _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream()); - } - _this.mediaRecorder.start(10); - } - catch (err) { - reject(err); - } - _this.mediaRecorder.ondataavailable = function (e) { - _this.chunks.push(e.data); - }; - _this.mediaRecorder.onerror = function (e) { - console.error('MediaRecorder error: ', e); - }; - _this.mediaRecorder.onstart = function () { - console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - }; - _this.mediaRecorder.onpause = function () { - console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onresume = function () { - console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onwarning = function (e) { - console.log('MediaRecorder warning: ' + e); - }; - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - resolve(); - }); - }; - LocalRecorder.prototype.stop = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before')); - } - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - resolve(); - }; - _this.mediaRecorder.stop(); - } - catch (e) { - reject(e); - } - }); - }; - LocalRecorder.prototype.pause = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) { - reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before')); - } - _this.mediaRecorder.pause(); - _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED; - } - catch (error) { - reject(error); - } - }); - }; - LocalRecorder.prototype.resume = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) { - throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before')); - } - _this.mediaRecorder.resume(); - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - } - catch (error) { - reject(error); - } - }); - }; - LocalRecorder.prototype.preview = function (parentElement) { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - this.videoPreview = document.createElement('video'); - this.videoPreview.id = this.id; - this.videoPreview.autoplay = true; - if (typeof parentElement === 'string') { - this.htmlParentElementId = parentElement; - var parentElementDom = document.getElementById(parentElement); - if (parentElementDom) { - this.videoPreview = parentElementDom.appendChild(this.videoPreview); - } - } - else { - this.htmlParentElementId = parentElement.id; - this.videoPreview = parentElement.appendChild(this.videoPreview); - } - this.videoPreview.src = this.videoPreviewSrc; - return this.videoPreview; - }; - LocalRecorder.prototype.clean = function () { - var _this = this; - var f = function () { - delete _this.blob; - _this.chunks = []; - _this.count = 0; - delete _this.mediaRecorder; - _this.state = LocalRecorderState_1.LocalRecorderState.READY; - }; - if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) { - this.stop().then(function () { return f(); }).catch(function () { return f(); }); - } - else { - f(); - } - }; - LocalRecorder.prototype.download = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var a = document.createElement('a'); - a.style.display = 'none'; - document.body.appendChild(a); - var url = window.URL.createObjectURL(this.blob); - a.href = url; - a.download = this.id + '.webm'; - a.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(a); - } - }; - LocalRecorder.prototype.getBlob = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); - } - else { - return this.blob; - } - }; - LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_1 = new XMLHttpRequest(); - http_1.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_1.setRequestHeader(key, headers[key]); - } - } - http_1.onreadystatechange = function () { - if (http_1.readyState === 4) { - if (http_1.status.toString().charAt(0) === '2') { - resolve(http_1.responseText); - } - else { - reject(http_1.status); - } - } - }; - http_1.send(_this.blob); - } - }); - }; - LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_2 = new XMLHttpRequest(); - http_2.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_2.setRequestHeader(key, headers[key]); - } - } - var sendable = new FormData(); - sendable.append('file', _this.blob, _this.id + '.webm'); - http_2.onreadystatechange = function () { - if (http_2.readyState === 4) { - if (http_2.status.toString().charAt(0) === '2') { - resolve(http_2.responseText); - } - else { - reject(http_2.status); - } - } - }; - http_2.send(sendable); - } - }); - }; - LocalRecorder.prototype.onStopDefault = function () { - console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')'); - this.blob = new Blob(this.chunks, { type: 'video/webm' }); - this.chunks = []; - this.videoPreviewSrc = window.URL.createObjectURL(this.blob); - this.state = LocalRecorderState_1.LocalRecorderState.FINISHED; - }; - return LocalRecorder; -}()); -exports.LocalRecorder = LocalRecorder; - -},{"../OpenViduInternal/Enums/LocalRecorderState":35}],29:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorder_1 = require("./LocalRecorder"); -var Publisher_1 = require("./Publisher"); -var Session_1 = require("./Session"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); -var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); -var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); -var platform = require("platform"); -var OpenVidu = (function () { - function OpenVidu() { - this.secret = ''; - this.recorder = false; - this.advancedConfiguration = {}; - console.info("'OpenVidu' initialized"); - } - OpenVidu.prototype.initSession = function () { - this.session = new Session_1.Session(this); - return this.session; - }; - OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) { - var properties; - if (!!param2 && (typeof param2 !== 'function')) { - properties = param2; - properties = { - audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, - frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), - insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, - publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, - publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, - resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), - videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: true, - publishAudio: true, - publishVideo: true, - resolution: '640x480' - }; - } - var publisher = new Publisher_1.Publisher(targetElement, properties, this); - var completionHandler; - if (!!param2 && (typeof param2 === 'function')) { - completionHandler = param2; - } - else if (!!param3) { - completionHandler = param3; - } - publisher.initialize() - .then(function () { - if (completionHandler !== undefined) { - completionHandler(undefined); - } - publisher.emitEvent('accessAllowed', []); - }).catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - publisher.emitEvent('accessDenied', []); - }); - return publisher; - }; - OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - var publisher; - var callback = function (error) { - if (!!error) { - reject(error); - } - else { - resolve(publisher); - } - }; - if (!!properties) { - publisher = _this.initPublisher(targetElement, properties, callback); - } - else { - publisher = _this.initPublisher(targetElement, callback); - } - }); - }; - OpenVidu.prototype.initLocalRecorder = function (stream) { - return new LocalRecorder_1.LocalRecorder(stream); - }; - OpenVidu.prototype.checkSystemRequirements = function () { - var browser = platform.name; - var version = platform.version; - if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') && - (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') && - (browser !== 'Opera') && (browser !== 'Opera Mobile') && - (browser !== 'Safari')) { - return 0; - } - else { - return 1; - } - }; - OpenVidu.prototype.getDevices = function () { - return new Promise(function (resolve, reject) { - navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { - var devices = []; - deviceInfos.forEach(function (deviceInfo) { - if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { - devices.push({ - kind: deviceInfo.kind, - deviceId: deviceInfo.deviceId, - label: deviceInfo.label - }); - } - }); - resolve(devices); - }).catch(function (error) { - console.error('Error getting devices', error); - reject(error); - }); - }); - }; - OpenVidu.prototype.getUserMedia = function (options) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.generateMediaConstraints(options) - .then(function (constraints) { - navigator.mediaDevices.getUserMedia(constraints) - .then(function (mediaStream) { - resolve(mediaStream); - }) - .catch(function (error) { - var errorName; - var errorMessage = error.toString(); - if (!(options.videoSource === 'screen')) { - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; - } - reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - }) - .catch(function (error) { - reject(error); - }); - }); - }; - OpenVidu.prototype.enableProdMode = function () { - console.log = function () { }; - console.debug = function () { }; - console.info = function () { }; - console.warn = function () { }; - }; - OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { - this.advancedConfiguration = configuration; - }; - OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { - var _this = this; - return new Promise(function (resolve, reject) { - var audio, video; - if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) { - audio = false; - } - else if (publisherProperties.audioSource === undefined) { - audio = true; - } - else { - audio = publisherProperties.audioSource; - } - if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) { - video = false; - } - else { - video = { - height: { - ideal: 480 - }, - width: { - ideal: 640 - } - }; - } - var mediaConstraints = { - audio: audio, - video: video - }; - if (typeof mediaConstraints.audio === 'string') { - mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } }; - } - if (mediaConstraints.video) { - if (!!publisherProperties.resolution) { - var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); - var width = Number(widthAndHeight[0]); - var height = Number(widthAndHeight[1]); - mediaConstraints.video.width.ideal = width; - mediaConstraints.video.height.ideal = height; - } - if (!!publisherProperties.frameRate) { - mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate }; - } - if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') { - if (publisherProperties.videoSource === 'screen') { - if (platform.name !== 'Chrome' && platform.name !== 'Firefox') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); - console.error(error); - reject(error); - } - else { - if (!!_this.advancedConfiguration.screenShareChromeExtension) { - var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); - screenSharing.getChromeExtensionStatus(extensionId, function (status) { - if (status === 'installed-enabled') { - screenSharing.getScreenConstraints(function (error, screenConstraints) { - if (!!error && error === 'permission-denied') { - var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - console.error(error_1); - reject(error_1); - } - else { - mediaConstraints.video = screenConstraints; - resolve(mediaConstraints); - } - }); - } - if (status === 'installed-disabled') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - console.error(error); - reject(error); - } - if (status === 'not-installed') { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); - console.error(error); - reject(error); - } - }); - } - else { - screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { - if (!!error) { - if (error === 'not-installed') { - var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); - console.error(error_2); - reject(error_2); - } - else if (error === 'installed-disabled') { - var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - console.error(error_3); - reject(error_3); - } - else if (error === 'permission-denied') { - var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - console.error(error_4); - reject(error_4); - } - } - else { - mediaConstraints.video = screenConstraints.video; - resolve(mediaConstraints); - } - }); - } - publisherProperties.videoSource = 'screen'; - } - } - else { - mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource }; - resolve(mediaConstraints); - } - } - else { - resolve(mediaConstraints); - } - } - else { - resolve(mediaConstraints); - } - }); - }; - OpenVidu.prototype.startWs = function (onConnectSucces) { - var config = { - heartbeat: 5000, - sendCloseMessage: false, - ws: { - uri: this.wsUri, - useSockJS: false, - onconnected: onConnectSucces, - ondisconnect: this.disconnectCallback.bind(this), - onreconnecting: this.reconnectingCallback.bind(this), - onreconnected: this.reconnectedCallback.bind(this) - }, - rpc: { - requestTimeout: 15000, - participantJoined: this.session.onParticipantJoined.bind(this.session), - participantPublished: this.session.onParticipantPublished.bind(this.session), - participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), - participantLeft: this.session.onParticipantLeft.bind(this.session), - participantEvicted: this.session.onParticipantEvicted.bind(this.session), - recordingStarted: this.session.onRecordingStarted.bind(this.session), - recordingStopped: this.session.onRecordingStopped.bind(this.session), - sendMessage: this.session.onNewMessage.bind(this.session), - iceCandidate: this.session.recvIceCandidate.bind(this.session), - mediaError: this.session.onMediaError.bind(this.session) - } - }; - this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); - }; - OpenVidu.prototype.closeWs = function () { - this.jsonRpcClient.close(); - }; - OpenVidu.prototype.sendRequest = function (method, params, callback) { - if (params && params instanceof Function) { - callback = params; - params = {}; - } - console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); - this.jsonRpcClient.send(method, params, callback); - }; - OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) { - var is = (!!mediaSource && - mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' && - mediaSource.id !== undefined && typeof mediaSource.id === 'string' && - mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' && - mediaSource.label !== undefined && typeof mediaSource.label === 'string' && - mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' && - mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string'); - return is; - }; - OpenVidu.prototype.getWsUri = function () { - return this.wsUri; - }; - OpenVidu.prototype.getSecret = function () { - return this.secret; - }; - OpenVidu.prototype.getRecorder = function () { - return this.recorder; - }; - OpenVidu.prototype.disconnectCallback = function () { - console.warn('Websocket connection lost'); - if (this.isRoomAvailable()) { - this.session.onLostConnection(); - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.reconnectingCallback = function () { - console.warn('Websocket connection lost (reconnecting)'); - if (this.isRoomAvailable()) { - this.session.onLostConnection(); - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.reconnectedCallback = function () { - console.warn('Websocket reconnected'); - }; - OpenVidu.prototype.isRoomAvailable = function () { - if (this.session !== undefined && this.session instanceof Session_1.Session) { - return true; - } - else { - console.warn('Session instance not found'); - return false; - } - }; - return OpenVidu; -}()); -exports.OpenVidu = OpenVidu; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":52,"../OpenViduInternal/ScreenSharing/Screen-Capturing":59,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":58,"./LocalRecorder":28,"./Publisher":30,"./Session":31,"platform":9}],30:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Session_1 = require("./Session"); -var Stream_1 = require("./Stream"); -var StreamManager_1 = require("./StreamManager"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var Publisher = (function (_super) { - __extends(Publisher, _super); - function Publisher(targEl, properties, openvidu) { - var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this; - _this.openvidu = openvidu; - _this.accessAllowed = false; - _this.isSubscribedToRemote = false; - _this.accessDenied = false; - _this.properties = properties; - _this.stream.ee.on('local-stream-destroyed-by-disconnect', function (reason) { - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - }); - return _this; - } - Publisher.prototype.publishAudio = function (value) { - this.stream.getWebRtcPeer().audioEnabled = value; - console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream'); - }; - Publisher.prototype.publishVideo = function (value) { - this.stream.getWebRtcPeer().videoEnabled = value; - console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream'); - }; - Publisher.prototype.subscribeToRemote = function (value) { - value = (value !== undefined) ? value : true; - this.isSubscribedToRemote = value; - this.stream.subscribeToMyRemote(value); - }; - Publisher.prototype.on = function (type, handler) { - var _this = this; - _super.prototype.on.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.on('stream-created-by-publisher', function () { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'remoteVideoPlaying') { - if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.ee.emitEvent('accessAllowed'); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.ee.emitEvent('accessDenied'); - } - } - return this; - }; - Publisher.prototype.once = function (type, handler) { - var _this = this; - _super.prototype.once.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.once('stream-created-by-publisher', function () { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'remoteVideoPlaying') { - if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.ee.emitEvent('accessAllowed'); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.ee.emitEvent('accessDenied'); - } - } - return this; - }; - Publisher.prototype.initialize = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var errorCallback = function (openViduError) { - _this.accessDenied = true; - _this.accessAllowed = false; - reject(openViduError); - }; - var successCallback = function (mediaStream) { - _this.accessAllowed = true; - _this.accessDenied = false; - if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) { - mediaStream.removeTrack(mediaStream.getAudioTracks()[0]); - mediaStream.addTrack(_this.properties.audioSource); - } - if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) { - mediaStream.removeTrack(mediaStream.getVideoTracks()[0]); - mediaStream.addTrack(_this.properties.videoSource); - } - if (!!mediaStream.getAudioTracks()[0]) { - mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; - } - if (!!mediaStream.getVideoTracks()[0]) { - mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; - } - _this.stream.setMediaStream(mediaStream); - if (!_this.stream.displayMyRemote()) { - _this.stream.updateMediaStreamInVideos(); - } - _this.stream.isLocalStreamReadyToPublish = true; - _this.stream.ee.emitEvent('stream-ready-to-publish', []); - if (!!_this.firstVideoElement) { - _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode); - } - delete _this.firstVideoElement; - resolve(); - }; - _this.openvidu.generateMediaConstraints(_this.properties) - .then(function (constraints) { - var outboundStreamOptions = { - mediaConstraints: constraints, - publisherProperties: _this.properties - }; - _this.stream.setOutboundStreamOptions(outboundStreamOptions); - var constraintsAux = {}; - var timeForDialogEvent = 1250; - if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) { - var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio); - constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1; - constraintsAux.video = constraints.video; - var startTime_1 = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (mediaStream) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) { - constraintsAux.audio = definedAudioConstraint_1; - constraintsAux.video = false; - startTime_1 = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (audioOnlyStream) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); - successCallback(mediaStream); - }) - .catch(function (error) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'notallowederror': - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'overconstrainederror': - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - } - }); - } - else { - successCallback(mediaStream); - } - }) - .catch(function (error) { - _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - case 'notallowederror': - errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'overconstrainederror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - } - }); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'")); - } - }) - .catch(function (error) { - errorCallback(error); - }); - }); - }; - Publisher.prototype.updateSession = function (session) { - this.session = session; - this.stream.session = session; - }; - Publisher.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - Publisher.prototype.reestablishStreamPlayingEvent = function () { - if (this.ee.getListeners('streamPlaying').length > 0) { - this.addPlayEventToFirstVideo(); - } - }; - Publisher.prototype.setPermissionDialogTimer = function (waitTime) { - var _this = this; - this.permissionDialogTimeout = setTimeout(function () { - _this.ee.emitEvent('accessDialogOpened', []); - }, waitTime); - }; - Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) { - clearTimeout(this.permissionDialogTimeout); - if ((Date.now() - startTime) > waitTime) { - this.ee.emitEvent('accessDialogClosed', []); - } - }; - return Publisher; -}(StreamManager_1.StreamManager)); -exports.Publisher = Publisher; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Events/StreamEvent":44,"../OpenViduInternal/Events/VideoElementEvent":46,"./Session":31,"./Stream":32,"./StreamManager":33}],31:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Connection_1 = require("./Connection"); -var Subscriber_1 = require("./Subscriber"); -var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent"); -var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent"); -var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); -var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var platform = require("platform"); -var EventEmitter = require("wolfy87-eventemitter"); -var Session = (function () { - function Session(openvidu) { - this.streamManagers = []; - this.remoteStreamsCreated = {}; - this.remoteConnections = {}; - this.speakingEventsEnabled = false; - this.ee = new EventEmitter(); - this.openvidu = openvidu; - } - Session.prototype.connect = function (token, metadata) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.processToken(token); - if (_this.openvidu.checkSystemRequirements()) { - _this.options = { - sessionId: _this.sessionId, - participantId: token, - metadata: !!metadata ? _this.stringClientMetadata(metadata) : '' - }; - _this.connectAux(token).then(function () { - resolve(); - }).catch(function (error) { - reject(error); - }); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu')); - } - }); - }; - Session.prototype.disconnect = function () { - this.leave(false, 'disconnect'); - }; - Session.prototype.subscribe = function (stream, targetElement, param3, param4) { - var properties = {}; - if (!!param3 && typeof param3 !== 'function') { - properties = { - insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, - subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: true, - subscribeToVideo: true - }; - } - var completionHandler; - if (!!param3 && (typeof param3 === 'function')) { - completionHandler = param3; - } - else if (!!param4) { - completionHandler = param4; - } - console.info('Subscribing to ' + stream.connection.connectionId); - stream.subscribe() - .then(function () { - console.info('Subscribed correctly to ' + stream.connection.connectionId); - if (completionHandler !== undefined) { - completionHandler(undefined); - } - }) - .catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - }); - var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties); - if (!!subscriber.targetElement) { - stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode); - } - return subscriber; - }; - Session.prototype.subscribeAsync = function (stream, targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - var subscriber; - var callback = function (error) { - if (!!error) { - reject(error); - } - else { - resolve(subscriber); - } - }; - if (!!properties) { - subscriber = _this.subscribe(stream, targetElement, properties, callback); - } - else { - subscriber = _this.subscribe(stream, targetElement, callback); - } - }); - }; - Session.prototype.unsubscribe = function (subscriber) { - var connectionId = subscriber.stream.connection.connectionId; - console.info('Unsubscribing from ' + connectionId); - this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { - if (error) { - console.error('Error unsubscribing from ' + connectionId, error); - } - else { - console.info('Unsubscribed correctly from ' + connectionId); - } - subscriber.stream.disposeWebRtcPeer(); - subscriber.stream.disposeMediaStream(); - }); - subscriber.stream.streamManager.removeAllVideos(); - }; - Session.prototype.publish = function (publisher) { - var _this = this; - return new Promise(function (resolve, reject) { - publisher.session = _this; - publisher.stream.session = _this; - if (!publisher.stream.isLocalStreamPublished) { - _this.connection.addStream(publisher.stream); - publisher.stream.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - } - else { - publisher.initialize() - .then(function () { - _this.connection.addStream(publisher.stream); - publisher.reestablishStreamPlayingEvent(); - publisher.stream.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }).catch(function (error) { - reject(error); - }); - } - }); - }; - Session.prototype.unpublish = function (publisher) { - var stream = publisher.stream; - if (!stream.connection) { - console.error('The associated Connection object of this Publisher is null', stream); - return; - } - else if (stream.connection !== this.connection) { - console.error('The associated Connection object of this Publisher is not your local Connection.' + - "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); - return; - } - else { - console.info('Unpublishing local media (' + stream.connection.connectionId + ')'); - this.openvidu.sendRequest('unpublishVideo', function (error, response) { - if (error) { - console.error(error); - } - else { - console.info('Media unpublished correctly'); - } - }); - stream.disposeWebRtcPeer(); - delete stream.connection.stream; - var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish'); - publisher.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - } - }; - Session.prototype.signal = function (signal) { - var _this = this; - return new Promise(function (resolve, reject) { - var signalMessage = {}; - if (signal.to && signal.to.length > 0) { - var connectionIds_1 = []; - signal.to.forEach(function (connection) { - connectionIds_1.push(connection.connectionId); - }); - signalMessage['to'] = connectionIds_1; - } - else { - signalMessage['to'] = []; - } - signalMessage['data'] = signal.data ? signal.data : ''; - signalMessage['type'] = signal.type ? signal.type : ''; - _this.openvidu.sendRequest('sendMessage', { - message: JSON.stringify(signalMessage) - }, function (error, response) { - if (!!error) { - reject(error); - } - else { - resolve(); - } - }); - }); - }; - Session.prototype.on = function (type, handler) { - this.ee.on(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered by 'Session'", event); - } - else { - console.info("Event '" + type + "' triggered by 'Session'"); - } - handler(event); - }); - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = true; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !str.speechEvent && str.hasAudio) { - str.enableSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.once = function (type, handler) { - this.ee.once(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered by 'Session'", event); - } - else { - console.info("Event '" + type + "' triggered by 'Session'"); - } - handler(event); - }); - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = true; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !str.speechEvent && str.hasAudio) { - str.enableOnceSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.off = function (type, handler) { - if (!handler) { - this.ee.removeAllListeners(type); - } - else { - this.ee.off(type, handler); - } - if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { - this.speakingEventsEnabled = false; - for (var connectionId in this.remoteConnections) { - var str = this.remoteConnections[connectionId].stream; - if (!!str && !!str.speechEvent) { - str.disableSpeakingEvents(); - } - } - } - return this; - }; - Session.prototype.onParticipantJoined = function (response) { - var _this = this; - this.getConnection(response.id, '') - .then(function (connection) { - console.warn('Connection ' + response.id + ' already exists in connections list'); - }) - .catch(function (openViduError) { - var connection = new Connection_1.Connection(_this, response); - _this.remoteConnections[response.id] = connection; - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - }; - Session.prototype.onParticipantLeft = function (msg) { - var _this = this; - this.getRemoteConnection(msg.name, 'Remote connection ' + msg.name + " unknown when 'onParticipantLeft'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (connection) { - if (!!connection.stream) { - var stream = connection.stream; - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - delete _this.remoteStreamsCreated[stream.streamId]; - } - delete _this.remoteConnections[connection.connectionId]; - _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onParticipantPublished = function (response) { - var _this = this; - var afterConnectionFound = function (connection) { - _this.remoteConnections[connection.connectionId] = connection; - if (!_this.remoteStreamsCreated[connection.stream.streamId]) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]); - } - _this.remoteStreamsCreated[connection.stream.streamId] = true; - }; - var connection; - this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (con) { - connection = con; - response.metadata = con.data; - connection.options = response; - connection.initRemoteStreams(response.streams); - afterConnectionFound(connection); - }) - .catch(function (openViduError) { - connection = new Connection_1.Connection(_this, response); - afterConnectionFound(connection); - }); - }; - Session.prototype.onParticipantUnpublished = function (msg) { - var _this = this; - this.getRemoteConnection(msg.name, "Remote connection '" + msg.name + "' unknown when 'onParticipantUnpublished'. " + - 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) - .then(function (connection) { - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehaviour(); - var streamId = connection.stream.streamId; - delete _this.remoteStreamsCreated[streamId]; - connection.removeStream(streamId); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onParticipantEvicted = function (msg) { - }; - Session.prototype.onNewMessage = function (msg) { - var _this = this; - console.info('New signal: ' + JSON.stringify(msg)); - this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: " - + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId) - .then(function (connection) { - _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); - _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.recvIceCandidate = function (msg) { - var candidate = { - candidate: msg.candidate, - sdpMid: msg.sdpMid, - sdpMLineIndex: msg.sdpMLineIndex - }; - this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) - .then(function (connection) { - var stream = connection.stream; - stream.getWebRtcPeer().addIceCandidate(candidate, function (error) { - if (error) { - console.error('Error adding candidate for ' + stream.streamId - + ' stream of endpoint ' + msg.endpointName + ': ' + error); - } - }); - }) - .catch(function (openViduError) { - console.error(openViduError); - }); - }; - Session.prototype.onSessionClosed = function (msg) { - console.info('Session closed: ' + JSON.stringify(msg)); - var s = msg.room; - if (s !== undefined) { - this.ee.emitEvent('session-closed', [{ - session: s - }]); - } - else { - console.warn('Session undefined on session closed', msg); - } - }; - Session.prototype.onLostConnection = function () { - if (!this.connection) { - console.warn('Not connected to session: if you are not debugging, this is probably a certificate error'); - var url = 'https://' + this.openvidu.getWsUri().split('wss://')[1].split('/openvidu')[0]; - if (window.confirm('If you are not debugging, this is probably a certificate error at \"' + url + '\"\n\nClick OK to navigate and accept it')) { - location.assign(url + '/accept-certificate'); - } - return; - } - console.warn('Lost connection in Session ' + this.sessionId); - if (!!this.sessionId && !this.connection.disposed) { - this.leave(true, 'networkDisconnect'); - } - }; - Session.prototype.onMediaError = function (params) { - console.error('Media error: ' + JSON.stringify(params)); - var err = params.error; - if (err) { - this.ee.emitEvent('error-media', [{ - error: err - }]); - } - else { - console.warn('Received undefined media error. Params:', params); - } - }; - Session.prototype.onRecordingStarted = function (response) { - this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]); - }; - Session.prototype.onRecordingStopped = function (response) { - this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]); - }; - Session.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - Session.prototype.leave = function (forced, reason) { - var _this = this; - forced = !!forced; - console.info('Leaving Session (forced=' + forced + ')'); - if (!!this.connection) { - if (!this.connection.disposed && !forced) { - this.openvidu.sendRequest('leaveRoom', function (error, response) { - if (error) { - console.error(error); - } - _this.openvidu.closeWs(); - }); - } - else { - this.openvidu.closeWs(); - } - if (!!this.connection.stream) { - this.connection.stream.disposeWebRtcPeer(); - if (this.connection.stream.isLocalStreamPublished) { - this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); - } - } - if (!this.connection.disposed) { - var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason); - this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); - sessionDisconnectEvent.callDefaultBehaviour(); - } - } - else { - console.warn('You were not connected to the session ' + this.sessionId); - } - }; - Session.prototype.connectAux = function (token) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.openvidu.startWs(function (error) { - if (!!error) { - reject(error); - } - else { - var joinParams = { - token: (!!token) ? token : '', - session: _this.sessionId, - metadata: !!_this.options.metadata ? _this.options.metadata : '', - secret: _this.openvidu.getSecret(), - recorder: _this.openvidu.getRecorder(), - }; - _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { - if (!!error) { - reject(error); - } - else { - _this.connection = new Connection_1.Connection(_this); - _this.connection.connectionId = response.id; - _this.connection.data = response.metadata; - var events_1 = { - connections: new Array(), - streams: new Array() - }; - var existingParticipants = response.value; - existingParticipants.forEach(function (participant) { - var connection = new Connection_1.Connection(_this, participant); - _this.remoteConnections[connection.connectionId] = connection; - events_1.connections.push(connection); - if (!!connection.stream) { - _this.remoteStreamsCreated[connection.stream.streamId] = true; - events_1.streams.push(connection.stream); - } - }); - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]); - events_1.connections.forEach(function (connection) { - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - events_1.streams.forEach(function (stream) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]); - }); - resolve(); - } - }); - } - }); - }); - }; - Session.prototype.stringClientMetadata = function (metadata) { - if (typeof metadata !== 'string') { - return JSON.stringify(metadata); - } - else { - return metadata; - } - }; - Session.prototype.getConnection = function (connectionId, errorMessage) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections[connectionId]; - if (!!connection) { - resolve(connection); - } - else { - if (_this.connection.connectionId === connectionId) { - resolve(_this.connection); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - } - }); - }; - Session.prototype.getRemoteConnection = function (connectionId, errorMessage) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections[connectionId]; - if (!!connection) { - resolve(connection); - } - else { - reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - }); - }; - Session.prototype.processToken = function (token) { - var url = new URL(token); - this.sessionId = url.searchParams.get('sessionId'); - var secret = url.searchParams.get('secret'); - var recorder = url.searchParams.get('recorder'); - if (!!secret) { - this.openvidu.secret = secret; - } - if (!!recorder) { - this.openvidu.recorder = true; - } - this.openvidu.wsUri = 'wss://' + url.host + '/openvidu'; - }; - return Session; -}()); -exports.Session = Session; - -},{"../OpenViduInternal/Enums/OpenViduError":36,"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/Events/ConnectionEvent":38,"../OpenViduInternal/Events/RecordingEvent":41,"../OpenViduInternal/Events/SessionDisconnectedEvent":42,"../OpenViduInternal/Events/SignalEvent":43,"../OpenViduInternal/Events/StreamEvent":44,"./Connection":27,"./Subscriber":34,"platform":9,"wolfy87-eventemitter":25}],32:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats"); -var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent"); -var EventEmitter = require("wolfy87-eventemitter"); -var kurentoUtils = require("../OpenViduInternal/KurentoUtils/kurento-utils-js"); -var Stream = (function () { - function Stream(session, options) { - var _this = this; - this.ee = new EventEmitter(); - this.isSubscribeToRemote = false; - this.isLocalStreamReadyToPublish = false; - this.isLocalStreamPublished = false; - this.session = session; - if (options.hasOwnProperty('id')) { - this.inboundStreamOpts = options; - this.streamId = this.inboundStreamOpts.id; - this.hasAudio = this.inboundStreamOpts.recvAudio; - this.hasVideo = this.inboundStreamOpts.recvVideo; - this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo; - this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; - } - else { - this.outboundStreamOpts = options; - if (this.isSendVideo()) { - if (this.isSendScreen()) { - this.streamId = 'SCREEN'; - this.typeOfVideo = 'SCREEN'; - } - else { - this.streamId = 'CAMERA'; - this.typeOfVideo = 'CAMERA'; - } - this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; - } - else { - this.streamId = 'MICRO'; - delete this.typeOfVideo; - } - this.hasAudio = this.isSendAudio(); - this.hasVideo = this.isSendVideo(); - } - this.ee.on('mediastream-updated', function () { - _this.streamManager.updateMediaStream(_this.mediaStream); - console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']'); - }); - } - Stream.prototype.getMediaStream = function () { - return this.mediaStream; - }; - Stream.prototype.setMediaStream = function (mediaStream) { - this.mediaStream = mediaStream; - }; - Stream.prototype.updateMediaStreamInVideos = function () { - this.ee.emitEvent('mediastream-updated'); - }; - Stream.prototype.getWebRtcPeer = function () { - return this.webRtcPeer; - }; - Stream.prototype.getRTCPeerConnection = function () { - return this.webRtcPeer.peerConnection; - }; - Stream.prototype.subscribeToMyRemote = function (value) { - this.isSubscribeToRemote = value; - }; - Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { - this.outboundStreamOpts = outboundStreamOpts; - }; - Stream.prototype.subscribe = function () { - var _this = this; - return new Promise(function (resolve, reject) { - _this.initWebRtcPeerReceive() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }); - }; - Stream.prototype.publish = function () { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.isLocalStreamReadyToPublish) { - _this.initWebRtcPeerSend() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - } - else { - _this.ee.once('stream-ready-to-publish', function () { - _this.publish() - .then(function () { - resolve(); - }) - .catch(function (error) { - reject(error); - }); - }); - } - }); - }; - Stream.prototype.disposeWebRtcPeer = function () { - if (this.webRtcPeer) { - this.webRtcPeer.dispose(); - } - if (this.speechEvent) { - this.speechEvent.stop(); - } - this.stopWebRtcStats(); - console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed'); - }; - Stream.prototype.disposeMediaStream = function () { - if (this.mediaStream) { - this.mediaStream.getAudioTracks().forEach(function (track) { - track.stop(); - }); - this.mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - delete this.mediaStream; - } - console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed'); - }; - Stream.prototype.displayMyRemote = function () { - return this.isSubscribeToRemote; - }; - Stream.prototype.isSendAudio = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.audioSource !== null && - this.outboundStreamOpts.publisherProperties.audioSource !== false); - }; - Stream.prototype.isSendVideo = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.videoSource !== null && - this.outboundStreamOpts.publisherProperties.videoSource !== false); - }; - Stream.prototype.isSendScreen = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.videoSource === 'screen'); - }; - Stream.prototype.setSpeechEventIfNotExists = function () { - if (!this.speechEvent) { - var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}; - harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50; - harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50; - this.speechEvent = kurentoUtils.WebRtcPeer.hark(this.mediaStream, harkOptions); - } - }; - Stream.prototype.enableSpeakingEvents = function () { - var _this = this; - this.setSpeechEventIfNotExists(); - this.speechEvent.on('speaking', function () { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - }); - this.speechEvent.on('stopped_speaking', function () { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - }); - }; - Stream.prototype.enableOnceSpeakingEvents = function () { - var _this = this; - this.setSpeechEventIfNotExists(); - this.speechEvent.on('speaking', function () { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - _this.disableSpeakingEvents(); - }); - this.speechEvent.on('stopped_speaking', function () { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - _this.disableSpeakingEvents(); - }); - }; - Stream.prototype.disableSpeakingEvents = function () { - this.speechEvent.stop(); - this.speechEvent = undefined; - }; - Stream.prototype.initWebRtcPeerSend = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var userMediaConstraints = { - audio: _this.isSendAudio(), - video: _this.isSendVideo() - }; - var options = { - videoStream: _this.mediaStream, - mediaConstraints: userMediaConstraints, - onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), - iceServers: _this.session.openvidu.advancedConfiguration.iceServers - }; - var successCallback = function (error, sdpOfferParam, wp) { - if (error) { - reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error))); - } - console.debug('Sending SDP offer to publish as ' - + _this.streamId, sdpOfferParam); - _this.session.openvidu.sendRequest('publishVideo', { - sdpOffer: sdpOfferParam, - doLoopback: _this.displayMyRemote() || false, - audioActive: _this.isSendAudio(), - videoActive: _this.isSendVideo(), - typeOfVideo: ((_this.isSendVideo()) ? (_this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''), - frameRate: !!_this.frameRate ? _this.frameRate : -1 - }, function (error, response) { - if (error) { - reject('Error on publishVideo: ' + JSON.stringify(error)); - } - else { - _this.processSdpAnswer(response.sdpAnswer) - .then(function () { - _this.isLocalStreamPublished = true; - if (_this.displayMyRemote()) { - _this.updateMediaStreamInVideos(); - } - _this.ee.emitEvent('stream-created-by-publisher'); - resolve(); - }) - .catch(function (error) { - reject(error); - }); - console.info("'Publisher' successfully published to session"); - } - }); - }; - if (_this.displayMyRemote()) { - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function (err) { - if (err) { - reject(err); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - } - else { - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options, function (error) { - if (error) { - reject(error); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - } - }); - }; - Stream.prototype.initWebRtcPeerReceive = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var offerConstraints = { - audio: _this.inboundStreamOpts.recvAudio, - video: _this.inboundStreamOpts.recvVideo - }; - console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); - var options = { - onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), - mediaConstraints: offerConstraints - }; - var successCallback = function (error, sdpOfferParam, wp) { - if (error) { - reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error))); - } - console.debug('Sending SDP offer to subscribe to ' - + _this.streamId, sdpOfferParam); - _this.session.openvidu.sendRequest('receiveVideoFrom', { - sender: _this.streamId, - sdpOffer: sdpOfferParam - }, function (error, response) { - if (error) { - reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error))); - } - else { - _this.processSdpAnswer(response.sdpAnswer).then(function () { - resolve(); - }).catch(function (error) { - reject(error); - }); - } - }); - }; - _this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function (error) { - if (error) { - reject(error); - } - _this.webRtcPeer.generateOffer(successCallback); - }); - }); - }; - Stream.prototype.processSdpAnswer = function (sdpAnswer) { - var _this = this; - return new Promise(function (resolve, reject) { - var answer = new RTCSessionDescription({ - type: 'answer', - sdp: sdpAnswer, - }); - console.debug(_this.streamId + ': set peer connection with recvd SDP answer', sdpAnswer); - var streamId = _this.streamId; - var peerConnection = _this.webRtcPeer.peerConnection; - peerConnection.setRemoteDescription(answer, function () { - if (!_this.isLocal() || _this.displayMyRemote()) { - _this.mediaStream = peerConnection.getRemoteStreams()[0]; - console.debug('Peer remote stream', _this.mediaStream); - if (!!_this.mediaStream) { - _this.ee.emitEvent('mediastream-updated'); - if (!!_this.mediaStream.getAudioTracks()[0] && _this.session.speakingEventsEnabled) { - _this.enableSpeakingEvents(); - } - } - } - _this.initWebRtcStats(); - resolve(); - }, function (error) { - reject(new Error(_this.streamId + ': Error setting SDP to the peer connection: ' + JSON.stringify(error))); - }); - }); - }; - Stream.prototype.initWebRtcStats = function () { - this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); - this.webRtcStats.initWebRtcStats(); - }; - Stream.prototype.stopWebRtcStats = function () { - if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { - this.webRtcStats.stopWebRtcStats(); - } - }; - Stream.prototype.isLocal = function () { - return (!this.inboundStreamOpts && !!this.outboundStreamOpts); - }; - return Stream; -}()); -exports.Stream = Stream; - -},{"../OpenViduInternal/Events/PublisherSpeakingEvent":40,"../OpenViduInternal/KurentoUtils/kurento-utils-js":57,"../OpenViduInternal/WebRtcStats/WebRtcStats":60,"wolfy87-eventemitter":25}],33:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); -var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var EventEmitter = require("wolfy87-eventemitter"); -var StreamManager = (function () { - function StreamManager(stream, targetElement) { - var _this = this; - this.videos = []; - this.lazyLaunchVideoElementCreatedEvent = false; - this.ee = new EventEmitter(); - this.stream = stream; - this.stream.streamManager = this; - this.remote = !this.stream.isLocal(); - if (!!targetElement) { - var targEl = void 0; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targetElement); - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - if (!!targEl) { - this.firstVideoElement = { - targetElement: targEl, - video: document.createElement('video'), - id: '' - }; - this.targetElement = targEl; - this.element = targEl; - } - } - this.canPlayListener = function () { - if (_this.stream.isLocal()) { - if (!_this.stream.displayMyRemote()) { - console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); - } - else { - console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]); - } - } - else { - console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); - _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); - } - _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]); - }; - } - StreamManager.prototype.on = function (type, handler) { - this.ee.on(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered", event); - } - else { - console.info("Event '" + type + "' triggered"); - } - handler(event); - }); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = false; - } - } - if (type === 'streamPlaying' || type === 'videoPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); - this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); - } - } - return this; - }; - StreamManager.prototype.once = function (type, handler) { - this.ee.once(type, function (event) { - if (event) { - console.info("Event '" + type + "' triggered once", event); - } - else { - console.info("Event '" + type + "' triggered once"); - } - handler(event); - }); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - } - } - if (type === 'streamPlaying' || type === 'videoPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); - this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); - } - } - return this; - }; - StreamManager.prototype.off = function (type, handler) { - if (!handler) { - this.ee.removeAllListeners(type); - } - else { - this.ee.off(type, handler); - } - return this; - }; - StreamManager.prototype.addVideoElement = function (video) { - this.initializeVideoProperties(video); - for (var _i = 0, _a = this.videos; _i < _a.length; _i++) { - var v = _a[_i]; - if (v.video === video) { - return 0; - } - } - var returnNumber = 1; - this.initializeVideoProperties(video); - for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) { - var streamManager = _c[_b]; - if (streamManager.disassociateVideo(video)) { - returnNumber = -1; - break; - } - } - this.stream.session.streamManagers.forEach(function (streamManager) { - streamManager.disassociateVideo(video); - }); - this.pushNewStreamManagerVideo({ - video: video, - id: video.id - }); - console.info('New video element associated to ', this); - return returnNumber; - }; - StreamManager.prototype.createVideoElement = function (targetElement, insertMode) { - var targEl; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targEl); - if (!targEl) { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - else { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - var video = document.createElement('video'); - this.initializeVideoProperties(video); - var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; - switch (insMode) { - case VideoInsertMode_1.VideoInsertMode.AFTER: - targEl.parentNode.insertBefore(video, targEl.nextSibling); - break; - case VideoInsertMode_1.VideoInsertMode.APPEND: - targEl.appendChild(video); - break; - case VideoInsertMode_1.VideoInsertMode.BEFORE: - targEl.parentNode.insertBefore(video, targEl); - break; - case VideoInsertMode_1.VideoInsertMode.PREPEND: - targEl.insertBefore(video, targEl.childNodes[0]); - break; - case VideoInsertMode_1.VideoInsertMode.REPLACE: - targEl.parentNode.replaceChild(video, targEl); - break; - default: - insMode = VideoInsertMode_1.VideoInsertMode.APPEND; - targEl.appendChild(video); - break; - } - var v = { - targetElement: targEl, - video: video, - insertMode: insMode, - id: video.id - }; - this.pushNewStreamManagerVideo(v); - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement; - return video; - }; - StreamManager.prototype.initializeVideoProperties = function (video) { - video.srcObject = this.stream.getMediaStream(); - video.autoplay = true; - video.controls = false; - if (!video.id) { - video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId; - if (!this.id && !!this.targetElement) { - this.id = video.id; - } - } - if (!this.remote && !this.stream.displayMyRemote()) { - video.muted = true; - if (this.stream.outboundStreamOpts.publisherProperties.mirror) { - this.mirrorVideo(video); - } - } - }; - StreamManager.prototype.removeAllVideos = function () { - var _this = this; - for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) { - if (this.stream.session.streamManagers[i] === this) { - this.stream.session.streamManagers.splice(i, 1); - } - } - this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) { - streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener); - if (!!streamManagerVideo.targetElement) { - streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video); - _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]); - _this.videos.splice(videos.length - 1 - index, 1); - } - else { - streamManagerVideo.video.srcObject = null; - } - }); - }; - StreamManager.prototype.disassociateVideo = function (video) { - var disassociated = false; - for (var i = 0; i < this.videos.length; i++) { - if (this.videos[i].video === video) { - this.videos.splice(i, 1); - disassociated = true; - console.info('Video element disassociated from ', this); - break; - } - } - return disassociated; - }; - StreamManager.prototype.addPlayEventToFirstVideo = function () { - if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) { - this.videos[0].video.addEventListener('canplay', this.canPlayListener); - } - }; - StreamManager.prototype.updateMediaStream = function (mediaStream) { - this.videos.forEach(function (streamManagerVideo) { - streamManagerVideo.video.srcObject = mediaStream; - }); - }; - StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) { - this.videos.push(streamManagerVideo); - this.addPlayEventToFirstVideo(); - if (this.stream.session.streamManagers.indexOf(this) === -1) { - this.stream.session.streamManagers.push(this); - } - }; - StreamManager.prototype.mirrorVideo = function (video) { - video.style.transform = 'rotateY(180deg)'; - video.style.webkitTransform = 'rotateY(180deg)'; - }; - return StreamManager; -}()); -exports.StreamManager = StreamManager; - -},{"../OpenViduInternal/Enums/VideoInsertMode":37,"../OpenViduInternal/Events/StreamManagerEvent":45,"../OpenViduInternal/Events/VideoElementEvent":46,"wolfy87-eventemitter":25}],34:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var StreamManager_1 = require("./StreamManager"); -var Subscriber = (function (_super) { - __extends(Subscriber, _super); - function Subscriber(stream, targEl, properties) { - var _this = _super.call(this, stream, targEl) || this; - _this.element = _this.targetElement; - _this.stream = stream; - _this.properties = properties; - return _this; - } - Subscriber.prototype.subscribeToAudio = function (value) { - this.stream.getMediaStream().getAudioTracks().forEach(function (track) { - track.enabled = value; - }); - console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream'); - return this; - }; - Subscriber.prototype.subscribeToVideo = function (value) { - this.stream.getMediaStream().getVideoTracks().forEach(function (track) { - track.enabled = value; - }); - console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream'); - return this; - }; - return Subscriber; -}(StreamManager_1.StreamManager)); -exports.Subscriber = Subscriber; - -},{"./StreamManager":33}],35:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var LocalRecorderState; -(function (LocalRecorderState) { - LocalRecorderState["READY"] = "READY"; - LocalRecorderState["RECORDING"] = "RECORDING"; - LocalRecorderState["PAUSED"] = "PAUSED"; - LocalRecorderState["FINISHED"] = "FINISHED"; -})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {})); - -},{}],36:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var OpenViduErrorName; -(function (OpenViduErrorName) { - OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; - OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED"; - OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; - OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; - OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; - OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED"; - OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; - OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; - OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; - OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; - OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; - OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED"; - OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; -})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); -var OpenViduError = (function () { - function OpenViduError(name, message) { - this.name = name; - this.message = message; - } - return OpenViduError; -}()); -exports.OpenViduError = OpenViduError; - -},{}],37:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var VideoInsertMode; -(function (VideoInsertMode) { - VideoInsertMode["AFTER"] = "AFTER"; - VideoInsertMode["APPEND"] = "APPEND"; - VideoInsertMode["BEFORE"] = "BEFORE"; - VideoInsertMode["PREPEND"] = "PREPEND"; - VideoInsertMode["REPLACE"] = "REPLACE"; -})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); - -},{}],38:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var ConnectionEvent = (function (_super) { - __extends(ConnectionEvent, _super); - function ConnectionEvent(cancelable, target, type, connection, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.connection = connection; - _this.reason = reason; - return _this; - } - ConnectionEvent.prototype.callDefaultBehaviour = function () { }; - return ConnectionEvent; -}(Event_1.Event)); -exports.ConnectionEvent = ConnectionEvent; - -},{"./Event":39}],39:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Event = (function () { - function Event(cancelable, target, type) { - this.hasBeenPrevented = false; - this.cancelable = cancelable; - this.target = target; - this.type = type; - } - Event.prototype.isDefaultPrevented = function () { - return this.hasBeenPrevented; - }; - Event.prototype.preventDefault = function () { - this.callDefaultBehaviour = function () { }; - this.hasBeenPrevented = true; - }; - return Event; -}()); -exports.Event = Event; - -},{}],40:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var PublisherSpeakingEvent = (function (_super) { - __extends(PublisherSpeakingEvent, _super); - function PublisherSpeakingEvent(target, type, connection, streamId) { - var _this = _super.call(this, false, target, type) || this; - _this.type = type; - _this.connection = connection; - _this.streamId = streamId; - return _this; - } - PublisherSpeakingEvent.prototype.callDefaultBehaviour = function () { }; - return PublisherSpeakingEvent; -}(Event_1.Event)); -exports.PublisherSpeakingEvent = PublisherSpeakingEvent; - -},{"./Event":39}],41:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var RecordingEvent = (function (_super) { - __extends(RecordingEvent, _super); - function RecordingEvent(target, type, id, name) { - var _this = _super.call(this, false, target, type) || this; - _this.id = id; - if (name !== id) { - _this.name = name; - } - return _this; - } - RecordingEvent.prototype.callDefaultBehaviour = function () { }; - return RecordingEvent; -}(Event_1.Event)); -exports.RecordingEvent = RecordingEvent; - -},{"./Event":39}],42:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var SessionDisconnectedEvent = (function (_super) { - __extends(SessionDisconnectedEvent, _super); - function SessionDisconnectedEvent(target, reason) { - var _this = _super.call(this, true, target, 'sessionDisconnected') || this; - _this.reason = reason; - return _this; - } - SessionDisconnectedEvent.prototype.callDefaultBehaviour = function () { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); - var session = this.target; - for (var connectionId in session.remoteConnections) { - if (!!session.remoteConnections[connectionId].stream) { - session.remoteConnections[connectionId].stream.disposeWebRtcPeer(); - session.remoteConnections[connectionId].stream.disposeMediaStream(); - if (session.remoteConnections[connectionId].stream.streamManager) { - session.remoteConnections[connectionId].stream.streamManager.removeAllVideos(); - } - delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId]; - session.remoteConnections[connectionId].dispose(); - } - delete session.remoteConnections[connectionId]; - } - }; - return SessionDisconnectedEvent; -}(Event_1.Event)); -exports.SessionDisconnectedEvent = SessionDisconnectedEvent; - -},{"./Event":39}],43:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var SignalEvent = (function (_super) { - __extends(SignalEvent, _super); - function SignalEvent(target, type, data, from) { - var _this = _super.call(this, false, target, type) || this; - _this.type = type; - _this.data = data; - _this.from = from; - return _this; - } - SignalEvent.prototype.callDefaultBehaviour = function () { }; - return SignalEvent; -}(Event_1.Event)); -exports.SignalEvent = SignalEvent; - -},{"./Event":39}],44:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var Publisher_1 = require("../../OpenVidu/Publisher"); -var Session_1 = require("../../OpenVidu/Session"); -var StreamEvent = (function (_super) { - __extends(StreamEvent, _super); - function StreamEvent(cancelable, target, type, stream, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.stream = stream; - _this.reason = reason; - return _this; - } - StreamEvent.prototype.callDefaultBehaviour = function () { - if (this.type === 'streamDestroyed') { - if (this.target instanceof Session_1.Session) { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); - this.stream.disposeWebRtcPeer(); - } - else if (this.target instanceof Publisher_1.Publisher) { - console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Publisher'"); - this.stream.isLocalStreamReadyToPublish = false; - } - this.stream.disposeMediaStream(); - if (this.stream.streamManager) - this.stream.streamManager.removeAllVideos(); - delete this.stream.session.remoteStreamsCreated[this.stream.streamId]; - var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId]; - if (!!remoteConnection && !!remoteConnection.options) { - var streamOptionsServer = remoteConnection.options.streams; - for (var i = streamOptionsServer.length - 1; i >= 0; --i) { - if (streamOptionsServer[i].id === this.stream.streamId) { - streamOptionsServer.splice(i, 1); - } - } - } - } - }; - return StreamEvent; -}(Event_1.Event)); -exports.StreamEvent = StreamEvent; - -},{"../../OpenVidu/Publisher":30,"../../OpenVidu/Session":31,"./Event":39}],45:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var StreamManagerEvent = (function (_super) { - __extends(StreamManagerEvent, _super); - function StreamManagerEvent(target) { - return _super.call(this, false, target, 'streamPlaying') || this; - } - StreamManagerEvent.prototype.callDefaultBehaviour = function () { }; - return StreamManagerEvent; -}(Event_1.Event)); -exports.StreamManagerEvent = StreamManagerEvent; - -},{"./Event":39}],46:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var Event_1 = require("./Event"); -var VideoElementEvent = (function (_super) { - __extends(VideoElementEvent, _super); - function VideoElementEvent(element, target, type) { - var _this = _super.call(this, false, target, type) || this; - _this.element = element; - return _this; - } - VideoElementEvent.prototype.callDefaultBehaviour = function () { }; - return VideoElementEvent; -}(Event_1.Event)); -exports.VideoElementEvent = VideoElementEvent; - -},{"./Event":39}],47:[function(require,module,exports){ -function Mapper() { - var sources = {}; - this.forEach = function (callback) { - for (var key in sources) { - var source = sources[key]; - for (var key2 in source) - callback(source[key2]); - } - ; - }; - this.get = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return undefined; - return ids[id]; - }; - this.remove = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return; - delete ids[id]; - for (var i in ids) { - return false; - } - delete sources[source]; - }; - this.set = function (value, id, source) { - if (value == undefined) - return this.remove(id, source); - var ids = sources[source]; - if (ids == undefined) - sources[source] = ids = {}; - ids[id] = value; - }; -} -; -Mapper.prototype.pop = function (id, source) { - var value = this.get(id, source); - if (value == undefined) - return undefined; - this.remove(id, source); - return value; -}; -module.exports = Mapper; - -},{}],48:[function(require,module,exports){ -var JsonRpcClient = require('./jsonrpcclient'); -exports.JsonRpcClient = JsonRpcClient; - -},{"./jsonrpcclient":49}],49:[function(require,module,exports){ -var RpcBuilder = require('../'); -var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); -Date.now = Date.now || function () { - return +new Date; -}; -var PING_INTERVAL = 5000; -var RECONNECTING = 'RECONNECTING'; -var CONNECTED = 'CONNECTED'; -var DISCONNECTED = 'DISCONNECTED'; -var Logger = console; -function JsonRpcClient(configuration) { - var self = this; - var wsConfig = configuration.ws; - var notReconnectIfNumLessThan = -1; - var pingNextNum = 0; - var enabledPings = true; - var pingPongStarted = false; - var pingInterval; - var status = DISCONNECTED; - var onreconnecting = wsConfig.onreconnecting; - var onreconnected = wsConfig.onreconnected; - var onconnected = wsConfig.onconnected; - var onerror = wsConfig.onerror; - configuration.rpc.pull = function (params, request) { - request.reply(null, "push"); - }; - wsConfig.onreconnecting = function () { - Logger.debug("--------- ONRECONNECTING -----------"); - if (status === RECONNECTING) { - Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it"); - return; - } - status = RECONNECTING; - if (onreconnecting) { - onreconnecting(); - } - }; - wsConfig.onreconnected = function () { - Logger.debug("--------- ONRECONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - enabledPings = true; - updateNotReconnectIfLessThan(); - usePing(); - if (onreconnected) { - onreconnected(); - } - }; - wsConfig.onconnected = function () { - Logger.debug("--------- ONCONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - enabledPings = true; - usePing(); - if (onconnected) { - onconnected(); - } - }; - wsConfig.onerror = function (error) { - Logger.debug("--------- ONERROR -----------"); - status = DISCONNECTED; - if (onerror) { - onerror(error); - } - }; - var ws = new WebSocketWithReconnection(wsConfig); - Logger.debug('Connecting websocket to URI: ' + wsConfig.uri); - var rpcBuilderOptions = { - request_timeout: configuration.rpc.requestTimeout, - ping_request_timeout: configuration.rpc.heartbeatRequestTimeout - }; - var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) { - Logger.debug('Received request: ' + JSON.stringify(request)); - try { - var func = configuration.rpc[request.method]; - if (func === undefined) { - Logger.error("Method " + request.method + " not registered in client"); - } - else { - func(request.params, request); - } - } - catch (err) { - Logger.error('Exception processing request: ' + JSON.stringify(request)); - Logger.error(err); - } - }); - this.send = function (method, params, callback) { - if (method !== 'ping') { - Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); - } - var requestTime = Date.now(); - rpc.encode(method, params, function (error, result) { - if (error) { - try { - Logger.error("ERROR:" + error.message + " in Request: method:" + - method + " params:" + JSON.stringify(params) + " request:" + - error.request); - if (error.data) { - Logger.error("ERROR DATA:" + JSON.stringify(error.data)); - } - } - catch (e) { } - error.requestTime = requestTime; - } - if (callback) { - if (result != undefined && result.value !== 'pong') { - Logger.debug('Response: ' + JSON.stringify(result)); - } - callback(error, result); - } - }); - }; - function updateNotReconnectIfLessThan() { - Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' + - notReconnectIfNumLessThan + ')'); - notReconnectIfNumLessThan = pingNextNum; - } - function sendPing() { - if (enabledPings) { - var params = null; - if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) { - params = { - interval: configuration.heartbeat || PING_INTERVAL - }; - } - pingNextNum++; - self.send('ping', params, (function (pingNum) { - return function (error, result) { - if (error) { - Logger.debug("Error in ping request #" + pingNum + " (" + - error.message + ")"); - if (pingNum > notReconnectIfNumLessThan) { - enabledPings = false; - updateNotReconnectIfLessThan(); - Logger.debug("Server did not respond to ping message #" + - pingNum + ". Reconnecting... "); - ws.reconnectWs(); - } - } - }; - })(pingNextNum)); - } - else { - Logger.debug("Trying to send ping, but ping is not enabled"); - } - } - function usePing() { - if (!pingPongStarted) { - Logger.debug("Starting ping (if configured)"); - pingPongStarted = true; - if (configuration.heartbeat != undefined) { - pingInterval = setInterval(sendPing, configuration.heartbeat); - sendPing(); - } - } - } - this.close = function () { - Logger.debug("Closing jsonRpcClient explicitly by client"); - if (pingInterval != undefined) { - Logger.debug("Clearing ping interval"); - clearInterval(pingInterval); - } - pingPongStarted = false; - enabledPings = false; - if (configuration.sendCloseMessage) { - Logger.debug("Sending close message"); - this.send('closeSession', null, function (error, result) { - if (error) { - Logger.error("Error sending close message: " + JSON.stringify(error)); - } - ws.close(); - }); - } - else { - ws.close(); - } - }; - this.forceClose = function (millis) { - ws.forceClose(millis); - }; - this.reconnect = function () { - ws.reconnectWs(); - }; -} -module.exports = JsonRpcClient; - -},{"../":52,"./transports/webSocketWithReconnection":51}],50:[function(require,module,exports){ -var WebSocketWithReconnection = require('./webSocketWithReconnection'); -exports.WebSocketWithReconnection = WebSocketWithReconnection; - -},{"./webSocketWithReconnection":51}],51:[function(require,module,exports){ -(function (global){ -"use strict"; -var BrowserWebSocket = global.WebSocket || global.MozWebSocket; -var Logger = console; -var MAX_RETRIES = 2000; -var RETRY_TIME_MS = 3000; -var CONNECTING = 0; -var OPEN = 1; -var CLOSING = 2; -var CLOSED = 3; -function WebSocketWithReconnection(config) { - var closing = false; - var registerMessageHandler; - var wsUri = config.uri; - var useSockJS = config.useSockJS; - var reconnecting = false; - var forcingDisconnection = false; - var ws; - if (useSockJS) { - ws = new SockJS(wsUri); - } - else { - ws = new WebSocket(wsUri); - } - ws.onopen = function () { - logConnected(ws, wsUri); - if (config.onconnected) { - config.onconnected(); - } - }; - ws.onerror = function (error) { - Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error); - if (config.onerror) { - config.onerror(error); - } - }; - function logConnected(ws, wsUri) { - try { - Logger.debug("WebSocket connected to " + wsUri); - } - catch (e) { - Logger.error(e); - } - } - var reconnectionOnClose = function () { - if (ws.readyState === CLOSED) { - if (closing) { - Logger.debug("Connection closed by user"); - } - else { - Logger.debug("Connection closed unexpectecly. Reconnecting..."); - reconnectToSameUri(MAX_RETRIES, 1); - } - } - else { - Logger.debug("Close callback from previous websocket. Ignoring it"); - } - }; - ws.onclose = reconnectionOnClose; - function reconnectToSameUri(maxRetries, numRetries) { - Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); - if (numRetries === 1) { - if (reconnecting) { - Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); - return; - } - else { - reconnecting = true; - } - if (config.onreconnecting) { - config.onreconnecting(); - } - } - if (forcingDisconnection) { - reconnectToNewUri(maxRetries, numRetries, wsUri); - } - else { - if (config.newWsUriOnReconnection) { - config.newWsUriOnReconnection(function (error, newWsUri) { - if (error) { - Logger.debug(error); - setTimeout(function () { - reconnectToSameUri(maxRetries, numRetries + 1); - }, RETRY_TIME_MS); - } - else { - reconnectToNewUri(maxRetries, numRetries, newWsUri); - } - }); - } - else { - reconnectToNewUri(maxRetries, numRetries, wsUri); - } - } - } - function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { - Logger.debug("Reconnection attempt #" + numRetries); - ws.close(); - wsUri = reconnectWsUri || wsUri; - var newWs; - if (useSockJS) { - newWs = new SockJS(wsUri); - } - else { - newWs = new WebSocket(wsUri); - } - newWs.onopen = function () { - Logger.debug("Reconnected after " + numRetries + " attempts..."); - logConnected(newWs, wsUri); - reconnecting = false; - registerMessageHandler(); - if (config.onreconnected()) { - config.onreconnected(); - } - newWs.onclose = reconnectionOnClose; - }; - var onErrorOrClose = function (error) { - Logger.warn("Reconnection error: ", error); - if (numRetries === maxRetries) { - if (config.ondisconnect) { - config.ondisconnect(); - } - } - else { - setTimeout(function () { - reconnectToSameUri(maxRetries, numRetries + 1); - }, RETRY_TIME_MS); - } - }; - newWs.onerror = onErrorOrClose; - ws = newWs; - } - this.close = function () { - closing = true; - ws.close(); - }; - this.forceClose = function (millis) { - Logger.debug("Testing: Force WebSocket close"); - if (millis) { - Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); - var goodWsUri = wsUri; - wsUri = "wss://21.234.12.34.4:443/"; - forcingDisconnection = true; - setTimeout(function () { - Logger.debug("Testing: Recover good wsUri " + goodWsUri); - wsUri = goodWsUri; - forcingDisconnection = false; - }, millis); - } - ws.close(); - }; - this.reconnectWs = function () { - Logger.debug("reconnectWs"); - reconnectToSameUri(MAX_RETRIES, 1, wsUri); - }; - this.send = function (message) { - ws.send(message); - }; - this.addEventListener = function (type, callback) { - registerMessageHandler = function () { - ws.addEventListener(type, callback); - }; - registerMessageHandler(); - }; -} -module.exports = WebSocketWithReconnection; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],52:[function(require,module,exports){ -var defineProperty_IE8 = false; -if (Object.defineProperty) { - try { - Object.defineProperty({}, "x", {}); - } - catch (e) { - defineProperty_IE8 = true; - } -} -if (!Function.prototype.bind) { - Function.prototype.bind = function (oThis) { - if (typeof this !== 'function') { - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { - return fToBind.apply(this instanceof fNOP && oThis - ? this - : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); - }; - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - return fBound; - }; -} -var EventEmitter = require('events').EventEmitter; -var inherits = require('inherits'); -var packers = require('./packers'); -var Mapper = require('./Mapper'); -var BASE_TIMEOUT = 5000; -function unifyResponseMethods(responseMethods) { - if (!responseMethods) - return {}; - for (var key in responseMethods) { - var value = responseMethods[key]; - if (typeof value == 'string') - responseMethods[key] = - { - response: value - }; - } - ; - return responseMethods; -} -; -function unifyTransport(transport) { - if (!transport) - return; - if (transport instanceof Function) - return { send: transport }; - if (transport.send instanceof Function) - return transport; - if (transport.postMessage instanceof Function) { - transport.send = transport.postMessage; - return transport; - } - if (transport.write instanceof Function) { - transport.send = transport.write; - return transport; - } - if (transport.onmessage !== undefined) - return; - if (transport.pause instanceof Function) - return; - throw new SyntaxError("Transport is not a function nor a valid object"); -} -; -function RpcNotification(method, params) { - if (defineProperty_IE8) { - this.method = method; - this.params = params; - } - else { - Object.defineProperty(this, 'method', { value: method, enumerable: true }); - Object.defineProperty(this, 'params', { value: params, enumerable: true }); - } -} -; -function RpcBuilder(packer, options, transport, onRequest) { - var self = this; - if (!packer) - throw new SyntaxError('Packer is not defined'); - if (!packer.pack || !packer.unpack) - throw new SyntaxError('Packer is invalid'); - var responseMethods = unifyResponseMethods(packer.responseMethods); - if (options instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = options; - transport = undefined; - options = undefined; - } - ; - if (options && options.send instanceof Function) { - if (transport && !(transport instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - onRequest = transport; - transport = options; - options = undefined; - } - ; - if (transport instanceof Function) { - if (onRequest != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = transport; - transport = undefined; - } - ; - if (transport && transport.send instanceof Function) - if (onRequest && !(onRequest instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - options = options || {}; - EventEmitter.call(this); - if (onRequest) - this.on('request', onRequest); - if (defineProperty_IE8) - this.peerID = options.peerID; - else - Object.defineProperty(this, 'peerID', { value: options.peerID }); - var max_retries = options.max_retries || 0; - function transportMessage(event) { - self.decode(event.data || event); - } - ; - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - if (transport) { - if (transport.removeEventListener) - transport.removeEventListener('message', transportMessage); - else if (transport.removeListener) - transport.removeListener('data', transportMessage); - } - ; - if (value) { - if (value.addEventListener) - value.addEventListener('message', transportMessage); - else if (value.addListener) - value.addListener('data', transportMessage); - } - ; - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - this.setTransport(transport); - var request_timeout = options.request_timeout || BASE_TIMEOUT; - var ping_request_timeout = options.ping_request_timeout || request_timeout; - var response_timeout = options.response_timeout || BASE_TIMEOUT; - var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT; - var requestID = 0; - var requests = new Mapper(); - var responses = new Mapper(); - var processedResponses = new Mapper(); - var message2Key = {}; - function storeResponse(message, id, dest) { - var response = { - message: message, - timeout: setTimeout(function () { - responses.remove(id, dest); - }, response_timeout) - }; - responses.set(response, id, dest); - } - ; - function storeProcessedResponse(ack, from) { - var timeout = setTimeout(function () { - processedResponses.remove(ack, from); - }, duplicates_timeout); - processedResponses.set(timeout, ack, from); - } - ; - function RpcRequest(method, params, id, from, transport) { - RpcNotification.call(this, method, params); - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - var response = responses.get(id, from); - if (!(transport || self.getTransport())) { - if (defineProperty_IE8) - this.duplicated = Boolean(response); - else - Object.defineProperty(this, 'duplicated', { - value: Boolean(response) - }); - } - var responseMethod = responseMethods[method]; - this.pack = packer.pack.bind(packer, this, id); - this.reply = function (error, result, transport) { - if (error instanceof Function || error && error.send instanceof Function) { - if (result != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = error; - result = null; - error = undefined; - } - else if (result instanceof Function - || result && result.send instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = result; - result = null; - } - ; - transport = unifyTransport(transport); - if (response) - clearTimeout(response.timeout); - if (from != undefined) { - if (error) - error.dest = from; - if (result) - result.dest = from; - } - ; - var message; - if (error || result != undefined) { - if (self.peerID != undefined) { - if (error) - error.from = self.peerID; - else - result.from = self.peerID; - } - if (responseMethod) { - if (responseMethod.error == undefined && error) - message = - { - error: error - }; - else { - var method = error - ? responseMethod.error - : responseMethod.response; - message = - { - method: method, - params: error || result - }; - } - } - else - message = - { - error: error, - result: result - }; - message = packer.pack(message, id); - } - else if (response) - message = response.message; - else - message = packer.pack({ result: null }, id); - storeResponse(message, id, from); - transport = transport || this.getTransport() || self.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - } - ; - inherits(RpcRequest, RpcNotification); - function cancel(message) { - var key = message2Key[message]; - if (!key) - return; - delete message2Key[message]; - var request = requests.pop(key.id, key.dest); - if (!request) - return; - clearTimeout(request.timeout); - storeProcessedResponse(key.id, key.dest); - } - ; - this.cancel = function (message) { - if (message) - return cancel(message); - for (var message in message2Key) - cancel(message); - }; - this.close = function () { - var transport = this.getTransport(); - if (transport && transport.close) - transport.close(); - this.cancel(); - processedResponses.forEach(clearTimeout); - responses.forEach(function (response) { - clearTimeout(response.timeout); - }); - }; - this.encode = function (method, params, dest, transport, callback) { - if (params instanceof Function) { - if (dest != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = params; - transport = undefined; - dest = undefined; - params = undefined; - } - else if (dest instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = dest; - transport = undefined; - dest = undefined; - } - else if (transport instanceof Function) { - if (callback != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = transport; - transport = undefined; - } - ; - if (self.peerID != undefined) { - params = params || {}; - params.from = self.peerID; - } - ; - if (dest != undefined) { - params = params || {}; - params.dest = dest; - } - ; - var message = { - method: method, - params: params - }; - if (callback) { - var id = requestID++; - var retried = 0; - message = packer.pack(message, id); - function dispatchCallback(error, result) { - self.cancel(message); - callback(error, result); - } - ; - var request = { - message: message, - callback: dispatchCallback, - responseMethods: responseMethods[method] || {} - }; - var encode_transport = unifyTransport(transport); - function sendRequest(transport) { - var rt = (method === 'ping' ? ping_request_timeout : request_timeout); - request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++)); - message2Key[message] = { id: id, dest: dest }; - requests.set(request, id, dest); - transport = transport || encode_transport || self.getTransport(); - if (transport) - return transport.send(message); - return message; - } - ; - function retry(transport) { - transport = unifyTransport(transport); - console.warn(retried + ' retry for request message:', message); - var timeout = processedResponses.pop(id, dest); - clearTimeout(timeout); - return sendRequest(transport); - } - ; - function timeout() { - if (retried < max_retries) - return retry(transport); - var error = new Error('Request has timed out'); - error.request = message; - error.retry = retry; - dispatchCallback(error); - } - ; - return sendRequest(transport); - } - ; - message = packer.pack(message); - transport = transport || this.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - this.decode = function (message, transport) { - if (!message) - throw new TypeError("Message is not defined"); - try { - message = packer.unpack(message); - } - catch (e) { - return console.debug(e, message); - } - ; - var id = message.id; - var ack = message.ack; - var method = message.method; - var params = message.params || {}; - var from = params.from; - var dest = params.dest; - if (self.peerID != undefined && from == self.peerID) - return; - if (id == undefined && ack == undefined) { - var notification = new RpcNotification(method, params); - if (self.emit('request', notification)) - return; - return notification; - } - ; - function processRequest() { - transport = unifyTransport(transport) || self.getTransport(); - if (transport) { - var response = responses.get(id, from); - if (response) - return transport.send(response.message); - } - ; - var idAck = (id != undefined) ? id : ack; - var request = new RpcRequest(method, params, idAck, from, transport); - if (self.emit('request', request)) - return; - return request; - } - ; - function processResponse(request, error, result) { - request.callback(error, result); - } - ; - function duplicatedResponse(timeout) { - console.warn("Response already processed", message); - clearTimeout(timeout); - storeProcessedResponse(ack, from); - } - ; - if (method) { - if (dest == undefined || dest == self.peerID) { - var request = requests.get(ack, from); - if (request) { - var responseMethods = request.responseMethods; - if (method == responseMethods.error) - return processResponse(request, params); - if (method == responseMethods.response) - return processResponse(request, null, params); - return processRequest(); - } - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - } - return processRequest(); - } - ; - var error = message.error; - var result = message.result; - if (error && error.dest && error.dest != self.peerID) - return; - if (result && result.dest && result.dest != self.peerID) - return; - var request = requests.get(ack, from); - if (!request) { - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - return console.warn("No callback was defined for this message", message); - } - ; - processResponse(request, error, result); - }; -} -; -inherits(RpcBuilder, EventEmitter); -RpcBuilder.RpcNotification = RpcNotification; -module.exports = RpcBuilder; -var clients = require('./clients'); -var transports = require('./clients/transports'); -RpcBuilder.clients = clients; -RpcBuilder.clients.transports = transports; -RpcBuilder.packers = packers; - -},{"./Mapper":47,"./clients":48,"./clients/transports":50,"./packers":55,"events":1,"inherits":6}],53:[function(require,module,exports){ -function pack(message, id) { - var result = { - jsonrpc: "2.0" - }; - if (message.method) { - result.method = message.method; - if (message.params) - result.params = message.params; - if (id != undefined) - result.id = id; - } - else if (id != undefined) { - if (message.error) { - if (message.result !== undefined) - throw new TypeError("Both result and error are defined"); - result.error = message.error; - } - else if (message.result !== undefined) - result.result = message.result; - else - throw new TypeError("No result or error is defined"); - result.id = id; - } - ; - return JSON.stringify(result); -} -; -function unpack(message) { - var result = message; - if (typeof message === 'string' || message instanceof String) { - result = JSON.parse(message); - } - var version = result.jsonrpc; - if (version !== '2.0') - throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); - if (result.method == undefined) { - if (result.id == undefined) - throw new TypeError("Invalid message: " + message); - var result_defined = result.result !== undefined; - var error_defined = result.error !== undefined; - if (result_defined && error_defined) - throw new TypeError("Both result and error are defined: " + message); - if (!result_defined && !error_defined) - throw new TypeError("No result or error is defined: " + message); - result.ack = result.id; - delete result.id; - } - return result; -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],54:[function(require,module,exports){ -function pack(message) { - throw new TypeError("Not yet implemented"); -} -; -function unpack(message) { - throw new TypeError("Not yet implemented"); -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],55:[function(require,module,exports){ -var JsonRPC = require('./JsonRPC'); -var XmlRPC = require('./XmlRPC'); -exports.JsonRPC = JsonRPC; -exports.XmlRPC = XmlRPC; - -},{"./JsonRPC":53,"./XmlRPC":54}],56:[function(require,module,exports){ -var freeice = require('freeice'); -var inherits = require('inherits'); -var UAParser = require('ua-parser-js'); -var uuid = require('uuid'); -var hark = require('hark'); -var EventEmitter = require('events').EventEmitter; -var recursive = require('merge').recursive.bind(undefined, true); -var sdpTranslator = require('sdp-translator'); -var logger = window.Logger || console; -var MEDIA_CONSTRAINTS = { - audio: true, - video: { - width: 640, - framerate: 15 - } -}; -var ua = (window && window.navigator) ? window.navigator.userAgent : ''; -var parser = new UAParser(ua); -var browser = parser.getBrowser(); -var usePlanB = false; -if (browser.name === 'Chrome' || browser.name === 'Chromium') { - logger.debug(browser.name + ": using SDP PlanB"); - usePlanB = true; -} -function noop(error) { - if (error) - logger.error(error); -} -function trackStop(track) { - track.stop && track.stop(); -} -function streamStop(stream) { - stream.getTracks().forEach(trackStop); -} -var dumpSDP = function (description) { - if (typeof description === 'undefined' || description === null) { - return ''; - } - return 'type: ' + description.type + '\r\n' + description.sdp; -}; -function bufferizeCandidates(pc, onerror) { - var candidatesQueue = []; - pc.addEventListener('signalingstatechange', function () { - if (this.signalingState === 'stable') { - while (candidatesQueue.length) { - var entry = candidatesQueue.shift(); - pc.addIceCandidate(entry.candidate, entry.callback, entry.callback); - } - } - }); - return function (candidate, callback) { - callback = callback || onerror; - switch (pc.signalingState) { - case 'closed': - callback(new Error('PeerConnection object is closed')); - break; - case 'stable': - if (pc.remoteDescription) { - pc.addIceCandidate(candidate, callback, callback); - } - break; - default: - candidatesQueue.push({ - candidate: candidate, - callback: callback - }); - } - }; -} -function removeFIDFromOffer(sdp) { - var n = sdp.indexOf("a=ssrc-group:FID"); - if (n > 0) { - return sdp.slice(0, n); - } - else { - return sdp; - } -} -function getSimulcastInfo(videoStream) { - var videoTracks = videoStream.getVideoTracks(); - if (!videoTracks.length) { - logger.warn('No video tracks available in the video stream'); - return ''; - } - var lines = [ - 'a=x-google-flag:conference', - 'a=ssrc-group:SIM 1 2 3', - 'a=ssrc:1 cname:localVideo', - 'a=ssrc:1 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:1 mslabel:' + videoStream.id, - 'a=ssrc:1 label:' + videoTracks[0].id, - 'a=ssrc:2 cname:localVideo', - 'a=ssrc:2 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:2 mslabel:' + videoStream.id, - 'a=ssrc:2 label:' + videoTracks[0].id, - 'a=ssrc:3 cname:localVideo', - 'a=ssrc:3 msid:' + videoStream.id + ' ' + videoTracks[0].id, - 'a=ssrc:3 mslabel:' + videoStream.id, - 'a=ssrc:3 label:' + videoTracks[0].id - ]; - lines.push(''); - return lines.join('\n'); -} -function WebRtcPeer(mode, options, callback) { - if (!(this instanceof WebRtcPeer)) { - return new WebRtcPeer(mode, options, callback); - } - WebRtcPeer.super_.call(this); - if (options instanceof Function) { - callback = options; - options = undefined; - } - options = options || {}; - callback = (callback || noop).bind(this); - var self = this; - var localVideo = options.localVideo; - var remoteVideo = options.remoteVideo; - var videoStream = options.videoStream; - var audioStream = options.audioStream; - var mediaConstraints = options.mediaConstraints; - var connectionConstraints = options.connectionConstraints; - var pc = options.peerConnection; - var sendSource = options.sendSource || 'webcam'; - var guid = uuid.v4(); - var configuration = recursive({ - iceServers: (!!options.iceServers && options.iceServers.length > 0) ? options.iceServers : freeice() - }, options.configuration); - var onicecandidate = options.onicecandidate; - if (onicecandidate) - this.on('icecandidate', onicecandidate); - var oncandidategatheringdone = options.oncandidategatheringdone; - if (oncandidategatheringdone) { - this.on('candidategatheringdone', oncandidategatheringdone); - } - var simulcast = options.simulcast; - var multistream = options.multistream; - var interop = new sdpTranslator.Interop(); - var candidatesQueueOut = []; - var candidategatheringdone = false; - Object.defineProperties(this, { - 'peerConnection': { - get: function () { - return pc; - } - }, - 'id': { - value: options.id || guid, - writable: false - }, - 'remoteVideo': { - get: function () { - return remoteVideo; - } - }, - 'localVideo': { - get: function () { - return localVideo; - } - }, - 'currentFrame': { - get: function () { - if (!remoteVideo) - return; - if (remoteVideo.readyState < remoteVideo.HAVE_CURRENT_DATA) - throw new Error('No video stream data available'); - var canvas = document.createElement('canvas'); - canvas.width = remoteVideo.videoWidth; - canvas.height = remoteVideo.videoHeight; - canvas.getContext('2d').drawImage(remoteVideo, 0, 0); - return canvas; - } - } - }); - if (!pc) { - pc = new RTCPeerConnection(configuration); - } - pc.addEventListener('icecandidate', function (event) { - var candidate = event.candidate; - if (EventEmitter.listenerCount(self, 'icecandidate') || - EventEmitter.listenerCount(self, 'candidategatheringdone')) { - if (candidate) { - var cand; - if (multistream && usePlanB) { - cand = interop.candidateToUnifiedPlan(candidate); - } - else { - cand = candidate; - } - self.emit('icecandidate', cand); - candidategatheringdone = false; - } - else if (!candidategatheringdone) { - self.emit('candidategatheringdone'); - candidategatheringdone = true; - } - } - else if (!candidategatheringdone) { - candidatesQueueOut.push(candidate); - if (!candidate) - candidategatheringdone = true; - } - }); - pc.onaddstream = options.onaddstream; - pc.onnegotiationneeded = options.onnegotiationneeded; - this.on('newListener', function (event, listener) { - if (event === 'icecandidate' || event === 'candidategatheringdone') { - while (candidatesQueueOut.length) { - var candidate = candidatesQueueOut.shift(); - if (!candidate === (event === 'candidategatheringdone')) { - listener(candidate); - } - } - } - }); - var addIceCandidate = bufferizeCandidates(pc); - this.addIceCandidate = function (iceCandidate, callback) { - var candidate; - if (multistream && usePlanB) { - candidate = interop.candidateToPlanB(iceCandidate); - } - else { - candidate = new RTCIceCandidate(iceCandidate); - } - logger.debug('Remote ICE candidate received', iceCandidate); - callback = (callback || noop).bind(this); - addIceCandidate(candidate, callback); - }; - this.generateOffer = function (callback) { - callback = callback.bind(this); - var offerAudio = true; - var offerVideo = true; - if (mediaConstraints) { - offerAudio = (typeof mediaConstraints.audio === 'boolean') ? - mediaConstraints.audio : true; - offerVideo = (typeof mediaConstraints.video === 'boolean') ? - mediaConstraints.video : true; - } - var browserDependantConstraints = { - offerToReceiveAudio: (mode !== 'sendonly' && offerAudio), - offerToReceiveVideo: (mode !== 'sendonly' && offerVideo) - }; - var constraints = browserDependantConstraints; - logger.debug('constraints: ' + JSON.stringify(constraints)); - pc.createOffer(constraints).then(function (offer) { - logger.debug('Created SDP offer'); - offer = mangleSdpToAddSimulcast(offer); - return pc.setLocalDescription(offer); - }).then(function () { - var localDescription = pc.localDescription; - logger.debug('Local description set', localDescription.sdp); - if (multistream && usePlanB) { - localDescription = interop.toUnifiedPlan(localDescription); - logger.debug('offer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); - } - callback(null, localDescription.sdp, self.processAnswer.bind(self)); - }).catch(callback); - }; - this.getLocalSessionDescriptor = function () { - return pc.localDescription; - }; - this.getRemoteSessionDescriptor = function () { - return pc.remoteDescription; - }; - function setRemoteVideo() { - if (remoteVideo) { - remoteVideo.pause(); - var stream = pc.getRemoteStreams()[0]; - remoteVideo.srcObject = stream; - logger.debug('Remote stream:', stream); - remoteVideo.load(); - } - } - this.showLocalVideo = function () { - localVideo.srcObject = videoStream; - localVideo.muted = true; - }; - this.processAnswer = function (sdpAnswer, callback) { - callback = (callback || noop).bind(this); - var answer = new RTCSessionDescription({ - type: 'answer', - sdp: sdpAnswer - }); - if (multistream && usePlanB) { - var planBAnswer = interop.toPlanB(answer); - logger.debug('asnwer::planB', dumpSDP(planBAnswer)); - answer = planBAnswer; - } - logger.debug('SDP answer received, setting remote description'); - if (pc.signalingState === 'closed') { - return callback('PeerConnection is closed'); - } - pc.setRemoteDescription(answer, function () { - setRemoteVideo(); - callback(); - }, callback); - }; - this.processOffer = function (sdpOffer, callback) { - callback = callback.bind(this); - var offer = new RTCSessionDescription({ - type: 'offer', - sdp: sdpOffer - }); - if (multistream && usePlanB) { - var planBOffer = interop.toPlanB(offer); - logger.debug('offer::planB', dumpSDP(planBOffer)); - offer = planBOffer; - } - logger.debug('SDP offer received, setting remote description'); - if (pc.signalingState === 'closed') { - return callback('PeerConnection is closed'); - } - pc.setRemoteDescription(offer).then(function () { - return setRemoteVideo(); - }).then(function () { - return pc.createAnswer(); - }).then(function (answer) { - answer = mangleSdpToAddSimulcast(answer); - logger.debug('Created SDP answer'); - return pc.setLocalDescription(answer); - }).then(function () { - var localDescription = pc.localDescription; - if (multistream && usePlanB) { - localDescription = interop.toUnifiedPlan(localDescription); - logger.debug('answer::origPlanB->UnifiedPlan', dumpSDP(localDescription)); - } - logger.debug('Local description set', localDescription.sdp); - callback(null, localDescription.sdp); - }).catch(callback); - }; - function mangleSdpToAddSimulcast(answer) { - if (simulcast) { - if (browser.name === 'Chrome' || browser.name === 'Chromium') { - logger.debug('Adding multicast info'); - answer = new RTCSessionDescription({ - 'type': answer.type, - 'sdp': removeFIDFromOffer(answer.sdp) + getSimulcastInfo(videoStream) - }); - } - else { - logger.warn('Simulcast is only available in Chrome browser.'); - } - } - return answer; - } - function start() { - if (pc.signalingState === 'closed') { - callback('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); - } - if (videoStream && localVideo) { - self.showLocalVideo(); - } - if (videoStream) { - pc.addStream(videoStream); - } - if (audioStream) { - pc.addStream(audioStream); - } - var browser = parser.getBrowser(); - if (mode === 'sendonly' && - (browser.name === 'Chrome' || browser.name === 'Chromium') && - browser.major === 39) { - mode = 'sendrecv'; - } - callback(); - } - if (mode !== 'recvonly' && !videoStream && !audioStream) { - function getMedia(constraints) { - if (constraints === undefined) { - constraints = MEDIA_CONSTRAINTS; - } - navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - videoStream = stream; - start(); - }).catch(callback); - } - if (sendSource === 'webcam') { - getMedia(mediaConstraints); - } - else { - getScreenConstraints(sendSource, function (error, constraints_) { - if (error) - return callback(error); - constraints = [mediaConstraints]; - constraints.unshift(constraints_); - getMedia(recursive.apply(undefined, constraints)); - }, guid); - } - } - else { - setTimeout(start, 0); - } - this.on('_dispose', function () { - if (localVideo) { - localVideo.pause(); - localVideo.srcObject = null; - localVideo.load(); - localVideo.muted = false; - } - if (remoteVideo) { - remoteVideo.pause(); - remoteVideo.srcObject = null; - remoteVideo.load(); - } - self.removeAllListeners(); - if (window.cancelChooseDesktopMedia !== undefined) { - window.cancelChooseDesktopMedia(guid); - } - }); -} -inherits(WebRtcPeer, EventEmitter); -function createEnableDescriptor(type) { - var method = 'get' + type + 'Tracks'; - return { - enumerable: true, - get: function () { - if (!this.peerConnection) - return; - var streams = this.peerConnection.getLocalStreams(); - if (!streams.length) - return; - for (var i = 0, stream; stream = streams[i]; i++) { - var tracks = stream[method](); - for (var j = 0, track; track = tracks[j]; j++) - if (!track.enabled) - return false; - } - return true; - }, - set: function (value) { - function trackSetEnable(track) { - track.enabled = value; - } - this.peerConnection.getLocalStreams().forEach(function (stream) { - stream[method]().forEach(trackSetEnable); - }); - } - }; -} -Object.defineProperties(WebRtcPeer.prototype, { - 'enabled': { - enumerable: true, - get: function () { - return this.audioEnabled && this.videoEnabled; - }, - set: function (value) { - this.audioEnabled = this.videoEnabled = value; - } - }, - 'audioEnabled': createEnableDescriptor('Audio'), - 'videoEnabled': createEnableDescriptor('Video') -}); -WebRtcPeer.prototype.getLocalStream = function (index) { - if (this.peerConnection) { - return this.peerConnection.getLocalStreams()[index || 0]; - } -}; -WebRtcPeer.prototype.getRemoteStream = function (index) { - if (this.peerConnection) { - return this.peerConnection.getRemoteStreams()[index || 0]; - } -}; -WebRtcPeer.prototype.dispose = function () { - logger.debug('Disposing WebRtcPeer'); - var pc = this.peerConnection; - try { - if (pc) { - if (pc.signalingState === 'closed') - return; - pc.getLocalStreams().forEach(streamStop); - pc.close(); - } - } - catch (err) { - logger.warn('Exception disposing webrtc peer ' + err); - } - this.emit('_dispose'); -}; -function WebRtcPeerRecvonly(options, callback) { - if (!(this instanceof WebRtcPeerRecvonly)) { - return new WebRtcPeerRecvonly(options, callback); - } - WebRtcPeerRecvonly.super_.call(this, 'recvonly', options, callback); -} -inherits(WebRtcPeerRecvonly, WebRtcPeer); -function WebRtcPeerSendonly(options, callback) { - if (!(this instanceof WebRtcPeerSendonly)) { - return new WebRtcPeerSendonly(options, callback); - } - WebRtcPeerSendonly.super_.call(this, 'sendonly', options, callback); -} -inherits(WebRtcPeerSendonly, WebRtcPeer); -function WebRtcPeerSendrecv(options, callback) { - if (!(this instanceof WebRtcPeerSendrecv)) { - return new WebRtcPeerSendrecv(options, callback); - } - WebRtcPeerSendrecv.super_.call(this, 'sendrecv', options, callback); -} -inherits(WebRtcPeerSendrecv, WebRtcPeer); -function harkUtils(stream, options) { - return hark(stream, options); -} -exports.bufferizeCandidates = bufferizeCandidates; -exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; -exports.WebRtcPeerSendonly = WebRtcPeerSendonly; -exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; -exports.hark = harkUtils; - -},{"events":1,"freeice":2,"hark":5,"inherits":6,"merge":7,"sdp-translator":15,"ua-parser-js":18,"uuid":19}],57:[function(require,module,exports){ -var WebRtcPeer = require('./WebRtcPeer'); -exports.WebRtcPeer = WebRtcPeer; - -},{"./WebRtcPeer":56}],58:[function(require,module,exports){ -window.getScreenId = function (callback) { - if (!!navigator.mozGetUserMedia) { - callback(null, 'firefox', { - video: { - mozMediaSource: 'window', - mediaSource: 'window' - } - }); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeMediaSourceId) { - if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { - callback('permission-denied'); - } - else { - callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId)); - } - window.removeEventListener('message', onIFrameCallback); - } - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); - window.removeEventListener('message', onIFrameCallback); - } - } - setTimeout(postGetSourceIdMessage, 100); -}; -function getScreenConstraints(error, sourceId) { - var screen_constraints = { - audio: false, - video: { - mandatory: { - chromeMediaSource: error ? 'screen' : 'desktop', - maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, - maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 - }, - optional: [] - } - }; - if (sourceId) { - screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; - } - return screen_constraints; -} -var iframe; -function postGetSourceIdMessage() { - if (!iframe) { - loadIFrame(postGetSourceIdMessage); - return; - } - if (!iframe.isLoaded) { - setTimeout(postGetSourceIdMessage, 100); - return; - } - iframe.contentWindow.postMessage({ - captureSourceId: true - }, '*'); -} -function loadIFrame(loadCallback) { - if (iframe) { - loadCallback(); - return; - } - iframe = document.createElement('iframe'); - iframe.onload = function () { - iframe.isLoaded = true; - loadCallback(); - }; - iframe.src = 'https://www.webrtc-experiment.com/getSourceId/'; - iframe.style.display = 'none'; - (document.body || document.documentElement).appendChild(iframe); -} -window.getChromeExtensionStatus = function (callback) { - if (!!navigator.mozGetUserMedia) { - callback('installed-enabled'); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus); - } - window.removeEventListener('message', onIFrameCallback); - } - setTimeout(postGetChromeExtensionStatusMessage, 100); -}; -function postGetChromeExtensionStatusMessage() { - if (!iframe) { - loadIFrame(postGetChromeExtensionStatusMessage); - return; - } - if (!iframe.isLoaded) { - setTimeout(postGetChromeExtensionStatusMessage, 100); - return; - } - iframe.contentWindow.postMessage({ - getChromeExtensionStatus: true - }, '*'); -} -exports.getScreenId = getScreenId; - -},{}],59:[function(require,module,exports){ -var chromeMediaSource = 'screen'; -var screenCallback; -var isFirefox = typeof window.InstallTrigger !== 'undefined'; -var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; -var isChrome = !!window.chrome && !isOpera; -window.addEventListener('message', function (event) { - if (event.origin != window.location.origin) { - return; - } - onMessageCallback(event.data); -}); -function onMessageCallback(data) { - if (data == 'PermissionDeniedError') { - chromeMediaSource = 'PermissionDeniedError'; - if (screenCallback) - return screenCallback('PermissionDeniedError'); - else - throw new Error('PermissionDeniedError'); - } - if (data == 'rtcmulticonnection-extension-loaded') { - chromeMediaSource = 'desktop'; - } - if (data.sourceId && screenCallback) { - screenCallback(sourceId = data.sourceId); - } -} -function isChromeExtensionAvailable(callback) { - if (isFirefox) - return callback(false); - if (chromeMediaSource == 'desktop') - return callback('isFirefox'); - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback('unavailable'); - } - else - callback('available'); - }, 2000); -} -function getSourceId(callback) { - if (!callback) - throw '"callback" parameter is mandatory.'; - if (sourceId) - return callback(sourceId); - screenCallback = callback; - window.postMessage('get-sourceId', '*'); -} -function getChromeExtensionStatus(extensionid, callback) { - if (isFirefox) - return callback('not-chrome'); - if (arguments.length != 2) { - callback = extensionid; - extensionid = 'ajhifddimkapgcifgcodmmfdlknahffk'; - } - var image = document.createElement('img'); - image.src = 'chrome-extension://' + extensionid + '/icon.png'; - image.onload = function () { - chromeMediaSource = 'screen'; - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback(extensionid == extensionid ? 'installed-enabled' : 'installed-disabled'); - } - else - callback('installed-enabled'); - }, 2000); - }; - image.onerror = function () { - callback('not-installed'); - }; -} -function getScreenConstraints(callback) { - sourceId = ''; - var firefoxScreenConstraints = { - mozMediaSource: 'window', - mediaSource: 'window' - }; - if (isFirefox) - return callback(null, firefoxScreenConstraints); - var screen_constraints = { - mandatory: { - chromeMediaSource: chromeMediaSource, - maxWidth: screen.width > 1920 ? screen.width : 1920, - maxHeight: screen.height > 1080 ? screen.height : 1080 - }, - optional: [] - }; - if (chromeMediaSource == 'desktop' && !sourceId) { - getSourceId(function () { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); - }); - return; - } - if (chromeMediaSource == 'desktop') { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - } - callback(null, screen_constraints); -} -exports.getScreenConstraints = getScreenConstraints; -exports.isChromeExtensionAvailable = isChromeExtensionAvailable; -exports.getChromeExtensionStatus = getChromeExtensionStatus; -exports.getSourceId = getSourceId; - -},{}],60:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var platform = require("platform"); -var WebRtcStats = (function () { - function WebRtcStats(stream) { - this.stream = stream; - this.webRtcStatsEnabled = false; - this.statsInterval = 1; - this.stats = { - inbound: { - audio: { - bytesReceived: 0, - packetsReceived: 0, - packetsLost: 0 - }, - video: { - bytesReceived: 0, - packetsReceived: 0, - packetsLost: 0, - framesDecoded: 0, - nackCount: 0 - } - }, - outbound: { - audio: { - bytesSent: 0, - packetsSent: 0, - }, - video: { - bytesSent: 0, - packetsSent: 0, - framesEncoded: 0, - nackCount: 0 - } - } - }; - } - WebRtcStats.prototype.isEnabled = function () { - return this.webRtcStatsEnabled; - }; - WebRtcStats.prototype.initWebRtcStats = function () { - var _this = this; - var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); - if (elastestInstrumentation) { - console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - this.webRtcStatsEnabled = true; - var instrumentation_1 = JSON.parse(elastestInstrumentation); - this.statsInterval = instrumentation_1.webrtc.interval; - console.warn('localStorage item: ' + JSON.stringify(instrumentation_1)); - this.webRtcStatsIntervalId = setInterval(function () { - _this.sendStatsToHttpEndpoint(instrumentation_1); - }, this.statsInterval * 1000); - return; - } - console.debug('WebRtc stats not enabled'); - }; - WebRtcStats.prototype.stopWebRtcStats = function () { - if (this.webRtcStatsEnabled) { - clearInterval(this.webRtcStatsIntervalId); - console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - } - }; - WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { - var _this = this; - var sendPost = function (json) { - var http = new XMLHttpRequest(); - var url = instrumentation.webrtc.httpEndpoint; - http.open('POST', url, true); - http.setRequestHeader('Content-type', 'application/json'); - http.onreadystatechange = function () { - if (http.readyState === 4 && http.status === 200) { - console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId); - } - }; - http.send(json); - }; - var f = function (stats) { - if (platform.name.indexOf('Firefox') !== -1) { - stats.forEach(function (stat) { - var json = {}; - if ((stat.type === 'inbound-rtp') && - (stat.nackCount !== null && - stat.isRemote === false && - stat.id.startsWith('inbound') && - stat.remoteId.startsWith('inbound'))) { - var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; - var jit = stat.jitter * 1000; - var metrics = { - bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, - jitter: jit, - packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, - packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval - }; - var units = { - bytesReceived: 'bytes', - jitter: 'ms', - packetsReceived: 'packets', - packetsLost: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; - metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; - units['framesDecoded'] = 'frames'; - units['nackCount'] = 'packets'; - _this.stats.inbound.video.framesDecoded = stat.framesDecoded; - _this.stats.inbound.video.nackCount = stat.nackCount; - } - _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; - _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; - _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - else if ((stat.type === 'outbound-rtp') && - (stat.isRemote === false && - stat.id.toLowerCase().includes('outbound'))) { - var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, - packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval - }; - var units = { - bytesSent: 'bytes', - packetsSent: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; - units['framesEncoded'] = 'frames'; - _this.stats.outbound.video.framesEncoded = stat.framesEncoded; - } - _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; - _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - }); - } - else if (platform.name.indexOf('Chrome') !== -1) { - for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { - var key = _a[_i]; - var stat = stats[key]; - if (stat.type === 'ssrc') { - var json = {}; - if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || - (stat.mediaType === 'video' && 'qpSum' in stat))) { - var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, - jitter: stat.googJitterBufferMs, - packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, - packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval - }; - var units = { - bytesReceived: 'bytes', - jitter: 'ms', - packetsReceived: 'packets', - packetsLost: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; - metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; - units['framesDecoded'] = 'frames'; - units['nackCount'] = 'packets'; - _this.stats.inbound.video.framesDecoded = stat.framesDecoded; - _this.stats.inbound.video.nackCount = stat.googNacksSent; - } - _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; - _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; - _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - else if ('bytesSent' in stat) { - var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; - var metrics = { - bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, - packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval - }; - var units = { - bytesSent: 'bytes', - packetsSent: 'packets' - }; - if (stat.mediaType === 'video') { - metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; - units['framesEncoded'] = 'frames'; - _this.stats.outbound.video.framesEncoded = stat.framesEncoded; - } - _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; - _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; - json = { - '@timestamp': new Date(stat.timestamp).toISOString(), - 'exec': instrumentation.exec, - 'component': instrumentation.component, - 'stream': 'webRtc', - 'type': metricId, - 'stream_type': 'composed_metrics', - 'units': units - }; - json[metricId] = metrics; - sendPost(JSON.stringify(json)); - } - } - } - } - }; - this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); }); - }; - WebRtcStats.prototype.standardizeReport = function (response) { - if (platform.name.indexOf('Firefox') !== -1) { - return response; - } - var standardReport = {}; - response.result().forEach(function (report) { - var standardStats = { - id: report.id, - timestamp: report.timestamp, - type: report.type - }; - report.names().forEach(function (name) { - standardStats[name] = report.stat(name); - }); - standardReport[standardStats.id] = standardStats; - }); - return standardReport; - }; - WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) { - var _this = this; - if (platform.name.indexOf('Firefox') !== -1) { - return pc.getStats(null, function (response) { - var report = _this.standardizeReport(response); - successCb(report); - }, failureCb); - } - else if (platform.name.indexOf('Chrome') !== -1) { - return pc.getStats(function (response) { - var report = _this.standardizeReport(response); - successCb(report); - }, null, failureCb); - } - }; - return WebRtcStats; -}()); -exports.WebRtcStats = WebRtcStats; - -},{"platform":9}]},{},[26]) -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL21lcmdlL21lcmdlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi9ncmFtbWFyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NkcC10cmFuc2Zvcm0vbGliL3BhcnNlci5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi93cml0ZXIuanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2FycmF5LWVxdWFscy5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNsYXRvci9saWIvaW5kZXguanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL2ludGVyb3AuanMiLCIuLi9ub2RlX21vZHVsZXMvc2RwLXRyYW5zbGF0b3IvbGliL3RyYW5zZm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91YS1wYXJzZXItanMvc3JjL3VhLXBhcnNlci5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9NYXBwZXIuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvSnNvblJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL1htbFJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcy9XZWJSdGNQZWVyLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8uanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2prQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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IjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qIVxyXG4gKiBAbmFtZSBKYXZhU2NyaXB0L05vZGVKUyBNZXJnZSB2MS4yLjBcclxuICogQGF1dGhvciB5ZWlrb3NcclxuICogQHJlcG9zaXRvcnkgaHR0cHM6Ly9naXRodWIuY29tL3llaWtvcy9qcy5tZXJnZVxyXG5cclxuICogQ29weXJpZ2h0IDIwMTQgeWVpa29zIC0gTUlUIGxpY2Vuc2VcclxuICogaHR0cHM6Ly9yYXcuZ2l0aHViLmNvbS95ZWlrb3MvanMubWVyZ2UvbWFzdGVyL0xJQ0VOU0VcclxuICovXHJcblxyXG47KGZ1bmN0aW9uKGlzTm9kZSkge1xyXG5cclxuXHQvKipcclxuXHQgKiBNZXJnZSBvbmUgb3IgbW9yZSBvYmplY3RzIFxyXG5cdCAqIEBwYXJhbSBib29sPyBjbG9uZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCwuLi4gYXJndW1lbnRzXHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0dmFyIFB1YmxpYyA9IGZ1bmN0aW9uKGNsb25lKSB7XHJcblxyXG5cdFx0cmV0dXJuIG1lcmdlKGNsb25lID09PSB0cnVlLCBmYWxzZSwgYXJndW1lbnRzKTtcclxuXHJcblx0fSwgcHVibGljTmFtZSA9ICdtZXJnZSc7XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvciBtb3JlIG9iamVjdHMgcmVjdXJzaXZlbHkgXHJcblx0ICogQHBhcmFtIGJvb2w/IGNsb25lXHJcblx0ICogQHBhcmFtIG1peGVkLC4uLiBhcmd1bWVudHNcclxuXHQgKiBAcmV0dXJuIG9iamVjdFxyXG5cdCAqL1xyXG5cclxuXHRQdWJsaWMucmVjdXJzaXZlID0gZnVuY3Rpb24oY2xvbmUpIHtcclxuXHJcblx0XHRyZXR1cm4gbWVyZ2UoY2xvbmUgPT09IHRydWUsIHRydWUsIGFyZ3VtZW50cyk7XHJcblxyXG5cdH07XHJcblxyXG5cdC8qKlxyXG5cdCAqIENsb25lIHRoZSBpbnB1dCByZW1vdmluZyBhbnkgcmVmZXJlbmNlXHJcblx0ICogQHBhcmFtIG1peGVkIGlucHV0XHJcblx0ICogQHJldHVybiBtaXhlZFxyXG5cdCAqL1xyXG5cclxuXHRQdWJsaWMuY2xvbmUgPSBmdW5jdGlvbihpbnB1dCkge1xyXG5cclxuXHRcdHZhciBvdXRwdXQgPSBpbnB1dCxcclxuXHRcdFx0dHlwZSA9IHR5cGVPZihpbnB1dCksXHJcblx0XHRcdGluZGV4LCBzaXplO1xyXG5cclxuXHRcdGlmICh0eXBlID09PSAnYXJyYXknKSB7XHJcblxyXG5cdFx0XHRvdXRwdXQgPSBbXTtcclxuXHRcdFx0c2l6ZSA9IGlucHV0Lmxlbmd0aDtcclxuXHJcblx0XHRcdGZvciAoaW5kZXg9MDtpbmRleDxzaXplOysraW5kZXgpXHJcblxyXG5cdFx0XHRcdG91dHB1dFtpbmRleF0gPSBQdWJsaWMuY2xvbmUoaW5wdXRbaW5kZXhdKTtcclxuXHJcblx0XHR9IGVsc2UgaWYgKHR5cGUgPT09ICdvYmplY3QnKSB7XHJcblxyXG5cdFx0XHRvdXRwdXQgPSB7fTtcclxuXHJcblx0XHRcdGZvciAoaW5kZXggaW4gaW5wdXQpXHJcblxyXG5cdFx0XHRcdG91dHB1dFtpbmRleF0gPSBQdWJsaWMuY2xvbmUoaW5wdXRbaW5kZXhdKTtcclxuXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIG91dHB1dDtcclxuXHJcblx0fTtcclxuXHJcblx0LyoqXHJcblx0ICogTWVyZ2UgdHdvIG9iamVjdHMgcmVjdXJzaXZlbHlcclxuXHQgKiBAcGFyYW0gbWl4ZWQgaW5wdXRcclxuXHQgKiBAcGFyYW0gbWl4ZWQgZXh0ZW5kXHJcblx0ICogQHJldHVybiBtaXhlZFxyXG5cdCAqL1xyXG5cclxuXHRmdW5jdGlvbiBtZXJnZV9yZWN1cnNpdmUoYmFzZSwgZXh0ZW5kKSB7XHJcblxyXG5cdFx0aWYgKHR5cGVPZihiYXNlKSAhPT0gJ29iamVjdCcpXHJcblxyXG5cdFx0XHRyZXR1cm4gZXh0ZW5kO1xyXG5cclxuXHRcdGZvciAodmFyIGtleSBpbiBleHRlbmQpIHtcclxuXHJcblx0XHRcdGlmICh0eXBlT2YoYmFzZVtrZXldKSA9PT0gJ29iamVjdCcgJiYgdHlwZU9mKGV4dGVuZFtrZXldKSA9PT0gJ29iamVjdCcpIHtcclxuXHJcblx0XHRcdFx0YmFzZVtrZXldID0gbWVyZ2VfcmVjdXJzaXZlKGJhc2Vba2V5XSwgZXh0ZW5kW2tleV0pO1xyXG5cclxuXHRcdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdFx0YmFzZVtrZXldID0gZXh0ZW5kW2tleV07XHJcblxyXG5cdFx0XHR9XHJcblxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBiYXNlO1xyXG5cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1lcmdlIHR3byBvciBtb3JlIG9iamVjdHNcclxuXHQgKiBAcGFyYW0gYm9vbCBjbG9uZVxyXG5cdCAqIEBwYXJhbSBib29sIHJlY3Vyc2l2ZVxyXG5cdCAqIEBwYXJhbSBhcnJheSBhcmd2XHJcblx0ICogQHJldHVybiBvYmplY3RcclxuXHQgKi9cclxuXHJcblx0ZnVuY3Rpb24gbWVyZ2UoY2xvbmUsIHJlY3Vyc2l2ZSwgYXJndikge1xyXG5cclxuXHRcdHZhciByZXN1bHQgPSBhcmd2WzBdLFxyXG5cdFx0XHRzaXplID0gYXJndi5sZW5ndGg7XHJcblxyXG5cdFx0aWYgKGNsb25lIHx8IHR5cGVPZihyZXN1bHQpICE9PSAnb2JqZWN0JylcclxuXHJcblx0XHRcdHJlc3VsdCA9IHt9O1xyXG5cclxuXHRcdGZvciAodmFyIGluZGV4PTA7aW5kZXg8c2l6ZTsrK2luZGV4KSB7XHJcblxyXG5cdFx0XHR2YXIgaXRlbSA9IGFyZ3ZbaW5kZXhdLFxyXG5cclxuXHRcdFx0XHR0eXBlID0gdHlwZU9mKGl0ZW0pO1xyXG5cclxuXHRcdFx0aWYgKHR5cGUgIT09ICdvYmplY3QnKSBjb250aW51ZTtcclxuXHJcblx0XHRcdGZvciAodmFyIGtleSBpbiBpdGVtKSB7XHJcblxyXG5cdFx0XHRcdHZhciBzaXRlbSA9IGNsb25lID8gUHVibGljLmNsb25lKGl0ZW1ba2V5XSkgOiBpdGVtW2tleV07XHJcblxyXG5cdFx0XHRcdGlmIChyZWN1cnNpdmUpIHtcclxuXHJcblx0XHRcdFx0XHRyZXN1bHRba2V5XSA9IG1lcmdlX3JlY3Vyc2l2ZShyZXN1bHRba2V5XSwgc2l0ZW0pO1xyXG5cclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cclxuXHRcdFx0XHRcdHJlc3VsdFtrZXldID0gc2l0ZW07XHJcblxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdH1cclxuXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHJlc3VsdDtcclxuXHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgdHlwZSBvZiB2YXJpYWJsZVxyXG5cdCAqIEBwYXJhbSBtaXhlZCBpbnB1dFxyXG5cdCAqIEByZXR1cm4gc3RyaW5nXHJcblx0ICpcclxuXHQgKiBAc2VlIGh0dHA6Ly9qc3BlcmYuY29tL3R5cGVvZnZhclxyXG5cdCAqL1xyXG5cclxuXHRmdW5jdGlvbiB0eXBlT2YoaW5wdXQpIHtcclxuXHJcblx0XHRyZXR1cm4gKHt9KS50b1N0cmluZy5jYWxsKGlucHV0KS5zbGljZSg4LCAtMSkudG9Mb3dlckNhc2UoKTtcclxuXHJcblx0fVxyXG5cclxuXHRpZiAoaXNOb2RlKSB7XHJcblxyXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBQdWJsaWM7XHJcblxyXG5cdH0gZWxzZSB7XHJcblxyXG5cdFx0d2luZG93W3B1YmxpY05hbWVdID0gUHVibGljO1xyXG5cclxuXHR9XHJcblxyXG59KSh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyk7IiwiLyoqXG4gICMgbm9ybWFsaWNlXG5cbiAgTm9ybWFsaXplIGFuIGljZSBzZXJ2ZXIgY29uZmlndXJhdGlvbiBvYmplY3QgKG9yIHBsYWluIG9sZCBzdHJpbmcpIGludG8gYSBmb3JtYXRcbiAgdGhhdCBpcyB1c2FibGUgaW4gYWxsIGJyb3dzZXJzIHN1cHBvcnRpbmcgV2ViUlRDLiAgUHJpbWFyaWx5IHRoaXMgbW9kdWxlIGlzIGRlc2lnbmVkXG4gIHRvIGhlbHAgd2l0aCB0aGUgdHJhbnNpdGlvbiBvZiB0aGUgYHVybGAgYXR0cmlidXRlIG9mIHRoZSBjb25maWd1cmF0aW9uIG9iamVjdCB0b1xuICB0aGUgYHVybHNgIGF0dHJpYnV0ZS5cblxuICAjIyBFeGFtcGxlIFVzYWdlXG5cbiAgPDw8IGV4YW1wbGVzL3NpbXBsZS5qc1xuXG4qKi9cblxudmFyIHByb3RvY29scyA9IFtcbiAgJ3N0dW46JyxcbiAgJ3R1cm46J1xuXTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihpbnB1dCkge1xuICB2YXIgdXJsID0gKGlucHV0IHx8IHt9KS51cmwgfHwgaW5wdXQ7XG4gIHZhciBwcm90b2NvbDtcbiAgdmFyIHBhcnRzO1xuICB2YXIgb3V0cHV0ID0ge307XG5cbiAgLy8gaWYgd2UgZG9uJ3QgaGF2ZSBhIHN0cmluZyB1cmwsIHRoZW4gYWxsb3cgdGhlIGlucHV0IHRvIHBhc3N0aHJvdWdoXG4gIGlmICh0eXBlb2YgdXJsICE9ICdzdHJpbmcnICYmICghICh1cmwgaW5zdGFuY2VvZiBTdHJpbmcpKSkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIC8vIHRyaW0gdGhlIHVybCBzdHJpbmcsIGFuZCBjb252ZXJ0IHRvIGFuIGFycmF5XG4gIHVybCA9IHVybC50cmltKCk7XG5cbiAgLy8gaWYgdGhlIHByb3RvY29sIGlzIG5vdCBrbm93biwgdGhlbiBwYXNzdGhyb3VnaFxuICBwcm90b2NvbCA9IHByb3RvY29sc1twcm90b2NvbHMuaW5kZXhPZih1cmwuc2xpY2UoMCwgNSkpXTtcbiAgaWYgKCEgcHJvdG9jb2wpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyBub3cgbGV0J3MgYXR0YWNrIHRoZSByZW1haW5pbmcgdXJsIHBhcnRzXG4gIHVybCA9IHVybC5zbGljZSg1KTtcbiAgcGFydHMgPSB1cmwuc3BsaXQoJ0AnKTtcblxuICBvdXRwdXQudXNlcm5hbWUgPSBpbnB1dC51c2VybmFtZTtcbiAgb3V0cHV0LmNyZWRlbnRpYWwgPSBpbnB1dC5jcmVkZW50aWFsO1xuICAvLyBpZiB3ZSBoYXZlIGFuIGF1dGhlbnRpY2F0aW9uIHBhcnQsIHRoZW4gc2V0IHRoZSBjcmVkZW50aWFsc1xuICBpZiAocGFydHMubGVuZ3RoID4gMSkge1xuICAgIHVybCA9IHBhcnRzWzFdO1xuICAgIHBhcnRzID0gcGFydHNbMF0uc3BsaXQoJzonKTtcblxuICAgIC8vIGFkZCB0aGUgb3V0cHV0IGNyZWRlbnRpYWwgYW5kIHVzZXJuYW1lXG4gICAgb3V0cHV0LnVzZXJuYW1lID0gcGFydHNbMF07XG4gICAgb3V0cHV0LmNyZWRlbnRpYWwgPSAoaW5wdXQgfHwge30pLmNyZWRlbnRpYWwgfHwgcGFydHNbMV0gfHwgJyc7XG4gIH1cblxuICBvdXRwdXQudXJsID0gcHJvdG9jb2wgKyB1cmw7XG4gIG91dHB1dC51cmxzID0gWyBvdXRwdXQudXJsIF07XG5cbiAgcmV0dXJuIG91dHB1dDtcbn07XG4iLCIvKiFcbiAqIFBsYXRmb3JtLmpzIDxodHRwczovL210aHMuYmUvcGxhdGZvcm0+XG4gKiBDb3B5cmlnaHQgMjAxNC0yMDE4IEJlbmphbWluIFRhbiA8aHR0cHM6Ly9ibmptbnQ0bi5ub3cuc2gvPlxuICogQ29weXJpZ2h0IDIwMTEtMjAxMyBKb2huLURhdmlkIERhbHRvbiA8aHR0cDovL2FsbHlvdWNhbmxlZXQuY29tLz5cbiAqIEF2YWlsYWJsZSB1bmRlciBNSVQgbGljZW5zZSA8aHR0cHM6Ly9tdGhzLmJlL21pdD5cbiAqL1xuOyhmdW5jdGlvbigpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVybWluZSBpZiB2YWx1ZXMgYXJlIG9mIHRoZSBsYW5ndWFnZSB0eXBlIGBPYmplY3RgLiAqL1xuICB2YXIgb2JqZWN0VHlwZXMgPSB7XG4gICAgJ2Z1bmN0aW9uJzogdHJ1ZSxcbiAgICAnb2JqZWN0JzogdHJ1ZVxuICB9O1xuXG4gIC8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgcm9vdCA9IChvYmplY3RUeXBlc1t0eXBlb2Ygd2luZG93XSAmJiB3aW5kb3cpIHx8IHRoaXM7XG5cbiAgLyoqIEJhY2t1cCBwb3NzaWJsZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgb2xkUm9vdCA9IHJvb3Q7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBleHBvcnRzYC4gKi9cbiAgdmFyIGZyZWVFeHBvcnRzID0gb2JqZWN0VHlwZXNbdHlwZW9mIGV4cG9ydHNdICYmIGV4cG9ydHM7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBtb2R1bGVgLiAqL1xuICB2YXIgZnJlZU1vZHVsZSA9IG9iamVjdFR5cGVzW3R5cGVvZiBtb2R1bGVdICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzIG9yIEJyb3dzZXJpZmllZCBjb2RlIGFuZCB1c2UgaXQgYXMgYHJvb3RgLiAqL1xuICB2YXIgZnJlZUdsb2JhbCA9IGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUgJiYgdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWw7XG4gIGlmIChmcmVlR2xvYmFsICYmIChmcmVlR2xvYmFsLmdsb2JhbCA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLndpbmRvdyA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLnNlbGYgPT09IGZyZWVHbG9iYWwpKSB7XG4gICAgcm9vdCA9IGZyZWVHbG9iYWw7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBhcyB0aGUgbWF4aW11bSBsZW5ndGggb2YgYW4gYXJyYXktbGlrZSBvYmplY3QuXG4gICAqIFNlZSB0aGUgW0VTNiBzcGVjXShodHRwOi8vcGVvcGxlLm1vemlsbGEub3JnL35qb3JlbmRvcmZmL2VzNi1kcmFmdC5odG1sI3NlYy10b2xlbmd0aClcbiAgICogZm9yIG1vcmUgZGV0YWlscy5cbiAgICovXG4gIHZhciBtYXhTYWZlSW50ZWdlciA9IE1hdGgucG93KDIsIDUzKSAtIDE7XG5cbiAgLyoqIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBkZXRlY3QgT3BlcmEuICovXG4gIHZhciByZU9wZXJhID0gL1xcYk9wZXJhLztcblxuICAvKiogUG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHRoaXNCaW5kaW5nID0gdGhpcztcblxuICAvKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xuICB2YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4gIC8qKiBVc2VkIHRvIGNoZWNrIGZvciBvd24gcHJvcGVydGllcyBvZiBhbiBvYmplY3QuICovXG4gIHZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4gIC8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIHZhbHVlcy4gKi9cbiAgdmFyIHRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENhcGl0YWxpemVzIGEgc3RyaW5nIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGNhcGl0YWxpemVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gU3RyaW5nKHN0cmluZyk7XG4gICAgcmV0dXJuIHN0cmluZy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0cmluZy5zbGljZSgxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHV0aWxpdHkgZnVuY3Rpb24gdG8gY2xlYW4gdXAgdGhlIE9TIG5hbWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcyBUaGUgT1MgbmFtZSB0byBjbGVhbiB1cC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwYXR0ZXJuXSBBIGBSZWdFeHBgIHBhdHRlcm4gbWF0Y2hpbmcgdGhlIE9TIG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbGFiZWxdIEEgbGFiZWwgZm9yIHRoZSBPUy5cbiAgICovXG4gIGZ1bmN0aW9uIGNsZWFudXBPUyhvcywgcGF0dGVybiwgbGFiZWwpIHtcbiAgICAvLyBQbGF0Zm9ybSB0b2tlbnMgYXJlIGRlZmluZWQgYXQ6XG4gICAgLy8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgLy8gaHR0cDovL3dlYi5hcmNoaXZlLm9yZy93ZWIvMjAwODExMjIwNTM5NTAvaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgdmFyIGRhdGEgPSB7XG4gICAgICAnMTAuMCc6ICcxMCcsXG4gICAgICAnNi40JzogICcxMCBUZWNobmljYWwgUHJldmlldycsXG4gICAgICAnNi4zJzogICc4LjEnLFxuICAgICAgJzYuMic6ICAnOCcsXG4gICAgICAnNi4xJzogICdTZXJ2ZXIgMjAwOCBSMiAvIDcnLFxuICAgICAgJzYuMCc6ICAnU2VydmVyIDIwMDggLyBWaXN0YScsXG4gICAgICAnNS4yJzogICdTZXJ2ZXIgMjAwMyAvIFhQIDY0LWJpdCcsXG4gICAgICAnNS4xJzogICdYUCcsXG4gICAgICAnNS4wMSc6ICcyMDAwIFNQMScsXG4gICAgICAnNS4wJzogICcyMDAwJyxcbiAgICAgICc0LjAnOiAgJ05UJyxcbiAgICAgICc0LjkwJzogJ01FJ1xuICAgIH07XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgdmVyc2lvbiBmcm9tIHBsYXRmb3JtIHRva2Vucy5cbiAgICBpZiAocGF0dGVybiAmJiBsYWJlbCAmJiAvXldpbi9pLnRlc3Qob3MpICYmICEvXldpbmRvd3MgUGhvbmUgL2kudGVzdChvcykgJiZcbiAgICAgICAgKGRhdGEgPSBkYXRhWy9bXFxkLl0rJC8uZXhlYyhvcyldKSkge1xuICAgICAgb3MgPSAnV2luZG93cyAnICsgZGF0YTtcbiAgICB9XG4gICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgb3MgPSBTdHJpbmcob3MpO1xuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwpIHtcbiAgICAgIG9zID0gb3MucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgbGFiZWwpO1xuICAgIH1cblxuICAgIG9zID0gZm9ybWF0KFxuICAgICAgb3MucmVwbGFjZSgvIGNlJC9pLCAnIENFJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYmhwdy9pLCAnd2ViJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hY2ludG9zaFxcYi8sICdNYWMgT1MnKVxuICAgICAgICAucmVwbGFjZSgvX1Bvd2VyUENcXGIvaSwgJyBPUycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoT1MgWCkgW14gXFxkXSsvaSwgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hYyAoT1MgWClcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFwvKFxcZCkvLCAnICQxJylcbiAgICAgICAgLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICAucmVwbGFjZSgvKD86IEJlUEN8WyAuXSpmY1sgXFxkLl0rKSQvaSwgJycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJ4ODZcXC42NFxcYi9naSwgJ3g4Nl82NCcpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoV2luZG93cyBQaG9uZSkgT1NcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKENocm9tZSBPUyBcXHcrKSBbXFxkLl0rXFxiLywgJyQxJylcbiAgICAgICAgLnNwbGl0KCcgb24gJylbMF1cbiAgICApO1xuXG4gICAgcmV0dXJuIG9zO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGl0ZXJhdGlvbiB1dGlsaXR5IGZvciBhcnJheXMgYW5kIG9iamVjdHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIGVhY2gob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBvYmplY3QgPyBvYmplY3QubGVuZ3RoIDogMDtcblxuICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInICYmIGxlbmd0aCA+IC0xICYmIGxlbmd0aCA8PSBtYXhTYWZlSW50ZWdlcikge1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2luZGV4XSwgaW5kZXgsIG9iamVjdCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvck93bihvYmplY3QsIGNhbGxiYWNrKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJpbSBhbmQgY29uZGl0aW9uYWxseSBjYXBpdGFsaXplIHN0cmluZyB2YWx1ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBmb3JtYXQuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBmb3JtYXR0ZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gZm9ybWF0KHN0cmluZykge1xuICAgIHN0cmluZyA9IHRyaW0oc3RyaW5nKTtcbiAgICByZXR1cm4gL14oPzp3ZWJPU3xpKD86T1N8UCkpLy50ZXN0KHN0cmluZylcbiAgICAgID8gc3RyaW5nXG4gICAgICA6IGNhcGl0YWxpemUoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJdGVyYXRlcyBvdmVyIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzLCBleGVjdXRpbmcgdGhlIGBjYWxsYmFja2AgZm9yIGVhY2guXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBleGVjdXRlZCBwZXIgb3duIHByb3BlcnR5LlxuICAgKi9cbiAgZnVuY3Rpb24gZm9yT3duKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2tleV0sIGtleSwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgaW50ZXJuYWwgYFtbQ2xhc3NdXWAgb2YgYSB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBgW1tDbGFzc11dYC5cbiAgICovXG4gIGZ1bmN0aW9uIGdldENsYXNzT2YodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPT0gbnVsbFxuICAgICAgPyBjYXBpdGFsaXplKHZhbHVlKVxuICAgICAgOiB0b1N0cmluZy5jYWxsKHZhbHVlKS5zbGljZSg4LCAtMSk7XG4gIH1cblxuICAvKipcbiAgICogSG9zdCBvYmplY3RzIGNhbiByZXR1cm4gdHlwZSB2YWx1ZXMgdGhhdCBhcmUgZGlmZmVyZW50IGZyb20gdGhlaXIgYWN0dWFsXG4gICAqIGRhdGEgdHlwZS4gVGhlIG9iamVjdHMgd2UgYXJlIGNvbmNlcm5lZCB3aXRoIHVzdWFsbHkgcmV0dXJuIG5vbi1wcmltaXRpdmVcbiAgICogdHlwZXMgb2YgXCJvYmplY3RcIiwgXCJmdW5jdGlvblwiLCBvciBcInVua25vd25cIi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSBvYmplY3QgVGhlIG93bmVyIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3BlcnR5IFRoZSBwcm9wZXJ0eSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyBhIG5vbi1wcmltaXRpdmUsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGlzSG9zdFR5cGUob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgIHZhciB0eXBlID0gb2JqZWN0ICE9IG51bGwgPyB0eXBlb2Ygb2JqZWN0W3Byb3BlcnR5XSA6ICdudW1iZXInO1xuICAgIHJldHVybiAhL14oPzpib29sZWFufG51bWJlcnxzdHJpbmd8dW5kZWZpbmVkKSQvLnRlc3QodHlwZSkgJiZcbiAgICAgICh0eXBlID09ICdvYmplY3QnID8gISFvYmplY3RbcHJvcGVydHldIDogdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUHJlcGFyZXMgYSBzdHJpbmcgZm9yIHVzZSBpbiBhIGBSZWdFeHBgIGJ5IG1ha2luZyBoeXBoZW5zIGFuZCBzcGFjZXMgb3B0aW9uYWwuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBxdWFsaWZ5LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgcXVhbGlmaWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIHF1YWxpZnkoc3RyaW5nKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoLyhbIC1dKSg/ISQpL2csICckMT8nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGJhcmUtYm9uZXMgYEFycmF5I3JlZHVjZWAgbGlrZSB1dGlsaXR5IGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHsqfSBUaGUgYWNjdW11bGF0ZWQgcmVzdWx0LlxuICAgKi9cbiAgZnVuY3Rpb24gcmVkdWNlKGFycmF5LCBjYWxsYmFjaykge1xuICAgIHZhciBhY2N1bXVsYXRvciA9IG51bGw7XG4gICAgZWFjaChhcnJheSwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICBhY2N1bXVsYXRvciA9IGNhbGxiYWNrKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGFycmF5KTtcbiAgICB9KTtcbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIGZyb20gYSBzdHJpbmcuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byB0cmltLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgdHJpbW1lZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiB0cmltKHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC9eICt8ICskL2csICcnKTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IHBsYXRmb3JtIG9iamVjdC5cbiAgICpcbiAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAqIEBwYXJhbSB7T2JqZWN0fHN0cmluZ30gW3VhPW5hdmlnYXRvci51c2VyQWdlbnRdIFRoZSB1c2VyIGFnZW50IHN0cmluZyBvclxuICAgKiAgY29udGV4dCBvYmplY3QuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IEEgcGxhdGZvcm0gb2JqZWN0LlxuICAgKi9cbiAgZnVuY3Rpb24gcGFyc2UodWEpIHtcblxuICAgIC8qKiBUaGUgZW52aXJvbm1lbnQgY29udGV4dCBvYmplY3QuICovXG4gICAgdmFyIGNvbnRleHQgPSByb290O1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGEgY3VzdG9tIGNvbnRleHQgaXMgcHJvdmlkZWQuICovXG4gICAgdmFyIGlzQ3VzdG9tQ29udGV4dCA9IHVhICYmIHR5cGVvZiB1YSA9PSAnb2JqZWN0JyAmJiBnZXRDbGFzc09mKHVhKSAhPSAnU3RyaW5nJztcblxuICAgIC8vIEp1Z2dsZSBhcmd1bWVudHMuXG4gICAgaWYgKGlzQ3VzdG9tQ29udGV4dCkge1xuICAgICAgY29udGV4dCA9IHVhO1xuICAgICAgdWEgPSBudWxsO1xuICAgIH1cblxuICAgIC8qKiBCcm93c2VyIG5hdmlnYXRvciBvYmplY3QuICovXG4gICAgdmFyIG5hdiA9IGNvbnRleHQubmF2aWdhdG9yIHx8IHt9O1xuXG4gICAgLyoqIEJyb3dzZXIgdXNlciBhZ2VudCBzdHJpbmcuICovXG4gICAgdmFyIHVzZXJBZ2VudCA9IG5hdi51c2VyQWdlbnQgfHwgJyc7XG5cbiAgICB1YSB8fCAodWEgPSB1c2VyQWdlbnQpO1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGB0aGlzQmluZGluZ2AgaXMgdGhlIFtNb2R1bGVTY29wZV0uICovXG4gICAgdmFyIGlzTW9kdWxlU2NvcGUgPSBpc0N1c3RvbUNvbnRleHQgfHwgdGhpc0JpbmRpbmcgPT0gb2xkUm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGRldGVjdCBpZiBicm93c2VyIGlzIGxpa2UgQ2hyb21lLiAqL1xuICAgIHZhciBsaWtlQ2hyb21lID0gaXNDdXN0b21Db250ZXh0XG4gICAgICA/ICEhbmF2Lmxpa2VDaHJvbWVcbiAgICAgIDogL1xcYkNocm9tZVxcYi8udGVzdCh1YSkgJiYgIS9pbnRlcm5hbHxcXG4vaS50ZXN0KHRvU3RyaW5nLnRvU3RyaW5nKCkpO1xuXG4gICAgLyoqIEludGVybmFsIGBbW0NsYXNzXV1gIHZhbHVlIHNob3J0Y3V0cy4gKi9cbiAgICB2YXIgb2JqZWN0Q2xhc3MgPSAnT2JqZWN0JyxcbiAgICAgICAgYWlyUnVudGltZUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnU2NyaXB0QnJpZGdpbmdQcm94eU9iamVjdCcsXG4gICAgICAgIGVudmlyb0NsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnRW52aXJvbm1lbnQnLFxuICAgICAgICBqYXZhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIGNvbnRleHQuamF2YSkgPyAnSmF2YVBhY2thZ2UnIDogZ2V0Q2xhc3NPZihjb250ZXh0LmphdmEpLFxuICAgICAgICBwaGFudG9tQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdSdW50aW1lT2JqZWN0JztcblxuICAgIC8qKiBEZXRlY3QgSmF2YSBlbnZpcm9ubWVudHMuICovXG4gICAgdmFyIGphdmEgPSAvXFxiSmF2YS8udGVzdChqYXZhQ2xhc3MpICYmIGNvbnRleHQuamF2YTtcblxuICAgIC8qKiBEZXRlY3QgUmhpbm8uICovXG4gICAgdmFyIHJoaW5vID0gamF2YSAmJiBnZXRDbGFzc09mKGNvbnRleHQuZW52aXJvbm1lbnQpID09IGVudmlyb0NsYXNzO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBhbHBoYS4gKi9cbiAgICB2YXIgYWxwaGEgPSBqYXZhID8gJ2EnIDogJ1xcdTAzYjEnO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBiZXRhLiAqL1xuICAgIHZhciBiZXRhID0gamF2YSA/ICdiJyA6ICdcXHUwM2IyJztcblxuICAgIC8qKiBCcm93c2VyIGRvY3VtZW50IG9iamVjdC4gKi9cbiAgICB2YXIgZG9jID0gY29udGV4dC5kb2N1bWVudCB8fCB7fTtcblxuICAgIC8qKlxuICAgICAqIERldGVjdCBPcGVyYSBicm93c2VyIChQcmVzdG8tYmFzZWQpLlxuICAgICAqIGh0dHA6Ly93d3cuaG93dG9jcmVhdGUuY28udWsvb3BlcmFTdHVmZi9vcGVyYU9iamVjdC5odG1sXG4gICAgICogaHR0cDovL2Rldi5vcGVyYS5jb20vYXJ0aWNsZXMvdmlldy9vcGVyYS1taW5pLXdlYi1jb250ZW50LWF1dGhvcmluZy1ndWlkZWxpbmVzLyNvcGVyYW1pbmlcbiAgICAgKi9cbiAgICB2YXIgb3BlcmEgPSBjb250ZXh0Lm9wZXJhbWluaSB8fCBjb250ZXh0Lm9wZXJhO1xuXG4gICAgLyoqIE9wZXJhIGBbW0NsYXNzXV1gLiAqL1xuICAgIHZhciBvcGVyYUNsYXNzID0gcmVPcGVyYS50ZXN0KG9wZXJhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIG9wZXJhKSA/IG9wZXJhWydbW0NsYXNzXV0nXSA6IGdldENsYXNzT2Yob3BlcmEpKVxuICAgICAgPyBvcGVyYUNsYXNzXG4gICAgICA6IChvcGVyYSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqIFRlbXBvcmFyeSB2YXJpYWJsZSB1c2VkIG92ZXIgdGhlIHNjcmlwdCdzIGxpZmV0aW1lLiAqL1xuICAgIHZhciBkYXRhO1xuXG4gICAgLyoqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlLiAqL1xuICAgIHZhciBhcmNoID0gdWE7XG5cbiAgICAvKiogUGxhdGZvcm0gZGVzY3JpcHRpb24gYXJyYXkuICovXG4gICAgdmFyIGRlc2NyaXB0aW9uID0gW107XG5cbiAgICAvKiogUGxhdGZvcm0gYWxwaGEvYmV0YSBpbmRpY2F0b3IuICovXG4gICAgdmFyIHByZXJlbGVhc2UgPSBudWxsO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSB0aGF0IGVudmlyb25tZW50IGZlYXR1cmVzIHNob3VsZCBiZSB1c2VkIHRvIHJlc29sdmUgdGhlIHBsYXRmb3JtLiAqL1xuICAgIHZhciB1c2VGZWF0dXJlcyA9IHVhID09IHVzZXJBZ2VudDtcblxuICAgIC8qKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLiAqL1xuICAgIHZhciB2ZXJzaW9uID0gdXNlRmVhdHVyZXMgJiYgb3BlcmEgJiYgdHlwZW9mIG9wZXJhLnZlcnNpb24gPT0gJ2Z1bmN0aW9uJyAmJiBvcGVyYS52ZXJzaW9uKCk7XG5cbiAgICAvKiogQSBmbGFnIHRvIGluZGljYXRlIGlmIHRoZSBPUyBlbmRzIHdpdGggXCIvIFZlcnNpb25cIiAqL1xuICAgIHZhciBpc1NwZWNpYWxDYXNlZE9TO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBsYXlvdXQgZW5naW5lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbGF5b3V0ID0gZ2V0TGF5b3V0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0VkZ2VIVE1MJywgJ3BhdHRlcm4nOiAnRWRnZScgfSxcbiAgICAgICdUcmlkZW50JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1dlYktpdCcsICdwYXR0ZXJuJzogJ0FwcGxlV2ViS2l0JyB9LFxuICAgICAgJ2lDYWInLFxuICAgICAgJ1ByZXN0bycsXG4gICAgICAnTmV0RnJvbnQnLFxuICAgICAgJ1Rhc21hbicsXG4gICAgICAnS0hUTUwnLFxuICAgICAgJ0dlY2tvJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBicm93c2VyIG5hbWVzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBuYW1lID0gZ2V0TmFtZShbXG4gICAgICAnQWRvYmUgQUlSJyxcbiAgICAgICdBcm9yYScsXG4gICAgICAnQXZhbnQgQnJvd3NlcicsXG4gICAgICAnQnJlYWNoJyxcbiAgICAgICdDYW1pbm8nLFxuICAgICAgJ0VsZWN0cm9uJyxcbiAgICAgICdFcGlwaGFueScsXG4gICAgICAnRmVubmVjJyxcbiAgICAgICdGbG9jaycsXG4gICAgICAnR2FsZW9uJyxcbiAgICAgICdHcmVlbkJyb3dzZXInLFxuICAgICAgJ2lDYWInLFxuICAgICAgJ0ljZXdlYXNlbCcsXG4gICAgICAnSy1NZWxlb24nLFxuICAgICAgJ0tvbnF1ZXJvcicsXG4gICAgICAnTHVuYXNjYXBlJyxcbiAgICAgICdNYXh0aG9uJyxcbiAgICAgIHsgJ2xhYmVsJzogJ01pY3Jvc29mdCBFZGdlJywgJ3BhdHRlcm4nOiAnRWRnZScgfSxcbiAgICAgICdNaWRvcmknLFxuICAgICAgJ05vb2sgQnJvd3NlcicsXG4gICAgICAnUGFsZU1vb24nLFxuICAgICAgJ1BoYW50b21KUycsXG4gICAgICAnUmF2ZW4nLFxuICAgICAgJ1Jla29ucScsXG4gICAgICAnUm9ja01lbHQnLFxuICAgICAgeyAnbGFiZWwnOiAnU2Ftc3VuZyBJbnRlcm5ldCcsICdwYXR0ZXJuJzogJ1NhbXN1bmdCcm93c2VyJyB9LFxuICAgICAgJ1NlYU1vbmtleScsXG4gICAgICB7ICdsYWJlbCc6ICdTaWxrJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ1NsZWlwbmlyJyxcbiAgICAgICdTbGltQnJvd3NlcicsXG4gICAgICB7ICdsYWJlbCc6ICdTUldhcmUgSXJvbicsICdwYXR0ZXJuJzogJ0lyb24nIH0sXG4gICAgICAnU3VucmlzZScsXG4gICAgICAnU3dpZnRmb3gnLFxuICAgICAgJ1dhdGVyZm94JyxcbiAgICAgICdXZWJQb3NpdGl2ZScsXG4gICAgICAnT3BlcmEgTWluaScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYSBNaW5pJywgJ3BhdHRlcm4nOiAnT1BpT1MnIH0sXG4gICAgICAnT3BlcmEnLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEnLCAncGF0dGVybic6ICdPUFInIH0sXG4gICAgICAnQ2hyb21lJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBNb2JpbGUnLCAncGF0dGVybic6ICcoPzpDcmlPU3xDck1vKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0ZpcmVmb3gnLCAncGF0dGVybic6ICcoPzpGaXJlZm94fE1pbmVmaWVsZCknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94IGZvciBpT1MnLCAncGF0dGVybic6ICdGeGlPUycgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0lFJywgJ3BhdHRlcm4nOiAnSUVNb2JpbGUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ01TSUUnIH0sXG4gICAgICAnU2FmYXJpJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBwcm9kdWN0cyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgcHJvZHVjdCA9IGdldFByb2R1Y3QoW1xuICAgICAgeyAnbGFiZWwnOiAnQmxhY2tCZXJyeScsICdwYXR0ZXJuJzogJ0JCMTAnIH0sXG4gICAgICAnQmxhY2tCZXJyeScsXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUycsICdwYXR0ZXJuJzogJ0dULUk5MDAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMyJywgJ3BhdHRlcm4nOiAnR1QtSTkxMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzMnLCAncGF0dGVybic6ICdHVC1JOTMwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNCcsICdwYXR0ZXJuJzogJ0dULUk5NTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM1JywgJ3BhdHRlcm4nOiAnU00tRzkwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNicsICdwYXR0ZXJuJzogJ1NNLUc5MjAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYgRWRnZScsICdwYXR0ZXJuJzogJ1NNLUc5MjUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzcnLCAncGF0dGVybic6ICdTTS1HOTMwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTM1JyB9LFxuICAgICAgJ0dvb2dsZSBUVicsXG4gICAgICAnTHVtaWEnLFxuICAgICAgJ2lQYWQnLFxuICAgICAgJ2lQb2QnLFxuICAgICAgJ2lQaG9uZScsXG4gICAgICAnS2luZGxlJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0tpbmRsZSBGaXJlJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ05leHVzJyxcbiAgICAgICdOb29rJyxcbiAgICAgICdQbGF5Qm9vaycsXG4gICAgICAnUGxheVN0YXRpb24gVml0YScsXG4gICAgICAnUGxheVN0YXRpb24nLFxuICAgICAgJ1RvdWNoUGFkJyxcbiAgICAgICdUcmFuc2Zvcm1lcicsXG4gICAgICB7ICdsYWJlbCc6ICdXaWkgVScsICdwYXR0ZXJuJzogJ1dpaVUnIH0sXG4gICAgICAnV2lpJyxcbiAgICAgICdYYm94IE9uZScsXG4gICAgICB7ICdsYWJlbCc6ICdYYm94IDM2MCcsICdwYXR0ZXJuJzogJ1hib3gnIH0sXG4gICAgICAnWG9vbSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgbWFudWZhY3R1cmVycy4gKi9cbiAgICB2YXIgbWFudWZhY3R1cmVyID0gZ2V0TWFudWZhY3R1cmVyKHtcbiAgICAgICdBcHBsZSc6IHsgJ2lQYWQnOiAxLCAnaVBob25lJzogMSwgJ2lQb2QnOiAxIH0sXG4gICAgICAnQXJjaG9zJzoge30sXG4gICAgICAnQW1hem9uJzogeyAnS2luZGxlJzogMSwgJ0tpbmRsZSBGaXJlJzogMSB9LFxuICAgICAgJ0FzdXMnOiB7ICdUcmFuc2Zvcm1lcic6IDEgfSxcbiAgICAgICdCYXJuZXMgJiBOb2JsZSc6IHsgJ05vb2snOiAxIH0sXG4gICAgICAnQmxhY2tCZXJyeSc6IHsgJ1BsYXlCb29rJzogMSB9LFxuICAgICAgJ0dvb2dsZSc6IHsgJ0dvb2dsZSBUVic6IDEsICdOZXh1cyc6IDEgfSxcbiAgICAgICdIUCc6IHsgJ1RvdWNoUGFkJzogMSB9LFxuICAgICAgJ0hUQyc6IHt9LFxuICAgICAgJ0xHJzoge30sXG4gICAgICAnTWljcm9zb2Z0JzogeyAnWGJveCc6IDEsICdYYm94IE9uZSc6IDEgfSxcbiAgICAgICdNb3Rvcm9sYSc6IHsgJ1hvb20nOiAxIH0sXG4gICAgICAnTmludGVuZG8nOiB7ICdXaWkgVSc6IDEsICAnV2lpJzogMSB9LFxuICAgICAgJ05va2lhJzogeyAnTHVtaWEnOiAxIH0sXG4gICAgICAnU2Ftc3VuZyc6IHsgJ0dhbGF4eSBTJzogMSwgJ0dhbGF4eSBTMic6IDEsICdHYWxheHkgUzMnOiAxLCAnR2FsYXh5IFM0JzogMSB9LFxuICAgICAgJ1NvbnknOiB7ICdQbGF5U3RhdGlvbic6IDEsICdQbGF5U3RhdGlvbiBWaXRhJzogMSB9XG4gICAgfSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG9wZXJhdGluZyBzeXN0ZW1zIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBvcyA9IGdldE9TKFtcbiAgICAgICdXaW5kb3dzIFBob25lJyxcbiAgICAgICdBbmRyb2lkJyxcbiAgICAgICdDZW50T1MnLFxuICAgICAgeyAnbGFiZWwnOiAnQ2hyb21lIE9TJywgJ3BhdHRlcm4nOiAnQ3JPUycgfSxcbiAgICAgICdEZWJpYW4nLFxuICAgICAgJ0ZlZG9yYScsXG4gICAgICAnRnJlZUJTRCcsXG4gICAgICAnR2VudG9vJyxcbiAgICAgICdIYWlrdScsXG4gICAgICAnS3VidW50dScsXG4gICAgICAnTGludXggTWludCcsXG4gICAgICAnT3BlbkJTRCcsXG4gICAgICAnUmVkIEhhdCcsXG4gICAgICAnU3VTRScsXG4gICAgICAnVWJ1bnR1JyxcbiAgICAgICdYdWJ1bnR1JyxcbiAgICAgICdDeWd3aW4nLFxuICAgICAgJ1N5bWJpYW4gT1MnLFxuICAgICAgJ2hwd09TJyxcbiAgICAgICd3ZWJPUyAnLFxuICAgICAgJ3dlYk9TJyxcbiAgICAgICdUYWJsZXQgT1MnLFxuICAgICAgJ1RpemVuJyxcbiAgICAgICdMaW51eCcsXG4gICAgICAnTWFjIE9TIFgnLFxuICAgICAgJ01hY2ludG9zaCcsXG4gICAgICAnTWFjJyxcbiAgICAgICdXaW5kb3dzIDk4OycsXG4gICAgICAnV2luZG93cyAnXG4gICAgXSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgbGF5b3V0IGVuZ2luZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBsYXlvdXQgZW5naW5lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldExheW91dChndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCBSZWdFeHAoJ1xcXFxiJyArIChcbiAgICAgICAgICBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpXG4gICAgICAgICkgKyAnXFxcXGInLCAnaScpLmV4ZWModWEpICYmIChndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgbWFudWZhY3R1cmVyIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBvYmplY3Qgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBtYW51ZmFjdHVyZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TWFudWZhY3R1cmVyKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICAgIC8vIExvb2t1cCB0aGUgbWFudWZhY3R1cmVyIGJ5IHByb2R1Y3Qgb3Igc2NhbiB0aGUgVUEgZm9yIHRoZSBtYW51ZmFjdHVyZXIuXG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgKFxuICAgICAgICAgIHZhbHVlW3Byb2R1Y3RdIHx8XG4gICAgICAgICAgdmFsdWVbL15bYS16XSsoPzogK1thLXpdK1xcYikqL2kuZXhlYyhwcm9kdWN0KV0gfHxcbiAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHF1YWxpZnkoa2V5KSArICcoPzpcXFxcYnxcXFxcdypcXFxcZCknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICkgJiYga2V5O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGJyb3dzZXIgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBicm93c2VyIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TmFtZShndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCBSZWdFeHAoJ1xcXFxiJyArIChcbiAgICAgICAgICBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpXG4gICAgICAgICkgKyAnXFxcXGInLCAnaScpLmV4ZWModWEpICYmIChndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgT1MgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBPUyBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE9TKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnKD86L1tcXFxcZC5dK3xbIFxcXFx3Ll0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICByZXN1bHQgPSBjbGVhbnVwT1MocmVzdWx0LCBwYXR0ZXJuLCBndWVzcy5sYWJlbCB8fCBndWVzcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBwcm9kdWN0IG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgcHJvZHVjdCBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFByb2R1Y3QoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKTtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgKHJlc3VsdCA9XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcgKlxcXFxkK1suXFxcXHdfXSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcgKlxcXFx3Ky1bXFxcXHddKicsICdpJykuZXhlYyh1YSkgfHxcbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/OjsgKig/OlthLXpdK1tfLV0pP1thLXpdK1xcXFxkK3xbXiAoKTstXSopJywgJ2knKS5leGVjKHVhKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIC8vIFNwbGl0IGJ5IGZvcndhcmQgc2xhc2ggYW5kIGFwcGVuZCBwcm9kdWN0IHZlcnNpb24gaWYgbmVlZGVkLlxuICAgICAgICAgIGlmICgocmVzdWx0ID0gU3RyaW5nKChndWVzcy5sYWJlbCAmJiAhUmVnRXhwKHBhdHRlcm4sICdpJykudGVzdChndWVzcy5sYWJlbCkpID8gZ3Vlc3MubGFiZWwgOiByZXN1bHQpLnNwbGl0KCcvJykpWzFdICYmICEvW1xcZC5dKy8udGVzdChyZXN1bHRbMF0pKSB7XG4gICAgICAgICAgICByZXN1bHRbMF0gKz0gJyAnICsgcmVzdWx0WzFdO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBDb3JyZWN0IGNoYXJhY3RlciBjYXNlIGFuZCBjbGVhbnVwIHN0cmluZy5cbiAgICAgICAgICBndWVzcyA9IGd1ZXNzLmxhYmVsIHx8IGd1ZXNzO1xuICAgICAgICAgIHJlc3VsdCA9IGZvcm1hdChyZXN1bHRbMF1cbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cChwYXR0ZXJuLCAnaScpLCBndWVzcylcbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cCgnOyAqKD86JyArIGd1ZXNzICsgJ1tfLV0pPycsICdpJyksICcgJylcbiAgICAgICAgICAgIC5yZXBsYWNlKFJlZ0V4cCgnKCcgKyBndWVzcyArICcpWy1fLl0/KFxcXFx3KScsICdpJyksICckMSAkMicpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzb2x2ZXMgdGhlIHZlcnNpb24gdXNpbmcgYW4gYXJyYXkgb2YgVUEgcGF0dGVybnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhdHRlcm5zIEFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHZlcnNpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0VmVyc2lvbihwYXR0ZXJucykge1xuICAgICAgcmV0dXJuIHJlZHVjZShwYXR0ZXJucywgZnVuY3Rpb24ocmVzdWx0LCBwYXR0ZXJuKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgKFJlZ0V4cChwYXR0ZXJuICtcbiAgICAgICAgICAnKD86LVtcXFxcZC5dKy98KD86IGZvciBbXFxcXHctXSspP1sgLy1dKShbXFxcXGQuXStbXiAoKTsvXy1dKiknLCAnaScpLmV4ZWModWEpIHx8IDApWzFdIHx8IG51bGw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgd2hlbiB0aGUgcGxhdGZvcm0gb2JqZWN0IGlzIGNvZXJjZWQgdG8gYSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbmFtZSB0b1N0cmluZ1xuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgYHBsYXRmb3JtLmRlc2NyaXB0aW9uYCBpZiBhdmFpbGFibGUsIGVsc2UgYW4gZW1wdHkgc3RyaW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvU3RyaW5nUGxhdGZvcm0oKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXNjcmlwdGlvbiB8fCAnJztcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBDb252ZXJ0IGxheW91dCB0byBhbiBhcnJheSBzbyB3ZSBjYW4gYWRkIGV4dHJhIGRldGFpbHMuXG4gICAgbGF5b3V0ICYmIChsYXlvdXQgPSBbbGF5b3V0XSk7XG5cbiAgICAvLyBEZXRlY3QgcHJvZHVjdCBuYW1lcyB0aGF0IGNvbnRhaW4gdGhlaXIgbWFudWZhY3R1cmVyJ3MgbmFtZS5cbiAgICBpZiAobWFudWZhY3R1cmVyICYmICFwcm9kdWN0KSB7XG4gICAgICBwcm9kdWN0ID0gZ2V0UHJvZHVjdChbbWFudWZhY3R1cmVyXSk7XG4gICAgfVxuICAgIC8vIENsZWFuIHVwIEdvb2dsZSBUVi5cbiAgICBpZiAoKGRhdGEgPSAvXFxiR29vZ2xlIFRWXFxiLy5leGVjKHByb2R1Y3QpKSkge1xuICAgICAgcHJvZHVjdCA9IGRhdGFbMF07XG4gICAgfVxuICAgIC8vIERldGVjdCBzaW11bGF0b3JzLlxuICAgIGlmICgvXFxiU2ltdWxhdG9yXFxiL2kudGVzdCh1YSkpIHtcbiAgICAgIHByb2R1Y3QgPSAocHJvZHVjdCA/IHByb2R1Y3QgKyAnICcgOiAnJykgKyAnU2ltdWxhdG9yJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIE1pbmkgOCsgcnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZSBvbiBpT1MuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhIE1pbmknICYmIC9cXGJPUGlPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ3J1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIE1vYmlsZSAxMS5cbiAgICBpZiAobmFtZSA9PSAnSUUnICYmIC9cXGJsaWtlIGlQaG9uZSBPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRhdGEgPSBwYXJzZSh1YS5yZXBsYWNlKC9saWtlIGlQaG9uZSBPUy8sICcnKSk7XG4gICAgICBtYW51ZmFjdHVyZXIgPSBkYXRhLm1hbnVmYWN0dXJlcjtcbiAgICAgIHByb2R1Y3QgPSBkYXRhLnByb2R1Y3Q7XG4gICAgfVxuICAgIC8vIERldGVjdCBpT1MuXG4gICAgZWxzZSBpZiAoL15pUC8udGVzdChwcm9kdWN0KSkge1xuICAgICAgbmFtZSB8fCAobmFtZSA9ICdTYWZhcmknKTtcbiAgICAgIG9zID0gJ2lPUycgKyAoKGRhdGEgPSAvIE9TIChbXFxkX10rKS9pLmV4ZWModWEpKVxuICAgICAgICA/ICcgJyArIGRhdGFbMV0ucmVwbGFjZSgvXy9nLCAnLicpXG4gICAgICAgIDogJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgS3VidW50dS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdLb25xdWVyb3InICYmICEvYnVudHUvaS50ZXN0KG9zKSkge1xuICAgICAgb3MgPSAnS3VidW50dSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBBbmRyb2lkIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKChtYW51ZmFjdHVyZXIgJiYgbWFudWZhY3R1cmVyICE9ICdHb29nbGUnICYmXG4gICAgICAgICgoL0Nocm9tZS8udGVzdChuYW1lKSAmJiAhL1xcYk1vYmlsZSBTYWZhcmlcXGIvaS50ZXN0KHVhKSkgfHwgL1xcYlZpdGFcXGIvLnRlc3QocHJvZHVjdCkpKSB8fFxuICAgICAgICAoL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpICYmIC9eQ2hyb21lLy50ZXN0KG5hbWUpICYmIC9cXGJWZXJzaW9uXFwvL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lID0gJ0FuZHJvaWQgQnJvd3Nlcic7XG4gICAgICBvcyA9IC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogJ0FuZHJvaWQnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgU2lsayBkZXNrdG9wL2FjY2VsZXJhdGVkIG1vZGVzLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1NpbGsnKSB7XG4gICAgICBpZiAoIS9cXGJNb2JpL2kudGVzdCh1YSkpIHtcbiAgICAgICAgb3MgPSAnQW5kcm9pZCc7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgfVxuICAgICAgaWYgKC9BY2NlbGVyYXRlZCAqPSAqdHJ1ZS9pLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2FjY2VsZXJhdGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBQYWxlTW9vbiBpZGVudGlmeWluZyBhcyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1BhbGVNb29uJyAmJiAoZGF0YSA9IC9cXGJGaXJlZm94XFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzIEZpcmVmb3ggJyArIGRhdGFbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBPUyBhbmQgcHJvZHVjdHMgcnVubmluZyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIChkYXRhID0gL1xcYihNb2JpbGV8VGFibGV0fFRWKVxcYi9pLmV4ZWModWEpKSkge1xuICAgICAgb3MgfHwgKG9zID0gJ0ZpcmVmb3ggT1MnKTtcbiAgICAgIHByb2R1Y3QgfHwgKHByb2R1Y3QgPSBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGZhbHNlIHBvc2l0aXZlcyBmb3IgRmlyZWZveC9TYWZhcmkuXG4gICAgZWxzZSBpZiAoIW5hbWUgfHwgKGRhdGEgPSAhL1xcYk1pbmVmaWVsZFxcYi9pLnRlc3QodWEpICYmIC9cXGIoPzpGaXJlZm94fFNhZmFyaSlcXGIvLmV4ZWMobmFtZSkpKSB7XG4gICAgICAvLyBFc2NhcGUgdGhlIGAvYCBmb3IgRmlyZWZveCAxLlxuICAgICAgaWYgKG5hbWUgJiYgIXByb2R1Y3QgJiYgL1tcXC8sXXxeW14oXSs/XFwpLy50ZXN0KHVhLnNsaWNlKHVhLmluZGV4T2YoZGF0YSArICcvJykgKyA4KSkpIHtcbiAgICAgICAgLy8gQ2xlYXIgbmFtZSBvZiBmYWxzZSBwb3NpdGl2ZXMuXG4gICAgICAgIG5hbWUgPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gUmVhc3NpZ24gYSBnZW5lcmljIG5hbWUuXG4gICAgICBpZiAoKGRhdGEgPSBwcm9kdWN0IHx8IG1hbnVmYWN0dXJlciB8fCBvcykgJiZcbiAgICAgICAgICAocHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgL1xcYig/OkFuZHJvaWR8U3ltYmlhbiBPU3xUYWJsZXQgT1N8d2ViT1MpXFxiLy50ZXN0KG9zKSkpIHtcbiAgICAgICAgbmFtZSA9IC9bYS16XSsoPzogSGF0KT8vaS5leGVjKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogZGF0YSkgKyAnIEJyb3dzZXInO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgQ2hyb21lIHZlcnNpb24gdG8gZGVzY3JpcHRpb24gZm9yIEVsZWN0cm9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0VsZWN0cm9uJyAmJiAoZGF0YSA9ICgvXFxiQ2hyb21lXFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyBkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IG5vbi1PcGVyYSAoUHJlc3RvLWJhc2VkKSB2ZXJzaW9ucyAob3JkZXIgaXMgaW1wb3J0YW50KS5cbiAgICBpZiAoIXZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSBnZXRWZXJzaW9uKFtcbiAgICAgICAgJyg/OkNsb3VkOXxDcmlPU3xDck1vfEVkZ2V8RnhpT1N8SUVNb2JpbGV8SXJvbnxPcGVyYSA/TWluaXxPUGlPU3xPUFJ8UmF2ZW58U2Ftc3VuZ0Jyb3dzZXJ8U2lsayg/IS9bXFxcXGQuXSskKSknLFxuICAgICAgICAnVmVyc2lvbicsXG4gICAgICAgIHF1YWxpZnkobmFtZSksXG4gICAgICAgICcoPzpGaXJlZm94fE1pbmVmaWVsZHxOZXRGcm9udCknXG4gICAgICBdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHN0dWJib3JuIGxheW91dCBlbmdpbmVzLlxuICAgIGlmICgoZGF0YSA9XG4gICAgICAgICAgbGF5b3V0ID09ICdpQ2FiJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID4gMyAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgIC9cXGJPcGVyYVxcYi8udGVzdChuYW1lKSAmJiAoL1xcYk9QUlxcYi8udGVzdCh1YSkgPyAnQmxpbmsnIDogJ1ByZXN0bycpIHx8XG4gICAgICAgICAgL1xcYig/Ok1pZG9yaXxOb29rfFNhZmFyaSlcXGIvaS50ZXN0KHVhKSAmJiAhL14oPzpUcmlkZW50fEVkZ2VIVE1MKSQvLnRlc3QobGF5b3V0KSAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgICFsYXlvdXQgJiYgL1xcYk1TSUVcXGIvaS50ZXN0KHVhKSAmJiAob3MgPT0gJ01hYyBPUycgPyAnVGFzbWFuJyA6ICdUcmlkZW50JykgfHxcbiAgICAgICAgICBsYXlvdXQgPT0gJ1dlYktpdCcgJiYgL1xcYlBsYXlTdGF0aW9uXFxiKD8hIFZpdGFcXGIpL2kudGVzdChuYW1lKSAmJiAnTmV0RnJvbnQnXG4gICAgICAgICkpIHtcbiAgICAgIGxheW91dCA9IFtkYXRhXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgUGhvbmUgNyBkZXNrdG9wIG1vZGUuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAoZGF0YSA9ICgvOyAqKD86WEJMV1B8WnVuZVdQKShcXGQrKS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lICcgKyAoL1xcKyQvLnRlc3QoZGF0YSkgPyBkYXRhIDogZGF0YSArICcueCcpO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDgueCBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAoL1xcYldQRGVza3RvcFxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBuYW1lID0gJ0lFIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lIDgueCc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIHZlcnNpb24gfHwgKHZlcnNpb24gPSAoL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkgfHwgMClbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgMTEgaWRlbnRpZnlpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAobmFtZSAhPSAnSUUnICYmIGxheW91dCA9PSAnVHJpZGVudCcgJiYgKGRhdGEgPSAvXFxicnY6KFtcXGQuXSspLy5leGVjKHVhKSkpIHtcbiAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzICcgKyBuYW1lICsgKHZlcnNpb24gPyAnICcgKyB2ZXJzaW9uIDogJycpKTtcbiAgICAgIH1cbiAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgdmVyc2lvbiA9IGRhdGFbMV07XG4gICAgfVxuICAgIC8vIExldmVyYWdlIGVudmlyb25tZW50IGZlYXR1cmVzLlxuICAgIGlmICh1c2VGZWF0dXJlcykge1xuICAgICAgLy8gRGV0ZWN0IHNlcnZlci1zaWRlIGVudmlyb25tZW50cy5cbiAgICAgIC8vIFJoaW5vIGhhcyBhIGdsb2JhbCBmdW5jdGlvbiB3aGlsZSBvdGhlcnMgaGF2ZSBhIGdsb2JhbCBvYmplY3QuXG4gICAgICBpZiAoaXNIb3N0VHlwZShjb250ZXh0LCAnZ2xvYmFsJykpIHtcbiAgICAgICAgaWYgKGphdmEpIHtcbiAgICAgICAgICBkYXRhID0gamF2YS5sYW5nLlN5c3RlbTtcbiAgICAgICAgICBhcmNoID0gZGF0YS5nZXRQcm9wZXJ0eSgnb3MuYXJjaCcpO1xuICAgICAgICAgIG9zID0gb3MgfHwgZGF0YS5nZXRQcm9wZXJ0eSgnb3MubmFtZScpICsgJyAnICsgZGF0YS5nZXRQcm9wZXJ0eSgnb3MudmVyc2lvbicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyaGlubykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2ZXJzaW9uID0gY29udGV4dC5yZXF1aXJlKCdyaW5nby9lbmdpbmUnKS52ZXJzaW9uLmpvaW4oJy4nKTtcbiAgICAgICAgICAgIG5hbWUgPSAnUmluZ29KUyc7XG4gICAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgICBpZiAoKGRhdGEgPSBjb250ZXh0LnN5c3RlbSkgJiYgZGF0YS5nbG9iYWwuc3lzdGVtID09IGNvbnRleHQuc3lzdGVtKSB7XG4gICAgICAgICAgICAgIG5hbWUgPSAnTmFyd2hhbCc7XG4gICAgICAgICAgICAgIG9zIHx8IChvcyA9IGRhdGFbMF0ub3MgfHwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdSaGlubyc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKFxuICAgICAgICAgIHR5cGVvZiBjb250ZXh0LnByb2Nlc3MgPT0gJ29iamVjdCcgJiYgIWNvbnRleHQucHJvY2Vzcy5icm93c2VyICYmXG4gICAgICAgICAgKGRhdGEgPSBjb250ZXh0LnByb2Nlc3MpXG4gICAgICAgICkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucyA9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLmVsZWN0cm9uID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ05vZGUgJyArIGRhdGEudmVyc2lvbnMubm9kZSk7XG4gICAgICAgICAgICAgIG5hbWUgPSAnRWxlY3Ryb24nO1xuICAgICAgICAgICAgICB2ZXJzaW9uID0gZGF0YS52ZXJzaW9ucy5lbGVjdHJvbjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMubncgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnQ2hyb21pdW0gJyArIHZlcnNpb24sICdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ05XLmpzJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMubnc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdOb2RlLmpzJztcbiAgICAgICAgICAgIGFyY2ggPSBkYXRhLmFyY2g7XG4gICAgICAgICAgICBvcyA9IGRhdGEucGxhdGZvcm07XG4gICAgICAgICAgICB2ZXJzaW9uID0gL1tcXGQuXSsvLmV4ZWMoZGF0YS52ZXJzaW9uKTtcbiAgICAgICAgICAgIHZlcnNpb24gPSB2ZXJzaW9uID8gdmVyc2lvblswXSA6IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgQWRvYmUgQUlSLlxuICAgICAgZWxzZSBpZiAoZ2V0Q2xhc3NPZigoZGF0YSA9IGNvbnRleHQucnVudGltZSkpID09IGFpclJ1bnRpbWVDbGFzcykge1xuICAgICAgICBuYW1lID0gJ0Fkb2JlIEFJUic7XG4gICAgICAgIG9zID0gZGF0YS5mbGFzaC5zeXN0ZW0uQ2FwYWJpbGl0aWVzLm9zO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IFBoYW50b21KUy5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnBoYW50b20pKSA9PSBwaGFudG9tQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdQaGFudG9tSlMnO1xuICAgICAgICB2ZXJzaW9uID0gKGRhdGEgPSBkYXRhLnZlcnNpb24gfHwgbnVsbCkgJiYgKGRhdGEubWFqb3IgKyAnLicgKyBkYXRhLm1pbm9yICsgJy4nICsgZGF0YS5wYXRjaCk7XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSUUgY29tcGF0aWJpbGl0eSBtb2Rlcy5cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBkb2MuZG9jdW1lbnRNb2RlID09ICdudW1iZXInICYmIChkYXRhID0gL1xcYlRyaWRlbnRcXC8oXFxkKykvaS5leGVjKHVhKSkpIHtcbiAgICAgICAgLy8gV2UncmUgaW4gY29tcGF0aWJpbGl0eSBtb2RlIHdoZW4gdGhlIFRyaWRlbnQgdmVyc2lvbiArIDQgZG9lc24ndFxuICAgICAgICAvLyBlcXVhbCB0aGUgZG9jdW1lbnQgbW9kZS5cbiAgICAgICAgdmVyc2lvbiA9IFt2ZXJzaW9uLCBkb2MuZG9jdW1lbnRNb2RlXTtcbiAgICAgICAgaWYgKChkYXRhID0gK2RhdGFbMV0gKyA0KSAhPSB2ZXJzaW9uWzFdKSB7XG4gICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnSUUgJyArIHZlcnNpb25bMV0gKyAnIG1vZGUnKTtcbiAgICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICcnKTtcbiAgICAgICAgICB2ZXJzaW9uWzFdID0gZGF0YTtcbiAgICAgICAgfVxuICAgICAgICB2ZXJzaW9uID0gbmFtZSA9PSAnSUUnID8gU3RyaW5nKHZlcnNpb25bMV0udG9GaXhlZCgxKSkgOiB2ZXJzaW9uWzBdO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIDExIG1hc2tpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAvXig/OkNocm9tZXxGaXJlZm94KVxcYi8udGVzdChuYW1lKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdtYXNraW5nIGFzICcgKyBuYW1lICsgJyAnICsgdmVyc2lvbik7XG4gICAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgICB2ZXJzaW9uID0gJzExLjAnO1xuICAgICAgICBsYXlvdXQgPSBbJ1RyaWRlbnQnXTtcbiAgICAgICAgb3MgPSAnV2luZG93cyc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zICYmIGZvcm1hdChvcyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBwcmVyZWxlYXNlIHBoYXNlcy5cbiAgICBpZiAodmVyc2lvbiAmJiAoZGF0YSA9XG4gICAgICAgICAgLyg/OlthYl18ZHB8cHJlfFthYl1cXGQrcHJlKSg/OlxcZCtcXCs/KT8kL2kuZXhlYyh2ZXJzaW9uKSB8fFxuICAgICAgICAgIC8oPzphbHBoYXxiZXRhKSg/OiA/XFxkKT8vaS5leGVjKHVhICsgJzsnICsgKHVzZUZlYXR1cmVzICYmIG5hdi5hcHBNaW5vclZlcnNpb24pKSB8fFxuICAgICAgICAgIC9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAnYSdcbiAgICAgICAgKSkge1xuICAgICAgcHJlcmVsZWFzZSA9IC9iL2kudGVzdChkYXRhKSA/ICdiZXRhJyA6ICdhbHBoYSc7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKFJlZ0V4cChkYXRhICsgJ1xcXFwrPyQnKSwgJycpICtcbiAgICAgICAgKHByZXJlbGVhc2UgPT0gJ2JldGEnID8gYmV0YSA6IGFscGhhKSArICgvXFxkK1xcKz8vLmV4ZWMoZGF0YSkgfHwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBNb2JpbGUuXG4gICAgaWYgKG5hbWUgPT0gJ0Zlbm5lYycgfHwgbmFtZSA9PSAnRmlyZWZveCcgJiYgL1xcYig/OkFuZHJvaWR8RmlyZWZveCBPUylcXGIvLnRlc3Qob3MpKSB7XG4gICAgICBuYW1lID0gJ0ZpcmVmb3ggTW9iaWxlJztcbiAgICB9XG4gICAgLy8gT2JzY3VyZSBNYXh0aG9uJ3MgdW5yZWxpYWJsZSB2ZXJzaW9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ01heHRob24nICYmIHZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSB2ZXJzaW9uLnJlcGxhY2UoL1xcLltcXGQuXSsvLCAnLngnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFhib3ggMzYwIGFuZCBYYm94IE9uZS5cbiAgICBlbHNlIGlmICgvXFxiWGJveFxcYi9pLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcpIHtcbiAgICAgICAgb3MgPSBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHByb2R1Y3QgPT0gJ1hib3ggMzYwJyAmJiAvXFxiSUVNb2JpbGVcXGIvLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ21vYmlsZSBtb2RlJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFkZCBtb2JpbGUgcG9zdGZpeC5cbiAgICBlbHNlIGlmICgoL14oPzpDaHJvbWV8SUV8T3BlcmEpJC8udGVzdChuYW1lKSB8fCBuYW1lICYmICFwcm9kdWN0ICYmICEvQnJvd3NlcnxNb2JpLy50ZXN0KG5hbWUpKSAmJlxuICAgICAgICAob3MgPT0gJ1dpbmRvd3MgQ0UnIHx8IC9Nb2JpL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lICs9ICcgTW9iaWxlJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIHBsYXRmb3JtIHByZXZpZXcuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnSUUnICYmIHVzZUZlYXR1cmVzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoY29udGV4dC5leHRlcm5hbCA9PT0gbnVsbCkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ3BsYXRmb3JtIHByZXZpZXcnKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2VtYmVkZGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBCbGFja0JlcnJ5IE9TIHZlcnNpb24uXG4gICAgLy8gaHR0cDovL2RvY3MuYmxhY2tiZXJyeS5jb20vZW4vZGV2ZWxvcGVycy9kZWxpdmVyYWJsZXMvMTgxNjkvSFRUUF9oZWFkZXJzX3NlbnRfYnlfQkJfQnJvd3Nlcl8xMjM0OTExXzExLmpzcFxuICAgIGVsc2UgaWYgKCgvXFxiQmxhY2tCZXJyeVxcYi8udGVzdChwcm9kdWN0KSB8fCAvXFxiQkIxMFxcYi8udGVzdCh1YSkpICYmIChkYXRhID1cbiAgICAgICAgICAoUmVnRXhwKHByb2R1Y3QucmVwbGFjZSgvICsvZywgJyAqJykgKyAnLyhbLlxcXFxkXSspJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fFxuICAgICAgICAgIHZlcnNpb25cbiAgICAgICAgKSkge1xuICAgICAgZGF0YSA9IFtkYXRhLCAvQkIxMC8udGVzdCh1YSldO1xuICAgICAgb3MgPSAoZGF0YVsxXSA/IChwcm9kdWN0ID0gbnVsbCwgbWFudWZhY3R1cmVyID0gJ0JsYWNrQmVycnknKSA6ICdEZXZpY2UgU29mdHdhcmUnKSArICcgJyArIGRhdGFbMF07XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGlkZW50aWZ5aW5nL21hc2tpbmcgaXRzZWxmIGFzIGFub3RoZXIgYnJvd3Nlci5cbiAgICAvLyBodHRwOi8vd3d3Lm9wZXJhLmNvbS9zdXBwb3J0L2tiL3ZpZXcvODQzL1xuICAgIGVsc2UgaWYgKHRoaXMgIT0gZm9yT3duICYmIHByb2R1Y3QgIT0gJ1dpaScgJiYgKFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiBvcGVyYSkgfHxcbiAgICAgICAgICAoL09wZXJhLy50ZXN0KG5hbWUpICYmIC9cXGIoPzpNU0lFfEZpcmVmb3gpXFxiL2kudGVzdCh1YSkpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGJPUyBYICg/OlxcZCtcXC4pezIsfS8udGVzdChvcykpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0lFJyAmJiAoXG4gICAgICAgICAgICAob3MgJiYgIS9eV2luLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gNS41KSB8fFxuICAgICAgICAgICAgL1xcYldpbmRvd3MgWFBcXGIvLnRlc3Qob3MpICYmIHZlcnNpb24gPiA4IHx8XG4gICAgICAgICAgICB2ZXJzaW9uID09IDggJiYgIS9cXGJUcmlkZW50XFxiLy50ZXN0KHVhKVxuICAgICAgICAgICkpXG4gICAgICAgICkgJiYgIXJlT3BlcmEudGVzdCgoZGF0YSA9IHBhcnNlLmNhbGwoZm9yT3duLCB1YS5yZXBsYWNlKHJlT3BlcmEsICcnKSArICc7JykpKSAmJiBkYXRhLm5hbWUpIHtcbiAgICAgIC8vIFdoZW4gXCJpZGVudGlmeWluZ1wiLCB0aGUgVUEgY29udGFpbnMgYm90aCBPcGVyYSBhbmQgdGhlIG90aGVyIGJyb3dzZXIncyBuYW1lLlxuICAgICAgZGF0YSA9ICdpbmcgYXMgJyArIGRhdGEubmFtZSArICgoZGF0YSA9IGRhdGEudmVyc2lvbikgPyAnICcgKyBkYXRhIDogJycpO1xuICAgICAgaWYgKHJlT3BlcmEudGVzdChuYW1lKSkge1xuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpICYmIG9zID09ICdNYWMgT1MnKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGRhdGEgPSAnaWRlbnRpZnknICsgZGF0YTtcbiAgICAgIH1cbiAgICAgIC8vIFdoZW4gXCJtYXNraW5nXCIsIHRoZSBVQSBjb250YWlucyBvbmx5IHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGVsc2Uge1xuICAgICAgICBkYXRhID0gJ21hc2snICsgZGF0YTtcbiAgICAgICAgaWYgKG9wZXJhQ2xhc3MpIHtcbiAgICAgICAgICBuYW1lID0gZm9ybWF0KG9wZXJhQ2xhc3MucmVwbGFjZSgvKFthLXpdKShbQS1aXSkvZywgJyQxICQyJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5hbWUgPSAnT3BlcmEnO1xuICAgICAgICB9XG4gICAgICAgIGlmICgvXFxiSUVcXGIvLnRlc3QoZGF0YSkpIHtcbiAgICAgICAgICBvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF1c2VGZWF0dXJlcykge1xuICAgICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsYXlvdXQgPSBbJ1ByZXN0byddO1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdlYktpdCBOaWdodGx5IGFuZCBhcHByb3hpbWF0ZSBDaHJvbWUvU2FmYXJpIHZlcnNpb25zLlxuICAgIGlmICgoZGF0YSA9ICgvXFxiQXBwbGVXZWJLaXRcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAvLyBDb3JyZWN0IGJ1aWxkIG51bWJlciBmb3IgbnVtZXJpYyBjb21wYXJpc29uLlxuICAgICAgLy8gKGUuZy4gXCI1MzIuNVwiIGJlY29tZXMgXCI1MzIuMDVcIilcbiAgICAgIGRhdGEgPSBbcGFyc2VGbG9hdChkYXRhLnJlcGxhY2UoL1xcLihcXGQpJC8sICcuMCQxJykpLCBkYXRhXTtcbiAgICAgIC8vIE5pZ2h0bHkgYnVpbGRzIGFyZSBwb3N0Zml4ZWQgd2l0aCBhIFwiK1wiLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgZGF0YVsxXS5zbGljZSgtMSkgPT0gJysnKSB7XG4gICAgICAgIG5hbWUgPSAnV2ViS2l0IE5pZ2h0bHknO1xuICAgICAgICBwcmVyZWxlYXNlID0gJ2FscGhhJztcbiAgICAgICAgdmVyc2lvbiA9IGRhdGFbMV0uc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuICAgICAgLy8gQ2xlYXIgaW5jb3JyZWN0IGJyb3dzZXIgdmVyc2lvbnMuXG4gICAgICBlbHNlIGlmICh2ZXJzaW9uID09IGRhdGFbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uID09IChkYXRhWzJdID0gKC9cXGJTYWZhcmlcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHRoZSBmdWxsIENocm9tZSB2ZXJzaW9uIHdoZW4gYXZhaWxhYmxlLlxuICAgICAgZGF0YVsxXSA9ICgvXFxiQ2hyb21lXFwvKFtcXGQuXSspL2kuZXhlYyh1YSkgfHwgMClbMV07XG4gICAgICAvLyBEZXRlY3QgQmxpbmsgbGF5b3V0IGVuZ2luZS5cbiAgICAgIGlmIChkYXRhWzBdID09IDUzNy4zNiAmJiBkYXRhWzJdID09IDUzNy4zNiAmJiBwYXJzZUZsb2F0KGRhdGFbMV0pID49IDI4ICYmIGxheW91dCA9PSAnV2ViS2l0Jykge1xuICAgICAgICBsYXlvdXQgPSBbJ0JsaW5rJ107XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSmF2YVNjcmlwdENvcmUuXG4gICAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY3Njg0NzQvaG93LWNhbi1pLWRldGVjdC13aGljaC1qYXZhc2NyaXB0LWVuZ2luZS12OC1vci1qc2MtaXMtdXNlZC1hdC1ydW50aW1lLWluLWFuZHJvaVxuICAgICAgaWYgKCF1c2VGZWF0dXJlcyB8fCAoIWxpa2VDaHJvbWUgJiYgIWRhdGFbMV0pKSB7XG4gICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJ2xpa2UgU2FmYXJpJyk7XG4gICAgICAgIGRhdGEgPSAoZGF0YSA9IGRhdGFbMF0sIGRhdGEgPCA0MDAgPyAxIDogZGF0YSA8IDUwMCA/IDIgOiBkYXRhIDwgNTI2ID8gMyA6IGRhdGEgPCA1MzMgPyA0IDogZGF0YSA8IDUzNCA/ICc0KycgOiBkYXRhIDwgNTM1ID8gNSA6IGRhdGEgPCA1MzcgPyA2IDogZGF0YSA8IDUzOCA/IDcgOiBkYXRhIDwgNjAxID8gOCA6ICc4Jyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIENocm9tZScpO1xuICAgICAgICBkYXRhID0gZGF0YVsxXSB8fCAoZGF0YSA9IGRhdGFbMF0sIGRhdGEgPCA1MzAgPyAxIDogZGF0YSA8IDUzMiA/IDIgOiBkYXRhIDwgNTMyLjA1ID8gMyA6IGRhdGEgPCA1MzMgPyA0IDogZGF0YSA8IDUzNC4wMyA/IDUgOiBkYXRhIDwgNTM0LjA3ID8gNiA6IGRhdGEgPCA1MzQuMTAgPyA3IDogZGF0YSA8IDUzNC4xMyA/IDggOiBkYXRhIDwgNTM0LjE2ID8gOSA6IGRhdGEgPCA1MzQuMjQgPyAxMCA6IGRhdGEgPCA1MzQuMzAgPyAxMSA6IGRhdGEgPCA1MzUuMDEgPyAxMiA6IGRhdGEgPCA1MzUuMDIgPyAnMTMrJyA6IGRhdGEgPCA1MzUuMDcgPyAxNSA6IGRhdGEgPCA1MzUuMTEgPyAxNiA6IGRhdGEgPCA1MzUuMTkgPyAxNyA6IGRhdGEgPCA1MzYuMDUgPyAxOCA6IGRhdGEgPCA1MzYuMTAgPyAxOSA6IGRhdGEgPCA1MzcuMDEgPyAyMCA6IGRhdGEgPCA1MzcuMTEgPyAnMjErJyA6IGRhdGEgPCA1MzcuMTMgPyAyMyA6IGRhdGEgPCA1MzcuMTggPyAyNCA6IGRhdGEgPCA1MzcuMjQgPyAyNSA6IGRhdGEgPCA1MzcuMzYgPyAyNiA6IGxheW91dCAhPSAnQmxpbmsnID8gJzI3JyA6ICcyOCcpO1xuICAgICAgfVxuICAgICAgLy8gQWRkIHRoZSBwb3N0Zml4IG9mIFwiLnhcIiBvciBcIitcIiBmb3IgYXBwcm94aW1hdGUgdmVyc2lvbnMuXG4gICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSArPSAnICcgKyAoZGF0YSArPSB0eXBlb2YgZGF0YSA9PSAnbnVtYmVyJyA/ICcueCcgOiAvWy4rXS8udGVzdChkYXRhKSA/ICcnIDogJysnKSk7XG4gICAgICAvLyBPYnNjdXJlIHZlcnNpb24gZm9yIHNvbWUgU2FmYXJpIDEtMiByZWxlYXNlcy5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmICghdmVyc2lvbiB8fCBwYXJzZUludCh2ZXJzaW9uKSA+IDQ1KSkge1xuICAgICAgICB2ZXJzaW9uID0gZGF0YTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGRlc2t0b3AgbW9kZXMuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhJyAmJiAgKGRhdGEgPSAvXFxiemJvdnx6dmF2JC8uZXhlYyhvcykpKSB7XG4gICAgICBuYW1lICs9ICcgJztcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgaWYgKGRhdGEgPT0gJ3p2YXYnKSB7XG4gICAgICAgIG5hbWUgKz0gJ01pbmknO1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5hbWUgKz0gJ01vYmlsZSc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhICsgJyQnKSwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQ2hyb21lIGRlc2t0b3AgbW9kZS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTYWZhcmknICYmIC9cXGJDaHJvbWVcXGIvLmV4ZWMobGF5b3V0ICYmIGxheW91dFsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgbmFtZSA9ICdDaHJvbWUgTW9iaWxlJztcbiAgICAgIHZlcnNpb24gPSBudWxsO1xuXG4gICAgICBpZiAoL1xcYk9TIFhcXGIvLnRlc3Qob3MpKSB7XG4gICAgICAgIG1hbnVmYWN0dXJlciA9ICdBcHBsZSc7XG4gICAgICAgIG9zID0gJ2lPUyA0LjMrJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gU3RyaXAgaW5jb3JyZWN0IE9TIHZlcnNpb25zLlxuICAgIGlmICh2ZXJzaW9uICYmIHZlcnNpb24uaW5kZXhPZigoZGF0YSA9IC9bXFxkLl0rJC8uZXhlYyhvcykpKSA9PSAwICYmXG4gICAgICAgIHVhLmluZGV4T2YoJy8nICsgZGF0YSArICctJykgPiAtMSkge1xuICAgICAgb3MgPSB0cmltKG9zLnJlcGxhY2UoZGF0YSwgJycpKTtcbiAgICB9XG4gICAgLy8gQWRkIGxheW91dCBlbmdpbmUuXG4gICAgaWYgKGxheW91dCAmJiAhL1xcYig/OkF2YW50fE5vb2spXFxiLy50ZXN0KG5hbWUpICYmIChcbiAgICAgICAgL0Jyb3dzZXJ8THVuYXNjYXBlfE1heHRob24vLnRlc3QobmFtZSkgfHxcbiAgICAgICAgbmFtZSAhPSAnU2FmYXJpJyAmJiAvXmlPUy8udGVzdChvcykgJiYgL1xcYlNhZmFyaVxcYi8udGVzdChsYXlvdXRbMV0pIHx8XG4gICAgICAgIC9eKD86QWRvYmV8QXJvcmF8QnJlYWNofE1pZG9yaXxPcGVyYXxQaGFudG9tfFJla29ucXxSb2NrfFNhbXN1bmcgSW50ZXJuZXR8U2xlaXBuaXJ8V2ViKS8udGVzdChuYW1lKSAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICAvLyBEb24ndCBhZGQgbGF5b3V0IGRldGFpbHMgdG8gZGVzY3JpcHRpb24gaWYgdGhleSBhcmUgZmFsc2V5LlxuICAgICAgKGRhdGEgPSBsYXlvdXRbbGF5b3V0Lmxlbmd0aCAtIDFdKSAmJiBkZXNjcmlwdGlvbi5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICAvLyBDb21iaW5lIGNvbnRleHR1YWwgaW5mb3JtYXRpb24uXG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgZGVzY3JpcHRpb24gPSBbJygnICsgZGVzY3JpcHRpb24uam9pbignOyAnKSArICcpJ107XG4gICAgfVxuICAgIC8vIEFwcGVuZCBtYW51ZmFjdHVyZXIgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiBwcm9kdWN0ICYmIHByb2R1Y3QuaW5kZXhPZihtYW51ZmFjdHVyZXIpIDwgMCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnb24gJyArIG1hbnVmYWN0dXJlcik7XG4gICAgfVxuICAgIC8vIEFwcGVuZCBwcm9kdWN0IHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChwcm9kdWN0KSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCgvXm9uIC8udGVzdChkZXNjcmlwdGlvbltkZXNjcmlwdGlvbi5sZW5ndGggLSAxXSkgPyAnJyA6ICdvbiAnKSArIHByb2R1Y3QpO1xuICAgIH1cbiAgICAvLyBQYXJzZSB0aGUgT1MgaW50byBhbiBvYmplY3QuXG4gICAgaWYgKG9zKSB7XG4gICAgICBkYXRhID0gLyAoW1xcZC4rXSspJC8uZXhlYyhvcyk7XG4gICAgICBpc1NwZWNpYWxDYXNlZE9TID0gZGF0YSAmJiBvcy5jaGFyQXQob3MubGVuZ3RoIC0gZGF0YVswXS5sZW5ndGggLSAxKSA9PSAnLyc7XG4gICAgICBvcyA9IHtcbiAgICAgICAgJ2FyY2hpdGVjdHVyZSc6IDMyLFxuICAgICAgICAnZmFtaWx5JzogKGRhdGEgJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gb3MucmVwbGFjZShkYXRhWzBdLCAnJykgOiBvcyxcbiAgICAgICAgJ3ZlcnNpb24nOiBkYXRhID8gZGF0YVsxXSA6IG51bGwsXG4gICAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciB2ZXJzaW9uID0gdGhpcy52ZXJzaW9uO1xuICAgICAgICAgIHJldHVybiB0aGlzLmZhbWlseSArICgodmVyc2lvbiAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyAnICcgKyB2ZXJzaW9uIDogJycpICsgKHRoaXMuYXJjaGl0ZWN0dXJlID09IDY0ID8gJyA2NC1iaXQnIDogJycpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBBZGQgYnJvd3Nlci9PUyBhcmNoaXRlY3R1cmUuXG4gICAgaWYgKChkYXRhID0gL1xcYig/OkFNRHxJQXxXaW58V09XfHg4Nl98eCk2NFxcYi9pLmV4ZWMoYXJjaCkpICYmICEvXFxiaTY4NlxcYi9pLnRlc3QoYXJjaCkpIHtcbiAgICAgIGlmIChvcykge1xuICAgICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICAgICAgb3MuZmFtaWx5ID0gb3MuZmFtaWx5LnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhKSwgJycpO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICAgIG5hbWUgJiYgKC9cXGJXT1c2NFxcYi9pLnRlc3QodWEpIHx8XG4gICAgICAgICAgKHVzZUZlYXR1cmVzICYmIC9cXHcoPzo4NnwzMikkLy50ZXN0KG5hdi5jcHVDbGFzcyB8fCBuYXYucGxhdGZvcm0pICYmICEvXFxiV2luNjQ7IHg2NFxcYi9pLnRlc3QodWEpKSlcbiAgICAgICkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCczMi1iaXQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQ2hyb21lIDM5IGFuZCBhYm92ZSBvbiBPUyBYIGlzIGFsd2F5cyA2NC1iaXQuXG4gICAgZWxzZSBpZiAoXG4gICAgICAgIG9zICYmIC9eT1MgWC8udGVzdChvcy5mYW1pbHkpICYmXG4gICAgICAgIG5hbWUgPT0gJ0Nocm9tZScgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+PSAzOVxuICAgICkge1xuICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgfVxuXG4gICAgdWEgfHwgKHVhID0gbnVsbCk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gb2JqZWN0LlxuICAgICAqXG4gICAgICogQG5hbWUgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICB2YXIgcGxhdGZvcm0gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBkZXNjcmlwdGlvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyJ3MgbGF5b3V0IGVuZ2luZS5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBsYXlvdXQgZW5naW5lcyBpbmNsdWRlOlxuICAgICAqIFwiQmxpbmtcIiwgXCJFZGdlSFRNTFwiLCBcIkdlY2tvXCIsIFwiVHJpZGVudFwiIGFuZCBcIldlYktpdFwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmxheW91dCA9IGxheW91dCAmJiBsYXlvdXRbMF07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCdzIG1hbnVmYWN0dXJlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIG1hbnVmYWN0dXJlcnMgaW5jbHVkZTpcbiAgICAgKiBcIkFwcGxlXCIsIFwiQXJjaG9zXCIsIFwiQW1hem9uXCIsIFwiQXN1c1wiLCBcIkJhcm5lcyAmIE5vYmxlXCIsIFwiQmxhY2tCZXJyeVwiLFxuICAgICAqIFwiR29vZ2xlXCIsIFwiSFBcIiwgXCJIVENcIiwgXCJMR1wiLCBcIk1pY3Jvc29mdFwiLCBcIk1vdG9yb2xhXCIsIFwiTmludGVuZG9cIixcbiAgICAgKiBcIk5va2lhXCIsIFwiU2Ftc3VuZ1wiIGFuZCBcIlNvbnlcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5tYW51ZmFjdHVyZXIgPSBtYW51ZmFjdHVyZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3Nlci9lbnZpcm9ubWVudC5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBicm93c2VyIG5hbWVzIGluY2x1ZGU6XG4gICAgICogXCJDaHJvbWVcIiwgXCJFbGVjdHJvblwiLCBcIkZpcmVmb3hcIiwgXCJGaXJlZm94IGZvciBpT1NcIiwgXCJJRVwiLFxuICAgICAqIFwiTWljcm9zb2Z0IEVkZ2VcIiwgXCJQaGFudG9tSlNcIiwgXCJTYWZhcmlcIiwgXCJTZWFNb25rZXlcIiwgXCJTaWxrXCIsXG4gICAgICogXCJPcGVyYSBNaW5pXCIgYW5kIFwiT3BlcmFcIlxuICAgICAqXG4gICAgICogTW9iaWxlIHZlcnNpb25zIG9mIHNvbWUgYnJvd3NlcnMgaGF2ZSBcIk1vYmlsZVwiIGFwcGVuZGVkIHRvIHRoZWlyIG5hbWU6XG4gICAgICogZWcuIFwiQ2hyb21lIE1vYmlsZVwiLCBcIkZpcmVmb3ggTW9iaWxlXCIsIFwiSUUgTW9iaWxlXCIgYW5kIFwiT3BlcmEgTW9iaWxlXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubmFtZSA9IG5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYWxwaGEvYmV0YSByZWxlYXNlIGluZGljYXRvci5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJlcmVsZWFzZSA9IHByZXJlbGVhc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCBob3N0aW5nIHRoZSBicm93c2VyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIHByb2R1Y3RzIGluY2x1ZGU6XG4gICAgICpcbiAgICAgKiBcIkJsYWNrQmVycnlcIiwgXCJHYWxheHkgUzRcIiwgXCJMdW1pYVwiLCBcImlQYWRcIiwgXCJpUG9kXCIsIFwiaVBob25lXCIsIFwiS2luZGxlXCIsXG4gICAgICogXCJLaW5kbGUgRmlyZVwiLCBcIk5leHVzXCIsIFwiTm9va1wiLCBcIlBsYXlCb29rXCIsIFwiVG91Y2hQYWRcIiBhbmQgXCJUcmFuc2Zvcm1lclwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByb2R1Y3QgPSBwcm9kdWN0O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIncyB1c2VyIGFnZW50IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udWEgPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyL2Vudmlyb25tZW50IHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnZlcnNpb24gPSBuYW1lICYmIHZlcnNpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgb3BlcmF0aW5nIHN5c3RlbS5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm9zID0gb3MgfHwge1xuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlIHRoZSBPUyBpcyBidWlsdCBmb3IuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBudW1iZXJ8bnVsbFxuICAgICAgICovXG4gICAgICAnYXJjaGl0ZWN0dXJlJzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgZmFtaWx5IG9mIHRoZSBPUy5cbiAgICAgICAqXG4gICAgICAgKiBDb21tb24gdmFsdWVzIGluY2x1ZGU6XG4gICAgICAgKiBcIldpbmRvd3NcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IFIyIC8gN1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggLyBWaXN0YVwiLFxuICAgICAgICogXCJXaW5kb3dzIFhQXCIsIFwiT1MgWFwiLCBcIlVidW50dVwiLCBcIkRlYmlhblwiLCBcIkZlZG9yYVwiLCBcIlJlZCBIYXRcIiwgXCJTdVNFXCIsXG4gICAgICAgKiBcIkFuZHJvaWRcIiwgXCJpT1NcIiBhbmQgXCJXaW5kb3dzIFBob25lXCJcbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICAgKi9cbiAgICAgICdmYW1pbHknOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSB2ZXJzaW9uIG9mIHRoZSBPUy5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICAgKi9cbiAgICAgICd2ZXJzaW9uJzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBSZXR1cm5zIHRoZSBPUyBzdHJpbmcuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgT1Mgc3RyaW5nLlxuICAgICAgICovXG4gICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHsgcmV0dXJuICdudWxsJzsgfVxuICAgIH07XG5cbiAgICBwbGF0Zm9ybS5wYXJzZSA9IHBhcnNlO1xuICAgIHBsYXRmb3JtLnRvU3RyaW5nID0gdG9TdHJpbmdQbGF0Zm9ybTtcblxuICAgIGlmIChwbGF0Zm9ybS52ZXJzaW9uKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KHZlcnNpb24pO1xuICAgIH1cbiAgICBpZiAocGxhdGZvcm0ubmFtZSkge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdChuYW1lKTtcbiAgICB9XG4gICAgaWYgKG9zICYmIG5hbWUgJiYgIShvcyA9PSBTdHJpbmcob3MpLnNwbGl0KCcgJylbMF0gJiYgKG9zID09IG5hbWUuc3BsaXQoJyAnKVswXSB8fCBwcm9kdWN0KSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2gocHJvZHVjdCA/ICcoJyArIG9zICsgJyknIDogJ29uICcgKyBvcyk7XG4gICAgfVxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gZGVzY3JpcHRpb24uam9pbignICcpO1xuICAgIH1cbiAgICByZXR1cm4gcGxhdGZvcm07XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvLyBFeHBvcnQgcGxhdGZvcm0uXG4gIHZhciBwbGF0Zm9ybSA9IHBhcnNlKCk7XG5cbiAgLy8gU29tZSBBTUQgYnVpbGQgb3B0aW1pemVycywgbGlrZSByLmpzLCBjaGVjayBmb3IgY29uZGl0aW9uIHBhdHRlcm5zIGxpa2UgdGhlIGZvbGxvd2luZzpcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PSAnb2JqZWN0JyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gRXhwb3NlIHBsYXRmb3JtIG9uIHRoZSBnbG9iYWwgb2JqZWN0IHRvIHByZXZlbnQgZXJyb3JzIHdoZW4gcGxhdGZvcm0gaXNcbiAgICAvLyBsb2FkZWQgYnkgYSBzY3JpcHQgdGFnIGluIHRoZSBwcmVzZW5jZSBvZiBhbiBBTUQgbG9hZGVyLlxuICAgIC8vIFNlZSBodHRwOi8vcmVxdWlyZWpzLm9yZy9kb2NzL2Vycm9ycy5odG1sI21pc21hdGNoIGZvciBtb3JlIGRldGFpbHMuXG4gICAgcm9vdC5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuXG4gICAgLy8gRGVmaW5lIGFzIGFuIGFub255bW91cyBtb2R1bGUgc28gcGxhdGZvcm0gY2FuIGJlIGFsaWFzZWQgdGhyb3VnaCBwYXRoIG1hcHBpbmcuXG4gICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHBsYXRmb3JtO1xuICAgIH0pO1xuICB9XG4gIC8vIENoZWNrIGZvciBgZXhwb3J0c2AgYWZ0ZXIgYGRlZmluZWAgaW4gY2FzZSBhIGJ1aWxkIG9wdGltaXplciBhZGRzIGFuIGBleHBvcnRzYCBvYmplY3QuXG4gIGVsc2UgaWYgKGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUpIHtcbiAgICAvLyBFeHBvcnQgZm9yIENvbW1vbkpTIHN1cHBvcnQuXG4gICAgZm9yT3duKHBsYXRmb3JtLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICBmcmVlRXhwb3J0c1trZXldID0gdmFsdWU7XG4gICAgfSk7XG4gIH1cbiAgZWxzZSB7XG4gICAgLy8gRXhwb3J0IHRvIHRoZSBnbG9iYWwgb2JqZWN0LlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcbiAgfVxufS5jYWxsKHRoaXMpKTtcbiIsInZhciBncmFtbWFyID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIHY6IFt7XG4gICAgICBuYW1lOiAndmVyc2lvbicsXG4gICAgICByZWc6IC9eKFxcZCopJC9cbiAgfV0sXG4gIG86IFt7IC8vbz0tIDIwNTE4IDAgSU4gSVA0IDIwMy4wLjExMy4xXG4gICAgLy8gTkI6IHNlc3Npb25JZCB3aWxsIGJlIGEgU3RyaW5nIGluIG1vc3QgY2FzZXMgYmVjYXVzZSBpdCBpcyBodWdlXG4gICAgbmFtZTogJ29yaWdpbicsXG4gICAgcmVnOiAvXihcXFMqKSAoXFxkKikgKFxcZCopIChcXFMqKSBJUChcXGQpIChcXFMqKS8sXG4gICAgbmFtZXM6IFsndXNlcm5hbWUnLCAnc2Vzc2lvbklkJywgJ3Nlc3Npb25WZXJzaW9uJywgJ25ldFR5cGUnLCAnaXBWZXInLCAnYWRkcmVzcyddLFxuICAgIGZvcm1hdDogXCIlcyAlcyAlZCAlcyBJUCVkICVzXCJcbiAgfV0sXG4gIC8vIGRlZmF1bHQgcGFyc2luZyBvZiB0aGVzZSBvbmx5ICh0aG91Z2ggc29tZSBvZiB0aGVzZSBmZWVsIG91dGRhdGVkKVxuICBzOiBbeyBuYW1lOiAnbmFtZScgfV0sXG4gIGk6IFt7IG5hbWU6ICdkZXNjcmlwdGlvbicgfV0sXG4gIHU6IFt7IG5hbWU6ICd1cmknIH1dLFxuICBlOiBbeyBuYW1lOiAnZW1haWwnIH1dLFxuICBwOiBbeyBuYW1lOiAncGhvbmUnIH1dLFxuICB6OiBbeyBuYW1lOiAndGltZXpvbmVzJyB9XSwgLy8gVE9ETzogdGhpcyBvbmUgY2FuIGFjdHVhbGx5IGJlIHBhcnNlZCBwcm9wZXJseS4uXG4gIHI6IFt7IG5hbWU6ICdyZXBlYXRzJyB9XSwgICAvLyBUT0RPOiB0aGlzIG9uZSBjYW4gYWxzbyBiZSBwYXJzZWQgcHJvcGVybHlcbiAgLy9rOiBbe31dLCAvLyBvdXRkYXRlZCB0aGluZyBpZ25vcmVkXG4gIHQ6IFt7IC8vdD0wIDBcbiAgICBuYW1lOiAndGltaW5nJyxcbiAgICByZWc6IC9eKFxcZCopIChcXGQqKS8sXG4gICAgbmFtZXM6IFsnc3RhcnQnLCAnc3RvcCddLFxuICAgIGZvcm1hdDogXCIlZCAlZFwiXG4gIH1dLFxuICBjOiBbeyAvL2M9SU4gSVA0IDEwLjQ3LjE5Ny4yNlxuICAgICAgbmFtZTogJ2Nvbm5lY3Rpb24nLFxuICAgICAgcmVnOiAvXklOIElQKFxcZCkgKFxcUyopLyxcbiAgICAgIG5hbWVzOiBbJ3ZlcnNpb24nLCAnaXAnXSxcbiAgICAgIGZvcm1hdDogXCJJTiBJUCVkICVzXCJcbiAgfV0sXG4gIGI6IFt7IC8vYj1BUzo0MDAwXG4gICAgICBwdXNoOiAnYmFuZHdpZHRoJyxcbiAgICAgIHJlZzogL14oVElBU3xBU3xDVHxSUnxSUyk6KFxcZCopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbGltaXQnXSxcbiAgICAgIGZvcm1hdDogXCIlczolc1wiXG4gIH1dLFxuICBtOiBbeyAvL209dmlkZW8gNTE3NDQgUlRQL0FWUCAxMjYgOTcgOTggMzQgMzFcbiAgICAgIC8vIE5COiBzcGVjaWFsIC0gcHVzaGVzIHRvIHNlc3Npb25cbiAgICAgIC8vIFRPRE86IHJ0cC9mbXRwIHNob3VsZCBiZSBmaWx0ZXJlZCBieSB0aGUgcGF5bG9hZHMgZm91bmQgaGVyZT9cbiAgICAgIHJlZzogL14oXFx3KikgKFxcZCopIChbXFx3XFwvXSopKD86ICguKikpPy8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ3BvcnQnLCAncHJvdG9jb2wnLCAncGF5bG9hZHMnXSxcbiAgICAgIGZvcm1hdDogXCIlcyAlZCAlcyAlc1wiXG4gIH1dLFxuICBhOiBbXG4gICAgeyAvL2E9cnRwbWFwOjExMCBvcHVzLzQ4MDAwLzJcbiAgICAgIHB1c2g6ICdydHAnLFxuICAgICAgcmVnOiAvXnJ0cG1hcDooXFxkKikgKFtcXHdcXC1dKikoPzpcXHMqXFwvKFxcZCopKD86XFxzKlxcLyhcXFMqKSk/KT8vLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb2RlYycsICdyYXRlJywgJ2VuY29kaW5nJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5lbmNvZGluZykgP1xuICAgICAgICAgIFwicnRwbWFwOiVkICVzLyVzLyVzXCI6XG4gICAgICAgICAgby5yYXRlID9cbiAgICAgICAgICBcInJ0cG1hcDolZCAlcy8lc1wiOlxuICAgICAgICAgIFwicnRwbWFwOiVkICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Zm10cDoxMDggcHJvZmlsZS1sZXZlbC1pZD0yNDtvYmplY3Q9MjM7Yml0cmF0ZT02NDAwMFxuICAgICAgLy9hPWZtdHA6MTExIG1pbnB0aW1lPTEwOyB1c2VpbmJhbmRmZWM9MVxuICAgICAgcHVzaDogJ2ZtdHAnLFxuICAgICAgcmVnOiAvXmZtdHA6KFxcZCopIChbXFxTfCBdKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb25maWcnXSxcbiAgICAgIGZvcm1hdDogXCJmbXRwOiVkICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWNvbnRyb2w6c3RyZWFtaWQ9MFxuICAgICAgICBuYW1lOiAnY29udHJvbCcsXG4gICAgICAgIHJlZzogL15jb250cm9sOiguKikvLFxuICAgICAgICBmb3JtYXQ6IFwiY29udHJvbDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwOjY1MTc5IElOIElQNCAxOTMuODQuNzcuMTk0XG4gICAgICBuYW1lOiAncnRjcCcsXG4gICAgICByZWc6IC9ecnRjcDooXFxkKikoPzogKFxcUyopIElQKFxcZCkgKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsncG9ydCcsICduZXRUeXBlJywgJ2lwVmVyJywgJ2FkZHJlc3MnXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmFkZHJlc3MgIT0gbnVsbCkgP1xuICAgICAgICAgIFwicnRjcDolZCAlcyBJUCVkICVzXCI6XG4gICAgICAgICAgXCJydGNwOiVkXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IHRyci1pbnQgMTAwXG4gICAgICBwdXNoOiAncnRjcEZiVHJySW50JyxcbiAgICAgIHJlZzogL15ydGNwLWZiOihcXCp8XFxkKikgdHJyLWludCAoXFxkKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICd2YWx1ZSddLFxuICAgICAgZm9ybWF0OiBcInJ0Y3AtZmI6JWQgdHJyLWludCAlZFwiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IG5hY2sgcnBzaVxuICAgICAgcHVzaDogJ3J0Y3BGYicsXG4gICAgICByZWc6IC9ecnRjcC1mYjooXFwqfFxcZCopIChbXFx3LV9dKikoPzogKFtcXHctX10qKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAndHlwZScsICdzdWJ0eXBlJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zdWJ0eXBlICE9IG51bGwpID9cbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXNcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPWV4dG1hcDoyIHVybjppZXRmOnBhcmFtczpydHAtaGRyZXh0OnRvZmZzZXRcbiAgICAgIC8vYT1leHRtYXA6MS9yZWN2b25seSBVUkktZ3BzLXN0cmluZ1xuICAgICAgcHVzaDogJ2V4dCcsXG4gICAgICByZWc6IC9eZXh0bWFwOihbXFx3X1xcL10qKSAoXFxTKikoPzogKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsndmFsdWUnLCAndXJpJywgJ2NvbmZpZyddLCAvLyB2YWx1ZSBtYXkgaW5jbHVkZSBcIi9kaXJlY3Rpb25cIiBzdWZmaXhcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmNvbmZpZyAhPSBudWxsKSA/XG4gICAgICAgICAgXCJleHRtYXA6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcImV4dG1hcDolcyAlc1wiO1xuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAgLy9hPWNyeXB0bzoxIEFFU19DTV8xMjhfSE1BQ19TSEExXzgwIGlubGluZTpQUzF1UUNWZWVDRkNhblZtY2prcFB5d2pOV2hjWUQwbVhYdHhhVkJSfDJeMjB8MTozMlxuICAgICAgcHVzaDogJ2NyeXB0bycsXG4gICAgICByZWc6IC9eY3J5cHRvOihcXGQqKSAoW1xcd19dKikgKFxcUyopKD86IChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2lkJywgJ3N1aXRlJywgJ2NvbmZpZycsICdzZXNzaW9uQ29uZmlnJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zZXNzaW9uQ29uZmlnICE9IG51bGwpID9cbiAgICAgICAgICBcImNyeXB0bzolZCAlcyAlcyAlc1wiOlxuICAgICAgICAgIFwiY3J5cHRvOiVkICVzICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1zZXR1cDphY3RwYXNzXG4gICAgICBuYW1lOiAnc2V0dXAnLFxuICAgICAgcmVnOiAvXnNldHVwOihcXHcqKS8sXG4gICAgICBmb3JtYXQ6IFwic2V0dXA6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9bWlkOjFcbiAgICAgIG5hbWU6ICdtaWQnLFxuICAgICAgcmVnOiAvXm1pZDooW15cXHNdKikvLFxuICAgICAgZm9ybWF0OiBcIm1pZDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkOjBjOGIwNjRkLWQ4MDctNDNiNC1iNDM0LWY5MmE4ODlkODU4NyA5ODE3ODY4NS1kNDA5LTQ2ZTAtOGUxNi03ZWYwZGIwZGI2NGFcbiAgICAgIG5hbWU6ICdtc2lkJyxcbiAgICAgIHJlZzogL15tc2lkOiguKikvLFxuICAgICAgZm9ybWF0OiBcIm1zaWQ6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9cHRpbWU6MjBcbiAgICAgIG5hbWU6ICdwdGltZScsXG4gICAgICByZWc6IC9ecHRpbWU6KFxcZCopLyxcbiAgICAgIGZvcm1hdDogXCJwdGltZTolZFwiXG4gICAgfSxcbiAgICB7IC8vYT1tYXhwdGltZTo2MFxuICAgICAgbmFtZTogJ21heHB0aW1lJyxcbiAgICAgIHJlZzogL15tYXhwdGltZTooXFxkKikvLFxuICAgICAgZm9ybWF0OiBcIm1heHB0aW1lOiVkXCJcbiAgICB9LFxuICAgIHsgLy9hPXNlbmRyZWN2XG4gICAgICBuYW1lOiAnZGlyZWN0aW9uJyxcbiAgICAgIHJlZzogL14oc2VuZHJlY3Z8cmVjdm9ubHl8c2VuZG9ubHl8aW5hY3RpdmUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLWxpdGVcbiAgICAgIG5hbWU6ICdpY2VsaXRlJyxcbiAgICAgIHJlZzogL14oaWNlLWxpdGUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLXVmcmFnOkY3Z0lcbiAgICAgIG5hbWU6ICdpY2VVZnJhZycsXG4gICAgICByZWc6IC9eaWNlLXVmcmFnOihcXFMqKS8sXG4gICAgICBmb3JtYXQ6IFwiaWNlLXVmcmFnOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1wd2Q6eDljbWwvWXppY2hWMitYbGhpTXU4Z1xuICAgICAgbmFtZTogJ2ljZVB3ZCcsXG4gICAgICByZWc6IC9eaWNlLXB3ZDooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1wd2Q6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9ZmluZ2VycHJpbnQ6U0hBLTEgMDA6MTE6MjI6MzM6NDQ6NTU6NjY6Nzc6ODg6OTk6QUE6QkI6Q0M6REQ6RUU6RkY6MDA6MTE6MjI6MzNcbiAgICAgIG5hbWU6ICdmaW5nZXJwcmludCcsXG4gICAgICByZWc6IC9eZmluZ2VycHJpbnQ6KFxcUyopIChcXFMqKS8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ2hhc2gnXSxcbiAgICAgIGZvcm1hdDogXCJmaW5nZXJwcmludDolcyAlc1wiXG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Y2FuZGlkYXRlOjAgMSBVRFAgMjExMzY2NzMyNyAyMDMuMC4xMTMuMSA1NDQwMCB0eXAgaG9zdFxuICAgICAgLy9hPWNhbmRpZGF0ZToxMTYyODc1MDgxIDEgdWRwIDIxMTM5MzcxNTEgMTkyLjE2OC4zNC43NSA2MDAxNyB0eXAgaG9zdCBnZW5lcmF0aW9uIDBcbiAgICAgIC8vYT1jYW5kaWRhdGU6MzI4OTkxMjk1NyAyIHVkcCAxODQ1NTAxNjk1IDE5My44NC43Ny4xOTQgNjAwMTcgdHlwIHNyZmx4IHJhZGRyIDE5Mi4xNjguMzQuNzUgcnBvcnQgNjAwMTcgZ2VuZXJhdGlvbiAwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjIyOTgxNTYyMCAxIHRjcCAxNTE4MjgwNDQ3IDE5Mi4xNjguMTUwLjE5IDYwMDE3IHR5cCBob3N0IHRjcHR5cGUgYWN0aXZlIGdlbmVyYXRpb24gMFxuICAgICAgLy9hPWNhbmRpZGF0ZTozMjg5OTEyOTU3IDIgdGNwIDE4NDU1MDE2OTUgMTkzLjg0Ljc3LjE5NCA2MDAxNyB0eXAgc3JmbHggcmFkZHIgMTkyLjE2OC4zNC43NSBycG9ydCA2MDAxNyB0Y3B0eXBlIHBhc3NpdmUgZ2VuZXJhdGlvbiAwXG4gICAgICBwdXNoOidjYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL15jYW5kaWRhdGU6KFxcUyopIChcXGQqKSAoXFxTKikgKFxcZCopIChcXFMqKSAoXFxkKikgdHlwIChcXFMqKSg/OiByYWRkciAoXFxTKikgcnBvcnQgKFxcZCopKT8oPzogdGNwdHlwZSAoXFxTKikpPyg/OiBnZW5lcmF0aW9uIChcXGQqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2ZvdW5kYXRpb24nLCAnY29tcG9uZW50JywgJ3RyYW5zcG9ydCcsICdwcmlvcml0eScsICdpcCcsICdwb3J0JywgJ3R5cGUnLCAncmFkZHInLCAncnBvcnQnLCAndGNwdHlwZScsICdnZW5lcmF0aW9uJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHZhciBzdHIgPSBcImNhbmRpZGF0ZTolcyAlZCAlcyAlZCAlcyAlZCB0eXAgJXNcIjtcblxuICAgICAgICBzdHIgKz0gKG8ucmFkZHIgIT0gbnVsbCkgPyBcIiByYWRkciAlcyBycG9ydCAlZFwiIDogXCIldiV2XCI7XG5cbiAgICAgICAgLy8gTkI6IGNhbmRpZGF0ZSBoYXMgdGhyZWUgb3B0aW9uYWwgY2h1bmtzLCBzbyAldm9pZCBtaWRkbGVzIG9uZSBpZiBpdCdzIG1pc3NpbmdcbiAgICAgICAgc3RyICs9IChvLnRjcHR5cGUgIT0gbnVsbCkgPyBcIiB0Y3B0eXBlICVzXCIgOiBcIiV2XCI7XG5cbiAgICAgICAgaWYgKG8uZ2VuZXJhdGlvbiAhPSBudWxsKSB7XG4gICAgICAgICAgc3RyICs9IFwiIGdlbmVyYXRpb24gJWRcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9ZW5kLW9mLWNhbmRpZGF0ZXMgKGtlZXAgYWZ0ZXIgdGhlIGNhbmRpZGF0ZXMgbGluZSBmb3IgcmVhZGFiaWxpdHkpXG4gICAgICBuYW1lOiAnZW5kT2ZDYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL14oZW5kLW9mLWNhbmRpZGF0ZXMpL1xuICAgIH0sXG4gICAgeyAvL2E9cmVtb3RlLWNhbmRpZGF0ZXM6MSAyMDMuMC4xMTMuMSA1NDQwMCAyIDIwMy4wLjExMy4xIDU0NDAxIC4uLlxuICAgICAgbmFtZTogJ3JlbW90ZUNhbmRpZGF0ZXMnLFxuICAgICAgcmVnOiAvXnJlbW90ZS1jYW5kaWRhdGVzOiguKikvLFxuICAgICAgZm9ybWF0OiBcInJlbW90ZS1jYW5kaWRhdGVzOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1vcHRpb25zOmdvb2dsZS1pY2VcbiAgICAgIG5hbWU6ICdpY2VPcHRpb25zJyxcbiAgICAgIHJlZzogL15pY2Utb3B0aW9uczooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1vcHRpb25zOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXNzcmM6MjU2NjEwNzU2OSBjbmFtZTp0OVlVOE0xVXhURjhZMUExXG4gICAgICBwdXNoOiBcInNzcmNzXCIsXG4gICAgICByZWc6IC9ec3NyYzooXFxkKikgKFtcXHdfXSopOiguKikvLFxuICAgICAgbmFtZXM6IFsnaWQnLCAnYXR0cmlidXRlJywgJ3ZhbHVlJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYzolZCAlczolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1zc3JjLWdyb3VwOkZFQyAxIDJcbiAgICAgIHB1c2g6IFwic3NyY0dyb3Vwc1wiLFxuICAgICAgcmVnOiAvXnNzcmMtZ3JvdXA6KFxcdyopICguKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWNzJywgJ3NzcmNzJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYy1ncm91cDolcyAlc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkLXNlbWFudGljOiBXTVMgSnZsYW01WDNTWDFPUDZwbjIweldvZ3ZhS0p6NUhqZjlPbmxWXG4gICAgICBuYW1lOiBcIm1zaWRTZW1hbnRpY1wiLFxuICAgICAgcmVnOiAvXm1zaWQtc2VtYW50aWM6XFxzPyhcXHcqKSAoXFxTKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWMnLCAndG9rZW4nXSxcbiAgICAgIGZvcm1hdDogXCJtc2lkLXNlbWFudGljOiAlcyAlc1wiIC8vIHNwYWNlIGFmdGVyIFwiOlwiIGlzIG5vdCBhY2NpZGVudGFsXG4gICAgfSxcbiAgICB7IC8vYT1ncm91cDpCVU5ETEUgYXVkaW8gdmlkZW9cbiAgICAgIHB1c2g6ICdncm91cHMnLFxuICAgICAgcmVnOiAvXmdyb3VwOihcXHcqKSAoLiopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbWlkcyddLFxuICAgICAgZm9ybWF0OiBcImdyb3VwOiVzICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtbXV4XG4gICAgICBuYW1lOiAncnRjcE11eCcsXG4gICAgICByZWc6IC9eKHJ0Y3AtbXV4KS9cbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtcnNpemVcbiAgICAgIG5hbWU6ICdydGNwUnNpemUnLFxuICAgICAgcmVnOiAvXihydGNwLXJzaXplKS9cbiAgICB9LFxuICAgIHsgLy8gYW55IGE9IHRoYXQgd2UgZG9uJ3QgdW5kZXJzdGFuZCBpcyBrZXB0cyB2ZXJiYXRpbSBvbiBtZWRpYS5pbnZhbGlkXG4gICAgICBwdXNoOiAnaW52YWxpZCcsXG4gICAgICBuYW1lczogW1widmFsdWVcIl1cbiAgICB9XG4gIF1cbn07XG5cbi8vIHNldCBzZW5zaWJsZSBkZWZhdWx0cyB0byBhdm9pZCBwb2xsdXRpbmcgdGhlIGdyYW1tYXIgd2l0aCBib3JpbmcgZGV0YWlsc1xuT2JqZWN0LmtleXMoZ3JhbW1hcikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gIHZhciBvYmpzID0gZ3JhbW1hcltrZXldO1xuICBvYmpzLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgIGlmICghb2JqLnJlZykge1xuICAgICAgb2JqLnJlZyA9IC8oLiopLztcbiAgICB9XG4gICAgaWYgKCFvYmouZm9ybWF0KSB7XG4gICAgICBvYmouZm9ybWF0ID0gXCIlc1wiO1xuICAgIH1cbiAgfSk7XG59KTtcbiIsInZhciBwYXJzZXIgPSByZXF1aXJlKCcuL3BhcnNlcicpO1xudmFyIHdyaXRlciA9IHJlcXVpcmUoJy4vd3JpdGVyJyk7XG5cbmV4cG9ydHMud3JpdGUgPSB3cml0ZXI7XG5leHBvcnRzLnBhcnNlID0gcGFyc2VyLnBhcnNlO1xuZXhwb3J0cy5wYXJzZUZtdHBDb25maWcgPSBwYXJzZXIucGFyc2VGbXRwQ29uZmlnO1xuZXhwb3J0cy5wYXJzZVBheWxvYWRzID0gcGFyc2VyLnBhcnNlUGF5bG9hZHM7XG5leHBvcnRzLnBhcnNlUmVtb3RlQ2FuZGlkYXRlcyA9IHBhcnNlci5wYXJzZVJlbW90ZUNhbmRpZGF0ZXM7XG4iLCJ2YXIgdG9JbnRJZkludCA9IGZ1bmN0aW9uICh2KSB7XG4gIHJldHVybiBTdHJpbmcoTnVtYmVyKHYpKSA9PT0gdiA/IE51bWJlcih2KSA6IHY7XG59O1xuXG52YXIgYXR0YWNoUHJvcGVydGllcyA9IGZ1bmN0aW9uIChtYXRjaCwgbG9jYXRpb24sIG5hbWVzLCByYXdOYW1lKSB7XG4gIGlmIChyYXdOYW1lICYmICFuYW1lcykge1xuICAgIGxvY2F0aW9uW3Jhd05hbWVdID0gdG9JbnRJZkludChtYXRjaFsxXSk7XG4gIH1cbiAgZWxzZSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgaWYgKG1hdGNoW2krMV0gIT0gbnVsbCkge1xuICAgICAgICBsb2NhdGlvbltuYW1lc1tpXV0gPSB0b0ludElmSW50KG1hdGNoW2krMV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxudmFyIHBhcnNlUmVnID0gZnVuY3Rpb24gKG9iaiwgbG9jYXRpb24sIGNvbnRlbnQpIHtcbiAgdmFyIG5lZWRzQmxhbmsgPSBvYmoubmFtZSAmJiBvYmoubmFtZXM7XG4gIGlmIChvYmoucHVzaCAmJiAhbG9jYXRpb25bb2JqLnB1c2hdKSB7XG4gICAgbG9jYXRpb25bb2JqLnB1c2hdID0gW107XG4gIH1cbiAgZWxzZSBpZiAobmVlZHNCbGFuayAmJiAhbG9jYXRpb25bb2JqLm5hbWVdKSB7XG4gICAgbG9jYXRpb25bb2JqLm5hbWVdID0ge307XG4gIH1cbiAgdmFyIGtleUxvY2F0aW9uID0gb2JqLnB1c2ggP1xuICAgIHt9IDogIC8vIGJsYW5rIG9iamVjdCB0aGF0IHdpbGwgYmUgcHVzaGVkXG4gICAgbmVlZHNCbGFuayA/IGxvY2F0aW9uW29iai5uYW1lXSA6IGxvY2F0aW9uOyAvLyBvdGhlcndpc2UsIG5hbWVkIGxvY2F0aW9uIG9yIHJvb3RcblxuICBhdHRhY2hQcm9wZXJ0aWVzKGNvbnRlbnQubWF0Y2gob2JqLnJlZyksIGtleUxvY2F0aW9uLCBvYmoubmFtZXMsIG9iai5uYW1lKTtcblxuICBpZiAob2JqLnB1c2gpIHtcbiAgICBsb2NhdGlvbltvYmoucHVzaF0ucHVzaChrZXlMb2NhdGlvbik7XG4gIH1cbn07XG5cbnZhciBncmFtbWFyID0gcmVxdWlyZSgnLi9ncmFtbWFyJyk7XG52YXIgdmFsaWRMaW5lID0gUmVnRXhwLnByb3RvdHlwZS50ZXN0LmJpbmQoL14oW2Etel0pPSguKikvKTtcblxuZXhwb3J0cy5wYXJzZSA9IGZ1bmN0aW9uIChzZHApIHtcbiAgdmFyIHNlc3Npb24gPSB7fVxuICAgICwgbWVkaWEgPSBbXVxuICAgICwgbG9jYXRpb24gPSBzZXNzaW9uOyAvLyBwb2ludHMgYXQgd2hlcmUgcHJvcGVydGllcyBnbyB1bmRlciAob25lIG9mIHRoZSBhYm92ZSlcblxuICAvLyBwYXJzZSBsaW5lcyB3ZSB1bmRlcnN0YW5kXG4gIHNkcC5zcGxpdCgvKFxcclxcbnxcXHJ8XFxuKS8pLmZpbHRlcih2YWxpZExpbmUpLmZvckVhY2goZnVuY3Rpb24gKGwpIHtcbiAgICB2YXIgdHlwZSA9IGxbMF07XG4gICAgdmFyIGNvbnRlbnQgPSBsLnNsaWNlKDIpO1xuICAgIGlmICh0eXBlID09PSAnbScpIHtcbiAgICAgIG1lZGlhLnB1c2goe3J0cDogW10sIGZtdHA6IFtdfSk7XG4gICAgICBsb2NhdGlvbiA9IG1lZGlhW21lZGlhLmxlbmd0aC0xXTsgLy8gcG9pbnQgYXQgbGF0ZXN0IG1lZGlhIGxpbmVcbiAgICB9XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IChncmFtbWFyW3R5cGVdIHx8IFtdKS5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgdmFyIG9iaiA9IGdyYW1tYXJbdHlwZV1bal07XG4gICAgICBpZiAob2JqLnJlZy50ZXN0KGNvbnRlbnQpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVJlZyhvYmosIGxvY2F0aW9uLCBjb250ZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHNlc3Npb24ubWVkaWEgPSBtZWRpYTsgLy8gbGluayBpdCB1cFxuICByZXR1cm4gc2Vzc2lvbjtcbn07XG5cbnZhciBmbXRwUmVkdWNlciA9IGZ1bmN0aW9uIChhY2MsIGV4cHIpIHtcbiAgdmFyIHMgPSBleHByLnNwbGl0KCc9Jyk7XG4gIGlmIChzLmxlbmd0aCA9PT0gMikge1xuICAgIGFjY1tzWzBdXSA9IHRvSW50SWZJbnQoc1sxXSk7XG4gIH1cbiAgcmV0dXJuIGFjYztcbn07XG5cbmV4cG9ydHMucGFyc2VGbXRwQ29uZmlnID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KC9cXDtcXHM/LykucmVkdWNlKGZtdHBSZWR1Y2VyLCB7fSk7XG59O1xuXG5leHBvcnRzLnBhcnNlUGF5bG9hZHMgPSBmdW5jdGlvbiAoc3RyKSB7XG4gIHJldHVybiBzdHIuc3BsaXQoJyAnKS5tYXAoTnVtYmVyKTtcbn07XG5cbmV4cG9ydHMucGFyc2VSZW1vdGVDYW5kaWRhdGVzID0gZnVuY3Rpb24gKHN0cikge1xuICB2YXIgY2FuZGlkYXRlcyA9IFtdO1xuICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoJyAnKS5tYXAodG9JbnRJZkludCk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpICs9IDMpIHtcbiAgICBjYW5kaWRhdGVzLnB1c2goe1xuICAgICAgY29tcG9uZW50OiBwYXJ0c1tpXSxcbiAgICAgIGlwOiBwYXJ0c1tpICsgMV0sXG4gICAgICBwb3J0OiBwYXJ0c1tpICsgMl1cbiAgICB9KTtcbiAgfVxuICByZXR1cm4gY2FuZGlkYXRlcztcbn07XG4iLCJ2YXIgZ3JhbW1hciA9IHJlcXVpcmUoJy4vZ3JhbW1hcicpO1xuXG4vLyBjdXN0b21pemVkIHV0aWwuZm9ybWF0IC0gZGlzY2FyZHMgZXhjZXNzIGFyZ3VtZW50cyBhbmQgY2FuIHZvaWQgbWlkZGxlIG9uZXNcbnZhciBmb3JtYXRSZWdFeHAgPSAvJVtzZHYlXS9nO1xudmFyIGZvcm1hdCA9IGZ1bmN0aW9uIChmb3JtYXRTdHIpIHtcbiAgdmFyIGkgPSAxO1xuICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgdmFyIGxlbiA9IGFyZ3MubGVuZ3RoO1xuICByZXR1cm4gZm9ybWF0U3RyLnJlcGxhY2UoZm9ybWF0UmVnRXhwLCBmdW5jdGlvbiAoeCkge1xuICAgIGlmIChpID49IGxlbikge1xuICAgICAgcmV0dXJuIHg7IC8vIG1pc3NpbmcgYXJndW1lbnRcbiAgICB9XG4gICAgdmFyIGFyZyA9IGFyZ3NbaV07XG4gICAgaSArPSAxO1xuICAgIHN3aXRjaCAoeCkge1xuICAgICAgY2FzZSAnJSUnOlxuICAgICAgICByZXR1cm4gJyUnO1xuICAgICAgY2FzZSAnJXMnOlxuICAgICAgICByZXR1cm4gU3RyaW5nKGFyZyk7XG4gICAgICBjYXNlICclZCc6XG4gICAgICAgIHJldHVybiBOdW1iZXIoYXJnKTtcbiAgICAgIGNhc2UgJyV2JzpcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfSk7XG4gIC8vIE5COiB3ZSBkaXNjYXJkIGV4Y2VzcyBhcmd1bWVudHMgLSB0aGV5IGFyZSB0eXBpY2FsbHkgdW5kZWZpbmVkIGZyb20gbWFrZUxpbmVcbn07XG5cbnZhciBtYWtlTGluZSA9IGZ1bmN0aW9uICh0eXBlLCBvYmosIGxvY2F0aW9uKSB7XG4gIHZhciBzdHIgPSBvYmouZm9ybWF0IGluc3RhbmNlb2YgRnVuY3Rpb24gP1xuICAgIChvYmouZm9ybWF0KG9iai5wdXNoID8gbG9jYXRpb24gOiBsb2NhdGlvbltvYmoubmFtZV0pKSA6XG4gICAgb2JqLmZvcm1hdDtcblxuICB2YXIgYXJncyA9IFt0eXBlICsgJz0nICsgc3RyXTtcbiAgaWYgKG9iai5uYW1lcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqLm5hbWVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICB2YXIgbiA9IG9iai5uYW1lc1tpXTtcbiAgICAgIGlmIChvYmoubmFtZSkge1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVdW25dKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgeyAvLyBmb3IgbUxpbmUgYW5kIHB1c2ggYXR0cmlidXRlc1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVzW2ldXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIGFyZ3MucHVzaChsb2NhdGlvbltvYmoubmFtZV0pO1xuICB9XG4gIHJldHVybiBmb3JtYXQuYXBwbHkobnVsbCwgYXJncyk7XG59O1xuXG4vLyBSRkMgc3BlY2lmaWVkIG9yZGVyXG4vLyBUT0RPOiBleHRlbmQgdGhpcyB3aXRoIGFsbCB0aGUgcmVzdFxudmFyIGRlZmF1bHRPdXRlck9yZGVyID0gW1xuICAndicsICdvJywgJ3MnLCAnaScsXG4gICd1JywgJ2UnLCAncCcsICdjJyxcbiAgJ2InLCAndCcsICdyJywgJ3onLCAnYSdcbl07XG52YXIgZGVmYXVsdElubmVyT3JkZXIgPSBbJ2knLCAnYycsICdiJywgJ2EnXTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzZXNzaW9uLCBvcHRzKSB7XG4gIG9wdHMgPSBvcHRzIHx8IHt9O1xuICAvLyBlbnN1cmUgY2VydGFpbiBwcm9wZXJ0aWVzIGV4aXN0XG4gIGlmIChzZXNzaW9uLnZlcnNpb24gPT0gbnVsbCkge1xuICAgIHNlc3Npb24udmVyc2lvbiA9IDA7IC8vIFwidj0wXCIgbXVzdCBiZSB0aGVyZSAob25seSBkZWZpbmVkIHZlcnNpb24gYXRtKVxuICB9XG4gIGlmIChzZXNzaW9uLm5hbWUgPT0gbnVsbCkge1xuICAgIHNlc3Npb24ubmFtZSA9IFwiIFwiOyAvLyBcInM9IFwiIG11c3QgYmUgdGhlcmUgaWYgbm8gbWVhbmluZ2Z1bCBuYW1lIHNldFxuICB9XG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBpZiAobUxpbmUucGF5bG9hZHMgPT0gbnVsbCkge1xuICAgICAgbUxpbmUucGF5bG9hZHMgPSBcIlwiO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIG91dGVyT3JkZXIgPSBvcHRzLm91dGVyT3JkZXIgfHwgZGVmYXVsdE91dGVyT3JkZXI7XG4gIHZhciBpbm5lck9yZGVyID0gb3B0cy5pbm5lck9yZGVyIHx8IGRlZmF1bHRJbm5lck9yZGVyO1xuICB2YXIgc2RwID0gW107XG5cbiAgLy8gbG9vcCB0aHJvdWdoIG91dGVyT3JkZXIgZm9yIG1hdGNoaW5nIHByb3BlcnRpZXMgb24gc2Vzc2lvblxuICBvdXRlck9yZGVyLmZvckVhY2goZnVuY3Rpb24gKHR5cGUpIHtcbiAgICBncmFtbWFyW3R5cGVdLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgICAgaWYgKG9iai5uYW1lIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoubmFtZV0gIT0gbnVsbCkge1xuICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIHNlc3Npb24pKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoucHVzaF0gIT0gbnVsbCkge1xuICAgICAgICBzZXNzaW9uW29iai5wdXNoXS5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIHNkcC5wdXNoKG1ha2VMaW5lKHR5cGUsIG9iaiwgZWwpKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIHRoZW4gZm9yIGVhY2ggbWVkaWEgbGluZSwgZm9sbG93IHRoZSBpbm5lck9yZGVyXG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBzZHAucHVzaChtYWtlTGluZSgnbScsIGdyYW1tYXIubVswXSwgbUxpbmUpKTtcblxuICAgIGlubmVyT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAodHlwZSkge1xuICAgICAgZ3JhbW1hclt0eXBlXS5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgaWYgKG9iai5uYW1lIGluIG1MaW5lICYmIG1MaW5lW29iai5uYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBtTGluZSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIG1MaW5lICYmIG1MaW5lW29iai5wdXNoXSAhPSBudWxsKSB7XG4gICAgICAgICAgbUxpbmVbb2JqLnB1c2hdLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIGVsKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gc2RwLmpvaW4oJ1xcclxcbicpICsgJ1xcclxcbic7XG59O1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGFycmF5RXF1YWxzKGFycmF5KSB7XG4gICAgLy8gaWYgdGhlIG90aGVyIGFycmF5IGlzIGEgZmFsc3kgdmFsdWUsIHJldHVyblxuICAgIGlmICghYXJyYXkpXG4gICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgIC8vIGNvbXBhcmUgbGVuZ3RocyAtIGNhbiBzYXZlIGEgbG90IG9mIHRpbWVcbiAgICBpZiAodGhpcy5sZW5ndGggIT0gYXJyYXkubGVuZ3RoKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgbmVzdGVkIGFycmF5c1xuICAgICAgICBpZiAodGhpc1tpXSBpbnN0YW5jZW9mIEFycmF5ICYmIGFycmF5W2ldIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIHJlY3Vyc2UgaW50byB0aGUgbmVzdGVkIGFycmF5c1xuICAgICAgICAgICAgaWYgKCFhcnJheUVxdWFscy5hcHBseSh0aGlzW2ldLCBbYXJyYXlbaV1dKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpc1tpXSAhPSBhcnJheVtpXSkge1xuICAgICAgICAgICAgLy8gV2FybmluZyAtIHR3byBkaWZmZXJlbnQgb2JqZWN0IGluc3RhbmNlcyB3aWxsIG5ldmVyIGJlIGVxdWFsOlxuICAgICAgICAgICAgLy8ge3g6MjB9ICE9IHt4OjIwfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufTtcblxuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnRzLkludGVyb3AgPSByZXF1aXJlKCcuL2ludGVyb3AnKTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyogZ2xvYmFsIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbiAqL1xuLyogZ2xvYmFsIFJUQ0ljZUNhbmRpZGF0ZSAqL1xuLyoganNoaW50IC1XMDk3ICovXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIHRyYW5zZm9ybSA9IHJlcXVpcmUoJy4vdHJhbnNmb3JtJyk7XG52YXIgYXJyYXlFcXVhbHMgPSByZXF1aXJlKCcuL2FycmF5LWVxdWFscycpO1xuXG5mdW5jdGlvbiBJbnRlcm9wKCkge1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtYXAgaG9sZHMgdGhlIG1vc3QgcmVjZW50IFVuaWZpZWQgUGxhbiBvZmZlci9hbnN3ZXIgU0RQIHRoYXQgd2FzXG4gICAgICogY29udmVydGVkIHRvIFBsYW4gQiwgd2l0aCB0aGUgU0RQIHR5cGUgKCdvZmZlcicgb3IgJ2Fuc3dlcicpIGFzIGtleXMgYW5kXG4gICAgICogdGhlIFNEUCBzdHJpbmcgYXMgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHR5cGUge3t9fVxuICAgICAqL1xuICAgIHRoaXMuY2FjaGUgPSB7XG4gICAgICAgIG1sQjJVTWFwIDoge30sXG4gICAgICAgIG1sVTJCTWFwIDoge31cbiAgICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEludGVyb3A7XG5cbi8qKlxuICogQ2hhbmdlcyB0aGUgY2FuZGlkYXRlIGFyZ3MgdG8gbWF0Y2ggd2l0aCB0aGUgcmVsYXRlZCBVbmlmaWVkIFBsYW5cbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuY2FuZGlkYXRlVG9VbmlmaWVkUGxhbiA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHZhciBjYW5kID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuXG4gICAgY2FuZC5zZHBNTGluZUluZGV4ID0gdGhpcy5jYWNoZS5tbEIyVU1hcFtjYW5kLnNkcE1MaW5lSW5kZXhdO1xuICAgIC8qIFRPRE86IGNoYW5nZSBzZHBNaWQgdG8gKGF1ZGlvfHZpZGVvKS1TU1JDICovXG5cbiAgICByZXR1cm4gY2FuZDtcbn07XG5cbi8qKlxuICogQ2hhbmdlcyB0aGUgY2FuZGlkYXRlIGFyZ3MgdG8gbWF0Y2ggd2l0aCB0aGUgcmVsYXRlZCBQbGFuIEJcbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuY2FuZGlkYXRlVG9QbGFuQiA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHZhciBjYW5kID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuXG4gICAgaWYgKGNhbmQuc2RwTWlkLmluZGV4T2YoJ2F1ZGlvJykgPT09IDApIHtcbiAgICAgIGNhbmQuc2RwTWlkID0gJ2F1ZGlvJztcbiAgICB9IGVsc2UgaWYgKGNhbmQuc2RwTWlkLmluZGV4T2YoJ3ZpZGVvJykgPT09IDApIHtcbiAgICAgIGNhbmQuc2RwTWlkID0gJ3ZpZGVvJztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5kaWRhdGUgd2l0aCAnICsgY2FuZC5zZHBNaWQgKyAnIG5vdCBhbGxvd2VkJyk7XG4gICAgfVxuXG4gICAgY2FuZC5zZHBNTGluZUluZGV4ID0gdGhpcy5jYWNoZS5tbFUyQk1hcFtjYW5kLnNkcE1MaW5lSW5kZXhdO1xuXG4gICAgcmV0dXJuIGNhbmQ7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBtLWxpbmUgd2l0aCB0aGUgZ2l2ZW4gbWVkaWEgdHlwZSBhbmQgd2l0aCBhXG4gKiBkaXJlY3Rpb24gd2hpY2ggYWxsb3dzIHNlbmRpbmcsIGluIHRoZSBsYXN0IFVuaWZpZWQgUGxhbiBkZXNjcmlwdGlvbiB3aXRoXG4gKiB0eXBlIFwiYW5zd2VyXCIgY29udmVydGVkIHRvIFBsYW4gQi4gUmV0dXJucyB7bnVsbH0gaWYgdGhlcmUgaXMgbm8gc2F2ZWRcbiAqIGFuc3dlciwgb3IgaWYgbm9uZSBvZiBpdHMgbS1saW5lcyB3aXRoIHRoZSBnaXZlbiB0eXBlIGFsbG93IHNlbmRpbmcuXG4gKiBAcGFyYW0gdHlwZSB0aGUgbWVkaWEgdHlwZSAoXCJhdWRpb1wiIG9yIFwidmlkZW9cIikuXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyID0gZnVuY3Rpb24odHlwZSkge1xuICAgIGlmICghdGhpcy5jYWNoZS5hbnN3ZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UodGhpcy5jYWNoZS5hbnN3ZXIpO1xuICAgIGlmIChzZXNzaW9uICYmIHNlc3Npb24ubWVkaWEgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSl7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vzc2lvbi5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHNlc3Npb24ubWVkaWFbaV0udHlwZSA9PSB0eXBlICYmXG4gICAgICAgICAgICAgICAgKCFzZXNzaW9uLm1lZGlhW2ldLmRpcmVjdGlvbiAvKiBkZWZhdWx0IHRvIHNlbmRyZWN2ICovIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn07XG5cbi8qKlxuICogVGhpcyBtZXRob2QgdHJhbnNmb3JtcyBhIFVuaWZpZWQgUGxhbiBTRFAgdG8gYW4gZXF1aXZhbGVudCBQbGFuIEIgU0RQLiBBXG4gKiBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIHRyYW5zZm9ybXMgdGhlIFNEUCB0byBQbGFuIEIgYmVmb3JlIHBhc3NpbmcgaXQgdG8gdGhlXG4gKiBhcHBsaWNhdGlvbi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvUGxhbkIgPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBPYmplY3RpZnkgdGhlIFNEUCBmb3IgZWFzaWVyIG1hbmlwdWxhdGlvbi5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFVuaWZpZWQgUGxhbiBTRFAuIFBsYW4gQlxuICAgIC8vIFNEUCBoYXMgYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA8PSAzICYmIHNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBVbmlmaWVkIFBsYW4uJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vI2VuZHJlZ2lvblxuXG4gICAgLy8gSEFDSyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMTEzNDQzXG4gICAgdmFyIHNkcCA9IGRlc2Muc2RwO1xuICAgIHZhciByZXdyaXRlID0gZmFsc2U7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB1TGluZSA9IHNlc3Npb24ubWVkaWFbaV07XG4gICAgICAgIHVMaW5lLnJ0cC5mb3JFYWNoKGZ1bmN0aW9uKHJ0cCkge1xuICAgICAgICAgICAgaWYgKHJ0cC5jb2RlYyA9PT0gJ05VTEwnKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHJld3JpdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBvZmZlciA9IHRyYW5zZm9ybS5wYXJzZShzZWxmLmNhY2hlLm9mZmVyKTtcbiAgICAgICAgICAgICAgICBydHAuY29kZWMgPSBvZmZlci5tZWRpYVtpXS5ydHBbMF0uY29kZWM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAocmV3cml0ZSkge1xuICAgICAgICBzZHAgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG4gICAgfVxuXG4gICAgLy8gVW5pZmllZCBQbGFuIFNEUCBpcyBvdXIgXCJwcmVjaW91c1wiLiBDYWNoZSBpdCBmb3IgbGF0ZXIgdXNlIGluIHRoZSBQbGFuIEJcbiAgICAvLyAtPiBVbmlmaWVkIFBsYW4gdHJhbnNmb3JtYXRpb24uXG4gICAgdGhpcy5jYWNoZVtkZXNjLnR5cGVdID0gc2RwO1xuXG4gICAgLy8jcmVnaW9uIENvbnZlcnQgZnJvbSBVbmlmaWVkIFBsYW4gdG8gUGxhbiBCLlxuXG4gICAgLy8gV2UgcmVidWlsZCB0aGUgc2Vzc2lvbi5tZWRpYSBhcnJheS5cbiAgICB2YXIgbWVkaWEgPSBzZXNzaW9uLm1lZGlhO1xuICAgIHNlc3Npb24ubWVkaWEgPSBbXTtcblxuICAgIC8vIEFzc29jaWF0aXZlIGFycmF5IHRoYXQgbWFwcyBjaGFubmVsIHR5cGVzIHRvIGNoYW5uZWwgb2JqZWN0cyBmb3IgZmFzdFxuICAgIC8vIGFjY2VzcyB0byBjaGFubmVsIG9iamVjdHMgYnkgdGhlaXIgdHlwZSwgZS5nLiB0eXBlMmJsWydhdWRpbyddLT5jaGFubmVsXG4gICAgLy8gb2JqLlxuICAgIHZhciB0eXBlMmJsID0ge307XG5cbiAgICAvLyBVc2VkIHRvIGJ1aWxkIHRoZSBncm91cDpCVU5ETEUgdmFsdWUgYWZ0ZXIgdGhlIGNoYW5uZWxzIGNvbnN0cnVjdGlvblxuICAgIC8vIGxvb3AuXG4gICAgdmFyIHR5cGVzID0gW107XG5cbiAgICBtZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKHVMaW5lKSB7XG4gICAgICAgIC8vIHJ0Y3AtbXV4IGlzIHJlcXVpcmVkIGluIHRoZSBQbGFuIEIgU0RQLlxuICAgICAgICBpZiAoKHR5cGVvZiB1TGluZS5ydGNwTXV4ICE9PSAnc3RyaW5nJyB8fFxuICAgICAgICAgICAgdUxpbmUucnRjcE11eCAhPT0gJ3J0Y3AtbXV4JykgJiZcbiAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29udmVydCB0byBQbGFuIEIgYmVjYXVzZSBtLWxpbmVzICcgK1xuICAgICAgICAgICAgICAgICd3aXRob3V0IHRoZSBydGNwLW11eCBhdHRyaWJ1dGUgd2VyZSBmb3VuZC4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHdlIGRvbid0IGhhdmUgYSBjaGFubmVsIGZvciB0aGlzIHVMaW5lLnR5cGUgT1IgdGhlIHNlbGVjdGVkIGlzXG4gICAgICAgIC8vIGluYWN0aXZlLCB0aGVuIHNlbGVjdCB0aGlzIHVMaW5lIGFzIHRoZSBjaGFubmVsIGJhc2lzLlxuICAgICAgICBpZiAodHlwZW9mIHR5cGUyYmxbdUxpbmUudHlwZV0gPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLmRpcmVjdGlvbiA9PT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXSA9IHVMaW5lO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVMaW5lLnByb3RvY29sICE9IHR5cGUyYmxbdUxpbmUudHlwZV0ucHJvdG9jb2wpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHRvIFBsYW4gQiBiZWNhdXNlIG0tbGluZXMgJyArXG4gICAgICAgICAgICAgICdoYXZlIGRpZmZlcmVudCBwcm90b2NvbHMgYW5kIHRoaXMgbGlicmFyeSBkb2VzIG5vdCBoYXZlICcgK1xuICAgICAgICAgICAgICAnc3VwcG9ydCBmb3IgdGhhdCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVMaW5lLnBheWxvYWRzICE9IHR5cGUyYmxbdUxpbmUudHlwZV0ucGF5bG9hZHMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHRvIFBsYW4gQiBiZWNhdXNlIG0tbGluZXMgJyArXG4gICAgICAgICAgICAgICdoYXZlIGRpZmZlcmVudCBwYXlsb2FkcyBhbmQgdGhpcyBsaWJyYXJ5IGRvZXMgbm90IGhhdmUgJyArXG4gICAgICAgICAgICAgICdzdXBwb3J0IGZvciB0aGF0Jyk7XG4gICAgICAgIH1cblxuICAgIH0pO1xuXG4gICAgLy8gSW1wbG9kZSB0aGUgVW5pZmllZCBQbGFuIG0tbGluZXMvdHJhY2tzIGludG8gUGxhbiBCIGNoYW5uZWxzLlxuICAgIG1lZGlhLmZvckVhY2goZnVuY3Rpb24odUxpbmUpIHtcbiAgICAgICAgaWYgKHVMaW5lLnR5cGUgPT09ICdhcHBsaWNhdGlvbicpIHtcbiAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG4gICAgICAgICAgICB0eXBlcy5wdXNoKHVMaW5lLm1pZCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgc291cmNlcyB0byB0aGUgY2hhbm5lbCBhbmQgaGFuZGxlIGE9bXNpZC5cbiAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5zb3VyY2VzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgT2JqZWN0LmtleXModUxpbmUuc291cmNlcykuZm9yRWFjaChmdW5jdGlvbihzc3JjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXMgIT09ICdvYmplY3QnKVxuICAgICAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXMgPSB7fTtcblxuICAgICAgICAgICAgICAgIC8vIEFzc2lnbiB0aGUgc291cmNlcyB0byB0aGUgY2hhbm5lbC5cbiAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXNbc3NyY10gPVxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5tc2lkICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbiBQbGFuIEIgdGhlIG1zaWQgaXMgYW4gU1NSQyBhdHRyaWJ1dGUuIEFsc28sIHdlIGRvbid0XG4gICAgICAgICAgICAgICAgICAgIC8vIGNhcmUgYWJvdXQgdGhlIG9ic29sZXRlIGxhYmVsIGFuZCBtc2xhYmVsIGF0dHJpYnV0ZXMuXG4gICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGUgdGhhdCBpdCBpcyBub3QgZ3VhcmFudGVlZCB0aGF0IHRoZSB1TGluZSB3aWxsXG4gICAgICAgICAgICAgICAgICAgIC8vIGhhdmUgYW4gbXNpZC4gcmVjdm9ubHkgY2hhbm5lbHMgaW4gcGFydGljdWxhciBkb24ndCBoYXZlXG4gICAgICAgICAgICAgICAgICAgIC8vIG9uZS5cbiAgICAgICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zb3VyY2VzW3NzcmNdLm1zaWQgPVxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubXNpZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gTk9URSBzc3JjcyBpbiBzc3JjIGdyb3VwcyB3aWxsIHNoYXJlIG1zaWRzLCBhc1xuICAgICAgICAgICAgICAgIC8vIGRyYWZ0LXViZXJ0aS1ydGN3ZWItcGxhbi0wMCBtYW5kYXRlcy5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHNzcmMgZ3JvdXBzIHRvIHRoZSBjaGFubmVsLlxuICAgICAgICBpZiAodHlwZW9mIHVMaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheSh1TGluZS5zc3JjR3JvdXBzKSkge1xuXG4gICAgICAgICAgICAvLyBDcmVhdGUgdGhlIHNzcmNHcm91cHMgYXJyYXksIGlmIGl0J3Mgbm90IGRlZmluZWQuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcyA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgIUFycmF5LmlzQXJyYXkodHlwZTJibFt1TGluZS50eXBlXS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcyA9IFtdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMgPVxuICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3Vwcy5jb25jYXQoXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNzcmNHcm91cHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUyYmxbdUxpbmUudHlwZV0gPT09IHVMaW5lKSB7XG4gICAgICAgICAgICAvLyBQbGFuIEIgbWlkcyBhcmUgaW4gWydhdWRpbycsICd2aWRlbycsICdkYXRhJ11cbiAgICAgICAgICAgIHVMaW5lLm1pZCA9IHVMaW5lLnR5cGU7XG5cbiAgICAgICAgICAgIC8vIFBsYW4gQiBkb2Vzbid0IHN1cHBvcnQvbmVlZCB0aGUgYnVuZGxlLW9ubHkgYXR0cmlidXRlLlxuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLmJ1bmRsZU9ubHk7XG5cbiAgICAgICAgICAgIC8vIEluIFBsYW4gQiB0aGUgbXNpZCBpcyBhbiBTU1JDIGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuXG5cdCAgICBpZiAodUxpbmUudHlwZSA9PSBtZWRpYVswXS50eXBlKSB7XG5cdCAgICAgIHR5cGVzLnVuc2hpZnQodUxpbmUudHlwZSk7XG5cdCAgICAgIC8vIEFkZCB0aGUgY2hhbm5lbCB0byB0aGUgbmV3IG1lZGlhIGFycmF5LlxuXHQgICAgICBzZXNzaW9uLm1lZGlhLnVuc2hpZnQodUxpbmUpO1xuXHQgICAgfSBlbHNlIHtcblx0ICAgICAgdHlwZXMucHVzaCh1TGluZS50eXBlKTtcblx0ICAgICAgLy8gQWRkIHRoZSBjaGFubmVsIHRvIHRoZSBuZXcgbWVkaWEgYXJyYXkuXG5cdCAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG5cdCAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAvLyBXZSByZWdlbmVyYXRlIHRoZSBCVU5ETEUgZ3JvdXAgd2l0aCB0aGUgbmV3IG1pZHMuXG4gICAgICBzZXNzaW9uLmdyb3Vwcy5zb21lKGZ1bmN0aW9uKGdyb3VwKSB7XG5cdCAgaWYgKGdyb3VwLnR5cGUgPT09ICdCVU5ETEUnKSB7XG5cdCAgICAgIGdyb3VwLm1pZHMgPSB0eXBlcy5qb2luKCcgJyk7XG5cdCAgICAgIHJldHVybiB0cnVlO1xuXHQgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIG1zaWQgc2VtYW50aWNcbiAgICBzZXNzaW9uLm1zaWRTZW1hbnRpYyA9IHtcbiAgICAgICAgc2VtYW50aWM6ICdXTVMnLFxuICAgICAgICB0b2tlbjogJyonXG4gICAgfTtcblxuICAgIHZhciByZXNTdHIgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG5cbiAgICByZXR1cm4gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgIHR5cGU6IGRlc2MudHlwZSxcbiAgICAgICAgc2RwOiByZXNTdHJcbiAgICB9KTtcblxuICAgIC8vI2VuZHJlZ2lvblxufTtcblxuLyogZm9sbG93IHJ1bGVzIGRlZmluZWQgaW4gUkZDNDE0NSAqL1xuZnVuY3Rpb24gYWRkU2V0dXBBdHRyKHVMaW5lKSB7XG4gICAgaWYgKHR5cGVvZiB1TGluZS5zZXR1cCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh1TGluZS5zZXR1cCA9PT0gXCJhY3RpdmVcIikge1xuICAgICAgICAgICAgdUxpbmUuc2V0dXAgPSBcInBhc3NpdmVcIjtcbiAgICB9IGVsc2UgaWYgKHVMaW5lLnNldHVwID09PSBcInBhc3NpdmVcIikge1xuICAgICAgICB1TGluZS5zZXR1cCA9IFwiYWN0aXZlXCI7XG4gICAgfVxufVxuXG4vKipcbiAqIFRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYSBQbGFuIEIgU0RQIHRvIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIFNEUC4gQVxuICogUGVlckNvbm5lY3Rpb24gd3JhcHBlciB0cmFuc2Zvcm1zIHRoZSBTRFAgdG8gVW5pZmllZCBQbGFuIGJlZm9yZSBwYXNzaW5nIGl0XG4gKiB0byBGRi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvVW5pZmllZFBsYW4gPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFBsYW4gQiBTRFAuIFBsYW4gQiBTRFAgaGFzXG4gICAgLy8gYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA+IDMgfHwgIXNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBQbGFuIEIuJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vIE1ha2Ugc3VyZSB0aGlzIFBsYW4gQiBTRFAgY2FuIGJlIGNvbnZlcnRlZCB0byBhIFVuaWZpZWQgUGxhbiBTRFAuXG4gICAgdmFyIG1pZHMgPSBbXTtcbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24obSkge1xuICAgICAgICBtaWRzLnB1c2gobS5taWQpO1xuICAgIH0pO1xuXG4gICAgdmFyIGhhc0J1bmRsZSA9IGZhbHNlO1xuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG4gICAgICAgIGhhc0J1bmRsZSA9IHNlc3Npb24uZ3JvdXBzLmV2ZXJ5KGZ1bmN0aW9uKGcpIHtcbiAgICAgICAgICAgIHJldHVybiBnLnR5cGUgIT09ICdCVU5ETEUnIHx8XG4gICAgICAgICAgICAgICAgYXJyYXlFcXVhbHMuYXBwbHkoZy5taWRzLnNvcnQoKSwgW21pZHMuc29ydCgpXSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICghaGFzQnVuZGxlKSB7XG4gICAgICAgIHZhciBtdXN0QmVCdW5kbGUgPSBmYWxzZTtcblxuICAgICAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgaWYgKG0uZGlyZWN0aW9uICE9PSAnaW5hY3RpdmUnKSB7XG4gICAgICAgICAgICAgICAgbXVzdEJlQnVuZGxlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKG11c3RCZUJ1bmRsZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNvbnZlcnQgdG8gVW5pZmllZCBQbGFuIGJlY2F1c2UgbS1saW5lcyB0aGF0XCIgK1xuICAgICAgICAgICAgICBcIiBhcmUgbm90IGJ1bmRsZWQgd2VyZSBmb3VuZC5cIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyNlbmRyZWdpb25cblxuXG4gICAgLy8jcmVnaW9uIENvbnZlcnQgZnJvbSBQbGFuIEIgdG8gVW5pZmllZCBQbGFuLlxuXG4gICAgLy8gVW5mb3J0dW5hdGVseSwgYSBQbGFuIEIgb2ZmZXIvYW5zd2VyIGRvZXNuJ3QgaGF2ZSBlbm91Z2ggaW5mb3JtYXRpb24gdG9cbiAgICAvLyByZWJ1aWxkIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIG9mZmVyL2Fuc3dlci5cbiAgICAvL1xuICAgIC8vIEZvciBleGFtcGxlLCBpZiB0aGlzIGlzIGEgbG9jYWwgYW5zd2VyIChpbiBVbmlmaWVkIFBsYW4gc3R5bGUpIHRoYXQgd2VcbiAgICAvLyBjb252ZXJ0IHRvIFBsYW4gQiBwcmlvciB0byBoYW5kaW5nIGl0IG92ZXIgdG8gdGhlIGFwcGxpY2F0aW9uICh0aGVcbiAgICAvLyBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIGNhbGxlZCB1cywgZm9yIGluc3RhbmNlLCBhZnRlciBhIHN1Y2Nlc3NmdWxcbiAgICAvLyBjcmVhdGVBbnN3ZXIpLCB3ZSB3YW50IHRvIHJlbWVtYmVyIHRoZSBtLWxpbmUgYXQgd2hpY2ggd2UndmUgc2VlbiB0aGVcbiAgICAvLyAobG9jYWwpIFNTUkMuIFRoYXQncyBiZWNhdXNlIHdoZW4gdGhlIGFwcGxpY2F0aW9uIHdhbnRzIHRvIGRvIGNhbGwgdGhlXG4gICAgLy8gU0xEIG1ldGhvZCwgZm9yY2luZyB1cyB0byBkbyB0aGUgaW52ZXJzZSB0cmFuc2Zvcm1hdGlvbiAoZnJvbSBQbGFuIEIgdG9cbiAgICAvLyBVbmlmaWVkIFBsYW4pLCB3ZSBuZWVkIHRvIGtub3cgdG8gd2hpY2ggbS1saW5lIHRvIGFzc2lnbiB0aGUgKGxvY2FsKVxuICAgIC8vIFNTUkMuIFdlIGFsc28gbmVlZCB0byBrbm93IGFsbCB0aGUgb3RoZXIgbS1saW5lcyB0aGF0IHRoZSBvcmlnaW5hbFxuICAgIC8vIGFuc3dlciBoYWQgYW5kIGluY2x1ZGUgdGhlbSBpbiB0aGUgdHJhbnNmb3JtZWQgYW5zd2VyIGFzIHdlbGwuXG4gICAgLy9cbiAgICAvLyBBbm90aGVyIGV4YW1wbGUgaXMgaWYgdGhpcyBpcyBhIHJlbW90ZSBvZmZlciB0aGF0IHdlIGNvbnZlcnQgdG8gUGxhbiBCXG4gICAgLy8gcHJpb3IgdG8gZ2l2aW5nIGl0IHRvIHRoZSBhcHBsaWNhdGlvbiwgd2Ugd2FudCB0byByZW1lbWJlciB0aGUgbWlkIGF0XG4gICAgLy8gd2hpY2ggd2UndmUgc2VlbiB0aGUgKHJlbW90ZSkgU1NSQy5cbiAgICAvL1xuICAgIC8vIEluIHRoZSBpdGVyYXRpb24gdGhhdCBmb2xsb3dzLCB3ZSB1c2UgdGhlIGNhY2hlZCBVbmlmaWVkIFBsYW4gKGlmIGl0XG4gICAgLy8gZXhpc3RzKSB0byBhc3NpZ24gbWlkcyB0byBzc3Jjcy5cblxuICAgIHZhciB0eXBlO1xuICAgIGlmIChkZXNjLnR5cGUgPT09ICdhbnN3ZXInKSB7XG4gICAgICAgIHR5cGUgPSAnb2ZmZXInO1xuICAgIH0gZWxzZSBpZiAoZGVzYy50eXBlID09PSAnb2ZmZXInKSB7XG4gICAgICAgIHR5cGUgPSAnYW5zd2VyJztcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUeXBlICdcIiArIGRlc2MudHlwZSArIFwiJyBub3Qgc3VwcG9ydGVkLlwiKTtcbiAgICB9XG5cbiAgICB2YXIgY2FjaGVkO1xuICAgIGlmICh0eXBlb2YgdGhpcy5jYWNoZVt0eXBlXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY2FjaGVkID0gdHJhbnNmb3JtLnBhcnNlKHRoaXMuY2FjaGVbdHlwZV0pO1xuICAgIH1cblxuICAgIHZhciByZWN2b25seVNzcmNzID0ge1xuICAgICAgICBhdWRpbzoge30sXG4gICAgICAgIHZpZGVvOiB7fVxuICAgIH07XG5cbiAgICAvLyBBIGhlbHBlciBtYXAgdGhhdCBzZW5kcyBtaWRzIHRvIG0tbGluZSBvYmplY3RzLiBXZSB1c2UgaXQgbGF0ZXIgdG9cbiAgICAvLyByZWJ1aWxkIHRoZSBVbmlmaWVkIFBsYW4gc3R5bGUgc2Vzc2lvbi5tZWRpYSBhcnJheS5cbiAgICB2YXIgbWlkMnVsID0ge307XG4gICAgdmFyIGJJZHggPSAwO1xuICAgIHZhciB1SWR4ID0gMDtcblxuICAgIHZhciBzb3VyY2VzMnVsID0ge307XG5cbiAgICB2YXIgY2FuZGlkYXRlcztcbiAgICB2YXIgaWNlVWZyYWc7XG4gICAgdmFyIGljZVB3ZDtcbiAgICB2YXIgZmluZ2VycHJpbnQ7XG4gICAgdmFyIHBheWxvYWRzID0ge307XG4gICAgdmFyIHJ0Y3BGYiA9IHt9O1xuICAgIHZhciBydHAgPSB7fTtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbihiTGluZSkge1xuICAgICAgICBpZiAoKHR5cGVvZiBiTGluZS5ydGNwTXV4ICE9PSAnc3RyaW5nJyB8fFxuICAgICAgICAgICAgYkxpbmUucnRjcE11eCAhPT0gJ3J0Y3AtbXV4JykgJiZcbiAgICAgICAgICAgIGJMaW5lLmRpcmVjdGlvbiAhPT0gJ2luYWN0aXZlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGNvbnZlcnQgdG8gVW5pZmllZCBQbGFuIGJlY2F1c2UgbS1saW5lcyBcIiArXG4gICAgICAgICAgICAgICAgXCJ3aXRob3V0IHRoZSBydGNwLW11eCBhdHRyaWJ1dGUgd2VyZSBmb3VuZC5cIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYkxpbmUudHlwZSA9PT0gJ2FwcGxpY2F0aW9uJykge1xuICAgICAgICAgICAgbWlkMnVsW2JMaW5lLm1pZF0gPSBiTGluZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdpdGggcnRjcC1tdXggYW5kIGJ1bmRsZSBhbGwgdGhlIGNoYW5uZWxzIHNob3VsZCBoYXZlIHRoZSBzYW1lIElDRVxuICAgICAgICAvLyBzdHVmZi5cbiAgICAgICAgdmFyIHNvdXJjZXMgPSBiTGluZS5zb3VyY2VzO1xuICAgICAgICB2YXIgc3NyY0dyb3VwcyA9IGJMaW5lLnNzcmNHcm91cHM7XG4gICAgICAgIHZhciBwb3J0ID0gYkxpbmUucG9ydDtcblxuICAgICAgICAvKiBDaHJvbWUgYWRkcyBkaWZmZXJlbnQgY2FuZGlkYXRlcyBldmVuIHVzaW5nIGJ1bmRsZSwgc28gd2UgY29uY2F0IHRoZSBjYW5kaWRhdGVzIGxpc3QgKi9cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5jYW5kaWRhdGVzICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNhbmRpZGF0ZXMgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBjYW5kaWRhdGVzID0gY2FuZGlkYXRlcy5jb25jYXQoYkxpbmUuY2FuZGlkYXRlcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbmRpZGF0ZXMgPSBiTGluZS5jYW5kaWRhdGVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCh0eXBlb2YgaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpICYmICh0eXBlb2YgYkxpbmUuaWNlVWZyYWcgIT0gJ3VuZGVmaW5lZCcpICYmIChpY2VVZnJhZyAhPSBiTGluZS5pY2VVZnJhZykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgQlVORExFIHN1cHBvcnRlZCwgaWNlVWZyYWcgbXVzdCBiZSB0aGUgc2FtZSBmb3IgYWxsIG0tbGluZXMuXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TGFzdCBpY2VVZnJhZzogXCIgKyBpY2VVZnJhZyArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGljZVVmcmFnOiBcIiArIGJMaW5lLmljZVVmcmFnXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5pY2VVZnJhZyAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGljZVVmcmFnID0gYkxpbmUuaWNlVWZyYWc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHR5cGVvZiBpY2VQd2QgIT0gJ3VuZGVmaW5lZCcpICYmICh0eXBlb2YgYkxpbmUuaWNlUHdkICE9ICd1bmRlZmluZWQnKSAmJiAoaWNlUHdkICE9IGJMaW5lLmljZVB3ZCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgQlVORExFIHN1cHBvcnRlZCwgaWNlUHdkIG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgaWNlUHdkOiBcIiArIGljZVB3ZCArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXFx0TmV3IGljZVB3ZDogXCIgKyBiTGluZS5pY2VQd2RcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGJMaW5lLmljZVB3ZCAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGljZVB3ZCA9IGJMaW5lLmljZVB3ZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgodHlwZW9mIGZpbmdlcnByaW50ICE9ICd1bmRlZmluZWQnKSAmJiAodHlwZW9mIGJMaW5lLmZpbmdlcnByaW50ICE9ICd1bmRlZmluZWQnKSAmJlxuICAgICAgICAgICAgKGZpbmdlcnByaW50LnR5cGUgIT0gYkxpbmUuZmluZ2VycHJpbnQudHlwZSB8fCBmaW5nZXJwcmludC5oYXNoICE9IGJMaW5lLmZpbmdlcnByaW50Lmhhc2gpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJPbmx5IEJVTkRMRSBzdXBwb3J0ZWQsIGZpbmdlcnByaW50IG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCBtLWxpbmVzLlxcblwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlxcdExhc3QgZmluZ2VycHJpbnQ6IFwiICsgSlNPTi5zdHJpbmdpZnkoZmluZ2VycHJpbnQpICsgXCJcXG5cIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJcXHROZXcgZmluZ2VycHJpbnQ6IFwiICsgSlNPTi5zdHJpbmdpZnkoYkxpbmUuZmluZ2VycHJpbnQpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBiTGluZS5maW5nZXJwcmludCAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGZpbmdlcnByaW50ID0gYkxpbmUuZmluZ2VycHJpbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBwYXlsb2Fkc1tiTGluZS50eXBlXSA9IGJMaW5lLnBheWxvYWRzO1xuICAgICAgICBydGNwRmJbYkxpbmUudHlwZV0gPSBiTGluZS5ydGNwRmI7XG4gICAgICAgIHJ0cFtiTGluZS50eXBlXSA9IGJMaW5lLnJ0cDtcblxuICAgICAgICAvLyBpbnZlcnRlZCBzc3JjIGdyb3VwIG1hcFxuICAgICAgICB2YXIgc3NyYzJncm91cCA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICAgIHNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgLy8gWFhYIFRoaXMgbWlnaHQgYnJha2UgaWYgYW4gU1NSQyBpcyBpbiBtb3JlIHRoYW4gb25lIGdyb3VwXG4gICAgICAgICAgICAgICAgLy8gZm9yIHNvbWUgcmVhc29uLlxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyY0dyb3VwLnNzcmNzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmNHcm91cC5zc3JjcykpIHtcbiAgICAgICAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzLmZvckVhY2goZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyYzJncm91cFtzc3JjXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzc3JjMmdyb3VwW3NzcmNdID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNzcmMyZ3JvdXBbc3NyY10ucHVzaChzc3JjR3JvdXApO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHNzcmMgdG8gbS1saW5lIGluZGV4LlxuICAgICAgICB2YXIgc3NyYzJtbCA9IHt9O1xuXG4gICAgICAgIGlmICh0eXBlb2Ygc291cmNlcyA9PT0gJ29iamVjdCcpIHtcblxuICAgICAgICAgICAgLy8gV2UnbGwgdXNlIHRoZSBcImJMaW5lXCIgb2JqZWN0IGFzIGEgcHJvdG90eXBlIGZvciBlYWNoIG5ldyBcIm1MaW5lXCJcbiAgICAgICAgICAgIC8vIHRoYXQgd2UgY3JlYXRlLCBidXQgZmlyc3Qgd2UgbmVlZCB0byBjbGVhbiBpdCB1cCBhIGJpdC5cbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5zb3VyY2VzO1xuICAgICAgICAgICAgZGVsZXRlIGJMaW5lLnNzcmNHcm91cHM7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuY2FuZGlkYXRlcztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5pY2VVZnJhZztcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5pY2VQd2Q7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUuZmluZ2VycHJpbnQ7XG4gICAgICAgICAgICBkZWxldGUgYkxpbmUucG9ydDtcbiAgICAgICAgICAgIGRlbGV0ZSBiTGluZS5taWQ7XG5cbiAgICAgICAgICAgIC8vIEV4cGxvZGUgdGhlIFBsYW4gQiBjaGFubmVsIHNvdXJjZXMgd2l0aCBvbmUgbS1saW5lIHBlciBzb3VyY2UuXG4gICAgICAgICAgICBPYmplY3Qua2V5cyhzb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uKHNzcmMpIHtcblxuICAgICAgICAgICAgICAgIC8vIFRoZSAodW5pZmllZCkgbS1saW5lIGZvciB0aGlzIFNTUkMuIFdlIGVpdGhlciBjcmVhdGUgaXQgZnJvbVxuICAgICAgICAgICAgICAgIC8vIHNjcmF0Y2ggb3IsIGlmIGl0J3MgYSBncm91cGVkIFNTUkMsIHdlIHJlLXVzZSBhIHJlbGF0ZWRcbiAgICAgICAgICAgICAgICAvLyBtbGluZS4gSW4gb3RoZXIgd29yZHMsIGlmIHRoZSBzb3VyY2UgaXMgZ3JvdXBlZCB3aXRoIGFub3RoZXJcbiAgICAgICAgICAgICAgICAvLyBzb3VyY2UsIHB1dCB0aGUgdHdvIHRvZ2V0aGVyIGluIHRoZSBzYW1lIG0tbGluZS5cbiAgICAgICAgICAgICAgICB2YXIgdUxpbmU7XG5cbiAgICAgICAgICAgICAgICAvLyBXZSBhc3N1bWUgaGVyZSB0aGF0IHdlIGFyZSB0aGUgYW5zd2VyZXIgaW4gdGhlIE8vQSwgc28gYW55XG4gICAgICAgICAgICAgICAgLy8gb2ZmZXJzIHdoaWNoIHdlIHRyYW5zbGF0ZSBjb21lIGZyb20gdGhlIHJlbW90ZSBzaWRlLCB3aGlsZVxuICAgICAgICAgICAgICAgIC8vIGFuc3dlcnMgYXJlIGxvY2FsLiBTbyB0aGUgY2hlY2sgYmVsb3cgaXMgdG8gbWFrZSB0aGF0IHdlXG4gICAgICAgICAgICAgICAgLy8gaGFuZGxlIHJlY2VpdmUtb25seSBTU1JDcyBpbiBhIHNwZWNpYWwgd2F5IG9ubHkgaWYgdGhleSBjb21lXG4gICAgICAgICAgICAgICAgLy8gZnJvbSB0aGUgcmVtb3RlIHNpZGUuXG4gICAgICAgICAgICAgICAgaWYgKGRlc2MudHlwZT09PSdvZmZlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2Ugd2FudCB0byBkZXRlY3QgU1NSQ3Mgd2hpY2ggYXJlIHVzZWQgYnkgYSByZW1vdGUgcGVlclxuICAgICAgICAgICAgICAgICAgICAvLyBpbiBhbiBtLWxpbmUgd2l0aCBkaXJlY3Rpb249cmVjdm9ubHkgKGkuZS4gdGhleSBhcmVcbiAgICAgICAgICAgICAgICAgICAgLy8gYmVpbmcgdXNlZCBmb3IgUlRDUCBvbmx5KS5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBpbmZvcm1hdGlvbiB3b3VsZCBoYXZlIGdvdHRlbiBsb3N0IGlmIHRoZSByZW1vdGVcbiAgICAgICAgICAgICAgICAgICAgLy8gcGVlciB1c2VkIFVuaWZpZWQgUGxhbiBhbmQgdGhlaXIgbG9jYWwgZGVzY3JpcHRpb24gd2FzXG4gICAgICAgICAgICAgICAgICAgIC8vIHRyYW5zbGF0ZWQgdG8gUGxhbiBCLiBTbyB3ZSB1c2UgdGhlIGxhY2sgb2YgYW4gTVNJRFxuICAgICAgICAgICAgICAgICAgICAvLyBhdHRyaWJ1dGUgdG8gZGVkdWNlIGEgXCJyZWNlaXZlIG9ubHlcIiBTU1JDLlxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNvdXJjZXNbc3NyY10ubXNpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjdm9ubHlTc3Jjc1tiTGluZS50eXBlXVtzc3JjXSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWNlaXZlLW9ubHkgU1NSQ3MgbXVzdCBub3QgY3JlYXRlIG5ldyBtLWxpbmVzLiBXZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2lsbCBhc3NpZ24gdGhlbSB0byBhbiBleGlzdGluZyBtLWxpbmUgbGF0ZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNzcmMyZ3JvdXBbc3NyY10gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoc3NyYzJncm91cFtzc3JjXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3NyYzJncm91cFtzc3JjXS5zb21lKGZ1bmN0aW9uIChzc3JjR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNzcmNHcm91cC5zc3JjcyAqaXMqIGFuIEFycmF5LCBubyBuZWVkIHRvIGNoZWNrXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhZ2FpbiBoZXJlLlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNzcmNHcm91cC5zc3Jjcy5zb21lKGZ1bmN0aW9uIChyZWxhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjMm1sW3JlbGF0ZWRdID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZSA9IHNzcmMybWxbcmVsYXRlZF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVMaW5lID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbS1saW5lIGFscmVhZHkgZXhpc3RzLiBKdXN0IGFkZCB0aGUgc291cmNlLlxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID0gc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIFwiYkxpbmVcIiBhcyBhIHByb3RvdHlwZSBmb3IgdGhlIFwidUxpbmVcIi5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUgPSBPYmplY3QuY3JlYXRlKGJMaW5lKTtcbiAgICAgICAgICAgICAgICAgICAgc3NyYzJtbFtzc3JjXSA9IHVMaW5lO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc291cmNlc1tzc3JjXS5tc2lkICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXNzaWduIHRoZSBtc2lkIG9mIHRoZSBzb3VyY2UgdG8gdGhlIG0tbGluZS4gTm90ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhhdCBpdCBpcyBub3QgZ3VhcmFudGVlZCB0aGF0IHRoZSBzb3VyY2Ugd2lsbCBoYXZlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtc2lkLiBJbiBwYXJ0aWN1bGFyIFwicmVjdm9ubHlcIiBzb3VyY2VzIGRvbid0IGhhdmUgYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1zaWQuIE5vdGUgdGhhdCBcInJlY3Zvbmx5XCIgaXMgYSB0ZXJtIG9ubHkgZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZm9yIG0tbGluZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5tc2lkID0gc291cmNlc1tzc3JjXS5tc2lkO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIGFzc2lnbiBvbmUgU1NSQyBwZXIgbWVkaWEgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID0gc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc3NyY0dyb3VwcyA9IHNzcmMyZ3JvdXBbc3NyY107XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHRoZSBjYWNoZWQgVW5pZmllZCBQbGFuIFNEUCAoaWYgaXQgZXhpc3RzKSB0byBhc3NpZ25cbiAgICAgICAgICAgICAgICAgICAgLy8gU1NSQ3MgdG8gbWlkcy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjYWNoZWQgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlb2YgY2FjaGVkLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShjYWNoZWQubWVkaWEpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZC5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtLnNvdXJjZXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKG0uc291cmNlcykuZm9yRWFjaChmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMgPT09IHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5taWQgPSBtLm1pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVMaW5lLm1pZCA9PT0gJ3VuZGVmaW5lZCcpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyBhbiBTU1JDIHRoYXQgd2Ugc2VlIGZvciB0aGUgZmlyc3QgdGltZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGl0IGEgbmV3IG1pZC4gVGhpcyBpcyB0eXBpY2FsbHkgdGhlIGNhc2Ugd2hlblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBtZXRob2QgaXMgY2FsbGVkIHRvIHRyYW5zZm9ybSBhIHJlbW90ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGVzY3JpcHRpb24gZm9yIHRoZSBmaXJzdCB0aW1lIG9yIHdoZW4gdGhlcmUgaXMgYVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbmV3IFNTUkMgaW4gdGhlIHJlbW90ZSBkZXNjcmlwdGlvbiBiZWNhdXNlIGEgbmV3XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwZWVyIGhhcyBqb2luZWQgdGhlIGNvbmZlcmVuY2UuIExvY2FsIFNTUkNzIHNob3VsZFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaGF2ZSBhbHJlYWR5IGJlZW4gYWRkZWQgdG8gdGhlIG1hcCBpbiB0aGUgdG9QbGFuQlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWV0aG9kLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2UgRkYgZ2VuZXJhdGVzIGFuc3dlcnMgaW4gVW5pZmllZCBQbGFuIHN0eWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UgTVVTVCBhbHJlYWR5IGhhdmUgYSBjYWNoZWQgYW5zd2VyIHdpdGggYWxsIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbG9jYWwgU1NSQ3MgbWFwcGVkIHRvIHNvbWUgbS1saW5lL21pZC5cblxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubWlkID0gW2JMaW5lLnR5cGUsICctJywgc3NyY10uam9pbignJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBJbmNsdWRlIHRoZSBjYW5kaWRhdGVzIGluIHRoZSAxc3QgbWVkaWEgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVVmcmFnID0gaWNlVWZyYWc7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUucG9ydCA9IHBvcnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgbWlkMnVsW3VMaW5lLm1pZF0gPSB1TGluZTtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlczJ1bFt1SWR4XSA9IHVMaW5lLnNvdXJjZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWNoZS5tbFUyQk1hcFt1SWR4XSA9IGJJZHg7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNhY2hlLm1sQjJVTWFwW2JJZHhdID0gdUlkeDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB1SWR4Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHVMaW5lID0gYkxpbmU7XG5cbiAgICAgICAgICB1TGluZS5jYW5kaWRhdGVzID0gY2FuZGlkYXRlcztcbiAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICB1TGluZS5maW5nZXJwcmludCA9IGZpbmdlcnByaW50O1xuICAgICAgICAgIHVMaW5lLnBvcnQgPSBwb3J0O1xuXG4gICAgICAgICAgbWlkMnVsW3VMaW5lLm1pZF0gPSB1TGluZTtcblxuICAgICAgICAgIHNlbGYuY2FjaGUubWxVMkJNYXBbdUlkeF0gPSBiSWR4O1xuICAgICAgICAgIGlmICh0eXBlb2Ygc2VsZi5jYWNoZS5tbEIyVU1hcFtiSWR4XSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHNlbGYuY2FjaGUubWxCMlVNYXBbYklkeF0gPSB1SWR4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGJJZHgrKztcbiAgICB9KTtcblxuICAgIC8vIFJlYnVpbGQgdGhlIG1lZGlhIGFycmF5IGluIHRoZSByaWdodCBvcmRlciBhbmQgYWRkIHRoZSBtaXNzaW5nIG1MaW5lc1xuICAgIC8vIChtaXNzaW5nIGZyb20gdGhlIFBsYW4gQiBTRFApLlxuICAgIHNlc3Npb24ubWVkaWEgPSBbXTtcbiAgICBtaWRzID0gW107IC8vIHJldXNlXG5cbiAgICBpZiAoZGVzYy50eXBlID09PSAnYW5zd2VyJykge1xuXG4gICAgICAgIC8vIFRoZSBtZWRpYSBsaW5lcyBpbiB0aGUgYW5zd2VyIG11c3QgbWF0Y2ggdGhlIG1lZGlhIGxpbmVzIGluIHRoZVxuICAgICAgICAvLyBvZmZlci4gVGhlIG9yZGVyIGlzIGltcG9ydGFudCB0b28uIEhlcmUgd2UgYXNzdW1lIHRoYXQgRmlyZWZveCBpc1xuICAgICAgICAvLyB0aGUgYW5zd2VyZXIsIHNvIHdlIG1lcmVseSBoYXZlIHRvIHVzZSB0aGUgcmVjb25zdHJ1Y3RlZCAodW5pZmllZClcbiAgICAgICAgLy8gYW5zd2VyIHRvIHVwZGF0ZSB0aGUgY2FjaGVkICh1bmlmaWVkKSBhbnN3ZXIgYWNjb3JkaW5nbHkuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEluIHRoZSBnZW5lcmFsIGNhc2UsIG9uZSB3b3VsZCBoYXZlIHRvIHVzZSB0aGUgY2FjaGVkICh1bmlmaWVkKVxuICAgICAgICAvLyBvZmZlciB0byBmaW5kIHRoZSBtLWxpbmVzIHRoYXQgYXJlIG1pc3NpbmcgZnJvbSB0aGUgcmVjb25zdHJ1Y3RlZFxuICAgICAgICAvLyBhbnN3ZXIsIHBvdGVudGlhbGx5IGdyYWJiaW5nIHRoZW0gZnJvbSB0aGUgY2FjaGVkICh1bmlmaWVkKSBhbnN3ZXIuXG4gICAgICAgIC8vIE9uZSBoYXMgdG8gYmUgY2FyZWZ1bCB3aXRoIHRoaXMgYXBwcm9hY2ggYmVjYXVzZSBpbmFjdGl2ZSBtLWxpbmVzIGRvXG4gICAgICAgIC8vIG5vdCBhbHdheXMgaGF2ZSBhbiBtaWQsIG1ha2luZyBpdCB0cmlja3kgKGltcG9zc2libGU/KSB0byBmaW5kIHdoZXJlXG4gICAgICAgIC8vIGV4YWN0bHkgYW5kIHdoaWNoIG0tbGluZXMgYXJlIG1pc3NpbmcgZnJvbSB0aGUgcmVjb25zdHJ1Y3RlZCBhbnN3ZXIuXG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjYWNoZWQubWVkaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB1TGluZSA9IGNhY2hlZC5tZWRpYVtpXTtcblxuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICBkZWxldGUgdUxpbmUuc291cmNlcztcbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zc3JjR3JvdXBzO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHNvdXJjZXMydWxbaV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAncmVjdm9ubHknO1xuICAgICAgICAgICAgICBlbHNlIGlmICh1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kb25seScpXG4gICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnaW5hY3RpdmUnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKCF1TGluZS5kaXJlY3Rpb25cbiAgICAgICAgICAgICAgICAgIHx8IHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JylcbiAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICAgIGVsc2UgaWYgKHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3JlY3Zvbmx5JylcbiAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdzZW5kb25seSc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHVMaW5lLnNvdXJjZXMgPSBzb3VyY2VzMnVsW2ldO1xuICAgICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgICB1TGluZS5pY2VVZnJhZyA9IGljZVVmcmFnO1xuICAgICAgICAgICAgdUxpbmUuaWNlUHdkID0gaWNlUHdkO1xuICAgICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcblxuICAgICAgICAgICAgdUxpbmUucnRwID0gcnRwW3VMaW5lLnR5cGVdO1xuICAgICAgICAgICAgdUxpbmUucGF5bG9hZHMgPSBwYXlsb2Fkc1t1TGluZS50eXBlXTtcbiAgICAgICAgICAgIHVMaW5lLnJ0Y3BGYiA9IHJ0Y3BGYlt1TGluZS50eXBlXTtcblxuICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZS5taWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgLy8gaW5hY3RpdmUgbGluZXMgZG9uJ3QvbWF5IG5vdCBoYXZlIGFuIG1pZC5cbiAgICAgICAgICAgICAgICBtaWRzLnB1c2godUxpbmUubWlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgLy8gU0RQIG9mZmVyL2Fuc3dlciAoYW5kIHRoZSBKU0VQIHNwZWMpIGZvcmJpZHMgcmVtb3ZpbmcgYW4gbS1zZWN0aW9uXG4gICAgICAgIC8vIHVuZGVyIGFueSBjaXJjdW1zdGFuY2VzLiBJZiB3ZSBhcmUgbm8gbG9uZ2VyIGludGVyZXN0ZWQgaW4gc2VuZGluZyBhXG4gICAgICAgIC8vIHRyYWNrLCB3ZSBqdXN0IHJlbW92ZSB0aGUgbXNpZCBhbmQgc3NyYyBhdHRyaWJ1dGVzIGFuZCBzZXQgaXQgdG9cbiAgICAgICAgLy8gZWl0aGVyIGE9cmVjdm9ubHkgKGFzIHRoZSByZW9mZmVyZXIsIHdlIG11c3QgdXNlIHJlY3Zvbmx5IGlmIHRoZVxuICAgICAgICAvLyBvdGhlciBzaWRlIHdhcyBwcmV2aW91c2x5IHNlbmRpbmcgb24gdGhlIG0tc2VjdGlvbiwgYnV0IHdlIGNhbiBhbHNvXG4gICAgICAgIC8vIGxlYXZlIHRoZSBwb3NzaWJpbGl0eSBvcGVuIGlmIGl0IHdhc24ndCBwcmV2aW91c2x5IGluIHVzZSksIG9yXG4gICAgICAgIC8vIGE9aW5hY3RpdmUuXG5cbiAgICAgICAgaWYgKHR5cGVvZiBjYWNoZWQgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICB0eXBlb2YgY2FjaGVkLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgQXJyYXkuaXNBcnJheShjYWNoZWQubWVkaWEpKSB7XG4gICAgICAgICAgICBjYWNoZWQubWVkaWEuZm9yRWFjaChmdW5jdGlvbih1TGluZSkge1xuICAgICAgICAgICAgICAgIG1pZHMucHVzaCh1TGluZS5taWQpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWlkMnVsW3VMaW5lLm1pZF0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaChtaWQydWxbdUxpbmUubWlkXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHVMaW5lLm1zaWQ7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zb3VyY2VzO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdUxpbmUuc3NyY0dyb3VwcztcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXVMaW5lLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAnc2VuZG9ubHknO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdyZWN2b25seScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdpbmFjdGl2ZSc7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhZGRTZXR1cEF0dHIgKHVMaW5lKTtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBhbGwgdGhlIHJlbWFpbmluZyAobmV3KSBtLWxpbmVzIG9mIHRoZSB0cmFuc2Zvcm1lZCBTRFAuXG4gICAgICAgIE9iamVjdC5rZXlzKG1pZDJ1bCkuZm9yRWFjaChmdW5jdGlvbihtaWQpIHtcbiAgICAgICAgICAgIGlmIChtaWRzLmluZGV4T2YobWlkKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtaWRzLnB1c2gobWlkKTtcbiAgICAgICAgICAgICAgICBpZiAobWlkMnVsW21pZF0uZGlyZWN0aW9uID09PSAncmVjdm9ubHknKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYSByZW1vdGUgcmVjdm9ubHkgY2hhbm5lbC4gQWRkIGl0cyBTU1JDIHRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyBhcHByb3ByaWF0ZSBzZW5kcmVjdiBvciBzZW5kb25seSBjaGFubmVsLlxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPKGdwKSB3aGF0IGlmIHdlIGRvbid0IGhhdmUgc2VuZHJlY3Yvc2VuZG9ubHlcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hhbm5lbD9cblxuICAgICAgICAgICAgICAgICAgICB2YXIgZG9uZSA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWEuc29tZShmdW5jdGlvbiAodUxpbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLnR5cGUgPT09IG1pZDJ1bFttaWRdLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtaWQydWxbbWlkXSBzaG91bGRuJ3QgaGF2ZSBhbnkgc3NyYy1ncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhtaWQydWxbbWlkXS5zb3VyY2VzKS5mb3JFYWNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pZDJ1bFttaWRdLnNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb25lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2gobWlkMnVsW21pZF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKG1pZDJ1bFttaWRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEFmdGVyIHdlIGhhdmUgY29uc3RydWN0ZWQgdGhlIFBsYW4gVW5pZmllZCBtLWxpbmVzIHdlIGNhbiBmaWd1cmUgb3V0XG4gICAgLy8gd2hlcmUgKGluIHdoaWNoIG0tbGluZSkgdG8gcGxhY2UgdGhlICdyZWN2b25seSBTU1JDcycuXG4gICAgLy8gTm90ZTogd2UgYXNzdW1lIGhlcmUgdGhhdCB3ZSBhcmUgdGhlIGFuc3dlcmVyIGluIHRoZSBPL0EsIHNvIGFueSBvZmZlcnNcbiAgICAvLyB3aGljaCB3ZSB0cmFuc2xhdGUgY29tZSBmcm9tIHRoZSByZW1vdGUgc2lkZSwgd2hpbGUgYW5zd2VycyBhcmUgbG9jYWxcbiAgICAvLyAoYW5kIHNvIG91ciBsYXN0IGxvY2FsIGRlc2NyaXB0aW9uIGlzIGNhY2hlZCBhcyBhbiAnYW5zd2VyJykuXG4gICAgW1wiYXVkaW9cIiwgXCJ2aWRlb1wiXS5mb3JFYWNoKGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIGlmICghc2Vzc2lvbiB8fCAhc2Vzc2lvbi5tZWRpYSB8fCAhQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB2YXIgaWR4ID0gbnVsbDtcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGlkeCA9IHNlbGYuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyKHR5cGUpO1xuICAgICAgICAgICAgaWYgKGlkeCA9PT0gbnVsbCl7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyB0aGUgZmlyc3Qgb2ZmZXIgd2UgcmVjZWl2ZSwgd2UgZG9uJ3QgaGF2ZSBhXG4gICAgICAgICAgICAgICAgLy8gY2FjaGVkIGFuc3dlci4gQXNzdW1lIHRoYXQgd2Ugd2lsbCBiZSBzZW5kaW5nIG1lZGlhIHVzaW5nXG4gICAgICAgICAgICAgICAgLy8gdGhlIGZpcnN0IG0tbGluZSBmb3IgZWFjaCBtZWRpYSB0eXBlLlxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZXNzaW9uLm1lZGlhW2ldLnR5cGUgPT09IHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkeCA9IGk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpZHggJiYgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPiBpZHgpIHtcbiAgICAgICAgICAgIHZhciBtTGluZSA9IHNlc3Npb24ubWVkaWFbaWR4XTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmZvckVhY2goZnVuY3Rpb24oc3NyYykge1xuICAgICAgICAgICAgICAgIGlmIChtTGluZS5zb3VyY2VzICYmIG1MaW5lLnNvdXJjZXNbc3NyY10pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiUmVwbGFjaW5nIGFuIGV4aXN0aW5nIFNTUkMuXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIW1MaW5lLnNvdXJjZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgbUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIG1MaW5lLnNvdXJjZXNbc3NyY10gPSByZWN2b25seVNzcmNzW3R5cGVdW3NzcmNdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAvLyBXZSByZWdlbmVyYXRlIHRoZSBCVU5ETEUgZ3JvdXAgKHNpbmNlIHdlIHJlZ2VuZXJhdGVkIHRoZSBtaWRzKVxuICAgICAgc2Vzc2lvbi5ncm91cHMuc29tZShmdW5jdGlvbihncm91cCkge1xuXHQgIGlmIChncm91cC50eXBlID09PSAnQlVORExFJykge1xuXHQgICAgICBncm91cC5taWRzID0gbWlkcy5qb2luKCcgJyk7XG5cdCAgICAgIHJldHVybiB0cnVlO1xuXHQgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIG1zaWQgc2VtYW50aWNcbiAgICBzZXNzaW9uLm1zaWRTZW1hbnRpYyA9IHtcbiAgICAgICAgc2VtYW50aWM6ICdXTVMnLFxuICAgICAgICB0b2tlbjogJyonXG4gICAgfTtcblxuICAgIHZhciByZXNTdHIgPSB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbik7XG5cbiAgICAvLyBDYWNoZSB0aGUgdHJhbnNmb3JtZWQgU0RQIChVbmlmaWVkIFBsYW4pIGZvciBsYXRlciByZS11c2UgaW4gdGhpc1xuICAgIC8vIGZ1bmN0aW9uLlxuICAgIHRoaXMuY2FjaGVbZGVzYy50eXBlXSA9IHJlc1N0cjtcblxuICAgIHJldHVybiBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgICAgdHlwZTogZGVzYy50eXBlLFxuICAgICAgICBzZHA6IHJlc1N0clxuICAgIH0pO1xuXG4gICAgLy8jZW5kcmVnaW9uXG59O1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgdHJhbnNmb3JtID0gcmVxdWlyZSgnc2RwLXRyYW5zZm9ybScpO1xuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24oc2Vzc2lvbiwgb3B0cykge1xuXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLm1lZGlhICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSkge1xuXG4gICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtTGluZSkge1xuICAgICAgLy8gZXhwYW5kIHNvdXJjZXMgdG8gc3NyY3NcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc291cmNlcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgT2JqZWN0LmtleXMobUxpbmUuc291cmNlcykubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbUxpbmUuc3NyY3MgPSBbXTtcbiAgICAgICAgICBPYmplY3Qua2V5cyhtTGluZS5zb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gbUxpbmUuc291cmNlc1tzc3JjXTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHNvdXJjZSkuZm9yRWFjaChmdW5jdGlvbiAoYXR0cmlidXRlKSB7XG4gICAgICAgICAgICAgIG1MaW5lLnNzcmNzLnB1c2goe1xuICAgICAgICAgICAgICAgIGlkOiBzc3JjLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogYXR0cmlidXRlLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBzb3VyY2VbYXR0cmlidXRlXVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGRlbGV0ZSBtTGluZS5zb3VyY2VzO1xuICAgICAgICB9XG5cbiAgICAgIC8vIGpvaW4gc3NyY3MgaW4gc3NyYyBncm91cHNcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmNHcm91cC5zc3JjcykpIHtcbiAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzID0gc3NyY0dyb3VwLnNzcmNzLmpvaW4oJyAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gam9pbiBncm91cCBtaWRzXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLmdyb3VwcykpIHtcblxuICAgIHNlc3Npb24uZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgIGlmICh0eXBlb2YgZy5taWRzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KGcubWlkcykpIHtcbiAgICAgICAgZy5taWRzID0gZy5taWRzLmpvaW4oJyAnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB0cmFuc2Zvcm0ud3JpdGUoc2Vzc2lvbiwgb3B0cyk7XG59O1xuXG5leHBvcnRzLnBhcnNlID0gZnVuY3Rpb24oc2RwKSB7XG4gIHZhciBzZXNzaW9uID0gdHJhbnNmb3JtLnBhcnNlKHNkcCk7XG5cbiAgaWYgKHR5cGVvZiBzZXNzaW9uICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Ygc2Vzc2lvbi5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpIHtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICAgIC8vIGdyb3VwIHNvdXJjZXMgYXR0cmlidXRlcyBieSBzc3JjXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNzICE9PSAndW5kZWZpbmVkJyAmJiBBcnJheS5pc0FycmF5KG1MaW5lLnNzcmNzKSkge1xuICAgICAgICBtTGluZS5zb3VyY2VzID0ge307XG4gICAgICAgIG1MaW5lLnNzcmNzLmZvckVhY2goZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICBpZiAoIW1MaW5lLnNvdXJjZXNbc3NyYy5pZF0pXG4gICAgICAgICAgbUxpbmUuc291cmNlc1tzc3JjLmlkXSA9IHt9O1xuICAgICAgICBtTGluZS5zb3VyY2VzW3NzcmMuaWRdW3NzcmMuYXR0cmlidXRlXSA9IHNzcmMudmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRlbGV0ZSBtTGluZS5zc3JjcztcbiAgICAgIH1cblxuICAgICAgLy8gc3BsaXQgc3NyY3MgaW4gc3NyYyBncm91cHNcbiAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cC5zc3JjcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgc3NyY0dyb3VwLnNzcmNzID0gc3NyY0dyb3VwLnNzcmNzLnNwbGl0KCcgJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuICAvLyBzcGxpdCBncm91cCBtaWRzXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIHR5cGVvZiBzZXNzaW9uLmdyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLmdyb3VwcykpIHtcblxuICAgIHNlc3Npb24uZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgIGlmICh0eXBlb2YgZy5taWRzID09PSAnc3RyaW5nJykge1xuICAgICAgICBnLm1pZHMgPSBnLm1pZHMuc3BsaXQoJyAnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzZXNzaW9uO1xufTtcblxuIiwiLyohXG4gKiBVQVBhcnNlci5qcyB2MC43LjE4XG4gKiBMaWdodHdlaWdodCBKYXZhU2NyaXB0LWJhc2VkIFVzZXItQWdlbnQgc3RyaW5nIHBhcnNlclxuICogaHR0cHM6Ly9naXRodWIuY29tL2ZhaXNhbG1hbi91YS1wYXJzZXItanNcbiAqXG4gKiBDb3B5cmlnaHQgwqkgMjAxMi0yMDE2IEZhaXNhbCBTYWxtYW4gPGZ5emxtYW5AZ21haWwuY29tPlxuICogRHVhbCBsaWNlbnNlZCB1bmRlciBHUEx2MiBvciBNSVRcbiAqL1xuXG4oZnVuY3Rpb24gKHdpbmRvdywgdW5kZWZpbmVkKSB7XG5cbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvLy8vLy8vLy8vLy8vL1xuICAgIC8vIENvbnN0YW50c1xuICAgIC8vLy8vLy8vLy8vLy9cblxuXG4gICAgdmFyIExJQlZFUlNJT04gID0gJzAuNy4xOCcsXG4gICAgICAgIEVNUFRZICAgICAgID0gJycsXG4gICAgICAgIFVOS05PV04gICAgID0gJz8nLFxuICAgICAgICBGVU5DX1RZUEUgICA9ICdmdW5jdGlvbicsXG4gICAgICAgIFVOREVGX1RZUEUgID0gJ3VuZGVmaW5lZCcsXG4gICAgICAgIE9CSl9UWVBFICAgID0gJ29iamVjdCcsXG4gICAgICAgIFNUUl9UWVBFICAgID0gJ3N0cmluZycsXG4gICAgICAgIE1BSk9SICAgICAgID0gJ21ham9yJywgLy8gZGVwcmVjYXRlZFxuICAgICAgICBNT0RFTCAgICAgICA9ICdtb2RlbCcsXG4gICAgICAgIE5BTUUgICAgICAgID0gJ25hbWUnLFxuICAgICAgICBUWVBFICAgICAgICA9ICd0eXBlJyxcbiAgICAgICAgVkVORE9SICAgICAgPSAndmVuZG9yJyxcbiAgICAgICAgVkVSU0lPTiAgICAgPSAndmVyc2lvbicsXG4gICAgICAgIEFSQ0hJVEVDVFVSRT0gJ2FyY2hpdGVjdHVyZScsXG4gICAgICAgIENPTlNPTEUgICAgID0gJ2NvbnNvbGUnLFxuICAgICAgICBNT0JJTEUgICAgICA9ICdtb2JpbGUnLFxuICAgICAgICBUQUJMRVQgICAgICA9ICd0YWJsZXQnLFxuICAgICAgICBTTUFSVFRWICAgICA9ICdzbWFydHR2JyxcbiAgICAgICAgV0VBUkFCTEUgICAgPSAnd2VhcmFibGUnLFxuICAgICAgICBFTUJFRERFRCAgICA9ICdlbWJlZGRlZCc7XG5cblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gSGVscGVyXG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgdXRpbCA9IHtcbiAgICAgICAgZXh0ZW5kIDogZnVuY3Rpb24gKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIHtcbiAgICAgICAgICAgIHZhciBtYXJnZWRSZWdleGVzID0ge307XG4gICAgICAgICAgICBmb3IgKHZhciBpIGluIHJlZ2V4ZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uc1tpXSAmJiBleHRlbnNpb25zW2ldLmxlbmd0aCAlIDIgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbWFyZ2VkUmVnZXhlc1tpXSA9IGV4dGVuc2lvbnNbaV0uY29uY2F0KHJlZ2V4ZXNbaV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcmdlZFJlZ2V4ZXNbaV0gPSByZWdleGVzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtYXJnZWRSZWdleGVzO1xuICAgICAgICB9LFxuICAgICAgICBoYXMgOiBmdW5jdGlvbiAoc3RyMSwgc3RyMikge1xuICAgICAgICAgIGlmICh0eXBlb2Ygc3RyMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHN0cjIudG9Mb3dlckNhc2UoKS5pbmRleE9mKHN0cjEudG9Mb3dlckNhc2UoKSkgIT09IC0xO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsb3dlcml6ZSA6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgIHJldHVybiBzdHIudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfSxcbiAgICAgICAgbWFqb3IgOiBmdW5jdGlvbiAodmVyc2lvbikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZih2ZXJzaW9uKSA9PT0gU1RSX1RZUEUgPyB2ZXJzaW9uLnJlcGxhY2UoL1teXFxkXFwuXS9nLCcnKS5zcGxpdChcIi5cIilbMF0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIHRyaW0gOiBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eW1xcc1xcdUZFRkZcXHhBMF0rfFtcXHNcXHVGRUZGXFx4QTBdKyQvZywgJycpO1xuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gTWFwIGhlbHBlclxuICAgIC8vLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciBtYXBwZXIgPSB7XG5cbiAgICAgICAgcmd4IDogZnVuY3Rpb24gKHVhLCBhcnJheXMpIHtcblxuICAgICAgICAgICAgLy92YXIgcmVzdWx0ID0ge30sXG4gICAgICAgICAgICB2YXIgaSA9IDAsIGosIGssIHAsIHEsIG1hdGNoZXMsIG1hdGNoOy8vLCBhcmdzID0gYXJndW1lbnRzO1xuXG4gICAgICAgICAgICAvKi8vIGNvbnN0cnVjdCBvYmplY3QgYmFyZWJvbmVzXG4gICAgICAgICAgICBmb3IgKHAgPSAwOyBwIDwgYXJnc1sxXS5sZW5ndGg7IHArKykge1xuICAgICAgICAgICAgICAgIHEgPSBhcmdzWzFdW3BdO1xuICAgICAgICAgICAgICAgIHJlc3VsdFt0eXBlb2YgcSA9PT0gT0JKX1RZUEUgPyBxWzBdIDogcV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9Ki9cblxuICAgICAgICAgICAgLy8gbG9vcCB0aHJvdWdoIGFsbCByZWdleGVzIG1hcHNcbiAgICAgICAgICAgIHdoaWxlIChpIDwgYXJyYXlzLmxlbmd0aCAmJiAhbWF0Y2hlcykge1xuXG4gICAgICAgICAgICAgICAgdmFyIHJlZ2V4ID0gYXJyYXlzW2ldLCAgICAgICAvLyBldmVuIHNlcXVlbmNlICgwLDIsNCwuLilcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSBhcnJheXNbaSArIDFdOyAgIC8vIG9kZCBzZXF1ZW5jZSAoMSwzLDUsLi4pXG4gICAgICAgICAgICAgICAgaiA9IGsgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gdHJ5IG1hdGNoaW5nIHVhc3RyaW5nIHdpdGggcmVnZXhlc1xuICAgICAgICAgICAgICAgIHdoaWxlIChqIDwgcmVnZXgubGVuZ3RoICYmICFtYXRjaGVzKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IHJlZ2V4W2orK10uZXhlYyh1YSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbWF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChwID0gMDsgcCA8IHByb3BzLmxlbmd0aDsgcCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBtYXRjaGVzWysra107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcSA9IHByb3BzW3BdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIGdpdmVuIHByb3BlcnR5IGlzIGFjdHVhbGx5IGFycmF5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBxID09PSBPQkpfVFlQRSAmJiBxLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHEubGVuZ3RoID09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcVsxXSA9PSBGVU5DX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhc3NpZ24gbW9kaWZpZWQgbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXS5jYWxsKHRoaXMsIG1hdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXNzaWduIGdpdmVuIHZhbHVlLCBpZ25vcmUgcmVnZXggbWF0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW3FbMF1dID0gcVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayB3aGV0aGVyIGZ1bmN0aW9uIG9yIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHFbMV0gPT09IEZVTkNfVFlQRSAmJiAhKHFbMV0uZXhlYyAmJiBxWzFdLnRlc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FsbCBmdW5jdGlvbiAodXN1YWxseSBzdHJpbmcgbWFwcGVyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbcVswXV0gPSBtYXRjaCA/IHFbMV0uY2FsbCh0aGlzLCBtYXRjaCwgcVsyXSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNhbml0aXplIG1hdGNoIHVzaW5nIGdpdmVuIHJlZ2V4XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gbWF0Y2gucmVwbGFjZShxWzFdLCBxWzJdKSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChxLmxlbmd0aCA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txWzBdXSA9IG1hdGNoID8gcVszXS5jYWxsKHRoaXMsIG1hdGNoLnJlcGxhY2UocVsxXSwgcVsyXSkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1txXSA9IG1hdGNoID8gbWF0Y2ggOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMpO1xuICAgICAgICAgICAgLy9yZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICBzdHIgOiBmdW5jdGlvbiAoc3RyLCBtYXApIHtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBtYXApIHtcbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBhcnJheVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWFwW2ldID09PSBPQkpfVFlQRSAmJiBtYXBbaV0ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1hcFtpXS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHV0aWwuaGFzKG1hcFtpXVtqXSwgc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoaSA9PT0gVU5LTk9XTikgPyB1bmRlZmluZWQgOiBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh1dGlsLmhhcyhtYXBbaV0sIHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChpID09PSBVTktOT1dOKSA/IHVuZGVmaW5lZCA6IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgICAgfVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIFN0cmluZyBtYXBcbiAgICAvLy8vLy8vLy8vLy8vL1xuXG5cbiAgICB2YXIgbWFwcyA9IHtcblxuICAgICAgICBicm93c2VyIDoge1xuICAgICAgICAgICAgb2xkc2FmYXJpIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICcxLjAnICAgOiAnLzgnLFxuICAgICAgICAgICAgICAgICAgICAnMS4yJyAgIDogJy8xJyxcbiAgICAgICAgICAgICAgICAgICAgJzEuMycgICA6ICcvMycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAnICAgOiAnLzQxMicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMicgOiAnLzQxNicsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuMycgOiAnLzQxNycsXG4gICAgICAgICAgICAgICAgICAgICcyLjAuNCcgOiAnLzQxOScsXG4gICAgICAgICAgICAgICAgICAgICc/JyAgICAgOiAnLydcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGV2aWNlIDoge1xuICAgICAgICAgICAgYW1hem9uIDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRmlyZSBQaG9uZScgOiBbJ1NEJywgJ0tGJ11cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3ByaW50IDoge1xuICAgICAgICAgICAgICAgIG1vZGVsIDoge1xuICAgICAgICAgICAgICAgICAgICAnRXZvIFNoaWZ0IDRHJyA6ICc3MzczS1QnXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB2ZW5kb3IgOiB7XG4gICAgICAgICAgICAgICAgICAgICdIVEMnICAgICAgIDogJ0FQQScsXG4gICAgICAgICAgICAgICAgICAgICdTcHJpbnQnICAgIDogJ1NwcmludCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgb3MgOiB7XG4gICAgICAgICAgICB3aW5kb3dzIDoge1xuICAgICAgICAgICAgICAgIHZlcnNpb24gOiB7XG4gICAgICAgICAgICAgICAgICAgICdNRScgICAgICAgIDogJzQuOTAnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgMy4xMScgICA6ICdOVDMuNTEnLFxuICAgICAgICAgICAgICAgICAgICAnTlQgNC4wJyAgICA6ICdOVDQuMCcsXG4gICAgICAgICAgICAgICAgICAgICcyMDAwJyAgICAgIDogJ05UIDUuMCcsXG4gICAgICAgICAgICAgICAgICAgICdYUCcgICAgICAgIDogWydOVCA1LjEnLCAnTlQgNS4yJ10sXG4gICAgICAgICAgICAgICAgICAgICdWaXN0YScgICAgIDogJ05UIDYuMCcsXG4gICAgICAgICAgICAgICAgICAgICc3JyAgICAgICAgIDogJ05UIDYuMScsXG4gICAgICAgICAgICAgICAgICAgICc4JyAgICAgICAgIDogJ05UIDYuMicsXG4gICAgICAgICAgICAgICAgICAgICc4LjEnICAgICAgIDogJ05UIDYuMycsXG4gICAgICAgICAgICAgICAgICAgICcxMCcgICAgICAgIDogWydOVCA2LjQnLCAnTlQgMTAuMCddLFxuICAgICAgICAgICAgICAgICAgICAnUlQnICAgICAgICA6ICdBUk0nXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8vLy8vLy8vLy8vLy9cbiAgICAvLyBSZWdleCBtYXBcbiAgICAvLy8vLy8vLy8vLy8vXG5cblxuICAgIHZhciByZWdleGVzID0ge1xuXG4gICAgICAgIGJyb3dzZXIgOiBbW1xuXG4gICAgICAgICAgICAvLyBQcmVzdG8gYmFzZWRcbiAgICAgICAgICAgIC8ob3BlcmFcXHNtaW5pKVxcLyhbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1pbmlcbiAgICAgICAgICAgIC8ob3BlcmFcXHNbbW9iaWxldGFiXSspLit2ZXJzaW9uXFwvKFtcXHdcXC4tXSspL2ksICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIE1vYmkvVGFibGV0XG4gICAgICAgICAgICAvKG9wZXJhKS4rdmVyc2lvblxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhID4gOS44MFxuICAgICAgICAgICAgLyhvcGVyYSlbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgPCA5LjgwXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhvcGlvcylbXFwvXFxzXSsoW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlcmEgbWluaSBvbiBpcGhvbmUgPj0gOC4wXG4gICAgICAgICAgICBdLCBbW05BTUUsICdPcGVyYSBNaW5pJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9cXHMob3ByKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZXJhIFdlYmtpdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gTWl4ZWRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvKGx1bmFzY2FwZXxtYXh0aG9ufG5ldGZyb250fGphc21pbmV8YmxhemVyKVtcXC9cXHNdPyhbXFx3XFwuXSopL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEx1bmFzY2FwZS9NYXh0aG9uL05ldGZyb250L0phc21pbmUvQmxhemVyXG5cbiAgICAgICAgICAgIC8vIFRyaWRlbnQgYmFzZWRcbiAgICAgICAgICAgIC8oYXZhbnRcXHN8aWVtb2JpbGV8c2xpbXxiYWlkdSkoPzpicm93c2VyKT9bXFwvXFxzXT8oW1xcd1xcLl0qKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdmFudC9JRU1vYmlsZS9TbGltQnJvd3Nlci9CYWlkdVxuICAgICAgICAgICAgLyg/Om1zfFxcKCkoaWUpXFxzKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW50ZXJuZXQgRXhwbG9yZXJcblxuICAgICAgICAgICAgLy8gV2Via2l0L0tIVE1MIGJhc2VkXG4gICAgICAgICAgICAvKHJla29ucSlcXC8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJla29ucVxuICAgICAgICAgICAgLyhjaHJvbWl1bXxmbG9ja3xyb2NrbWVsdHxtaWRvcml8ZXBpcGhhbnl8c2lsa3xza3lmaXJlfG92aWJyb3dzZXJ8Ym9sdHxpcm9ufHZpdmFsZGl8aXJpZGl1bXxwaGFudG9tanN8Ym93c2VyfHF1YXJrKVxcLyhbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9taXVtL0Zsb2NrL1JvY2tNZWx0L01pZG9yaS9FcGlwaGFueS9TaWxrL1NreWZpcmUvQm9sdC9Jcm9uL0lyaWRpdW0vUGhhbnRvbUpTL0Jvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8odHJpZGVudCkuK3J2WzpcXHNdKFtcXHdcXC5dKykuK2xpa2VcXHNnZWNrby9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElFMTFcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0lFJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oZWRnZXxlZGdpb3N8ZWRnZWEpXFwvKChcXGQrKT9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBFZGdlXG4gICAgICAgICAgICBdLCBbW05BTUUsICdFZGdlJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oeWFicm93c2VyKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWWFuZGV4XG4gICAgICAgICAgICBdLCBbW05BTUUsICdZYW5kZXgnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhwdWZmaW4pXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQdWZmaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ1B1ZmZpbiddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKCg/OltcXHNcXC9dKXVjP1xccz9icm93c2VyfCg/Omp1Yy4rKXVjd2ViKVtcXC9cXHNdPyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVUNCcm93c2VyXG4gICAgICAgICAgICBdLCBbW05BTUUsICdVQ0Jyb3dzZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb21vZG9fZHJhZ29uKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb21vZG8gRHJhZ29uXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obWljcm9tZXNzZW5nZXIpXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2VDaGF0XG4gICAgICAgICAgICBdLCBbW05BTUUsICdXZUNoYXQnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhxcWJyb3dzZXJsaXRlKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUUJyb3dzZXJMaXRlXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhRUSlcXC8oW1xcZFxcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRUSwgYWthIFNob3VRXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL20/KHFxYnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUVFCcm93c2VyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhCSURVQnJvd3NlcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmFpZHUgQnJvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oMjM0NUV4cGxvcmVyKVtcXC9cXHNdPyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDIzNDUgQnJvd3NlclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oTWV0YVNyKVtcXC9cXHNdPyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvdUdvdUJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAvKExCQlJPV1NFUikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGllQmFvIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtOQU1FXSwgW1xuXG4gICAgICAgICAgICAveGlhb21pXFwvbWl1aWJyb3dzZXJcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNSVVJIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ01JVUkgQnJvd3NlciddXSwgW1xuXG4gICAgICAgICAgICAvO2ZiYXZcXC8oW1xcd1xcLl0rKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZhY2Vib29rIEFwcCBmb3IgaU9TICYgQW5kcm9pZFxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnRmFjZWJvb2snXV0sIFtcblxuICAgICAgICAgICAgL2hlYWRsZXNzY2hyb21lKD86XFwvKFtcXHdcXC5dKyl8XFxzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lIEhlYWRsZXNzXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdDaHJvbWUgSGVhZGxlc3MnXV0sIFtcblxuICAgICAgICAgICAgL1xcc3d2XFwpLisoY2hyb21lKVxcLyhbXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENocm9tZSBXZWJWaWV3XG4gICAgICAgICAgICBdLCBbW05BTUUsIC8oLispLywgJyQxIFdlYlZpZXcnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLygoPzpvY3VsdXN8c2Ftc3VuZylicm93c2VyKVxcLyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgLyguKyg/Omd8dXMpKSguKykvLCAnJDEgJDInXSwgVkVSU0lPTl0sIFsgICAgICAgICAgICAgICAgLy8gT2N1bHVzIC8gU2Ftc3VuZyBCcm93c2VyXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLit2ZXJzaW9uXFwvKFtcXHdcXC5dKylcXHMrKD86bW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpKi9pICAgICAgICAvLyBBbmRyb2lkIEJyb3dzZXJcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0FuZHJvaWQgQnJvd3NlciddXSwgW1xuXG4gICAgICAgICAgICAvKGNocm9tZXxvbW5pd2VifGFyb3JhfFt0aXplbm9rYV17NX1cXHM/YnJvd3NlcilcXC92PyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21lL09tbmlXZWIvQXJvcmEvVGl6ZW4vTm9raWFcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGRvbGZpbilcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvbHBoaW5cbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0RvbHBoaW4nXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLygoPzphbmRyb2lkLispY3Jtb3xjcmlvcylcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDaHJvbWUgZm9yIEFuZHJvaWQvaU9TXG4gICAgICAgICAgICBdLCBbW05BTUUsICdDaHJvbWUnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhjb2FzdClcXC8oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPcGVyYSBDb2FzdFxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnT3BlcmEgQ29hc3QnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL2Z4aW9zXFwvKFtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IGZvciBpT1NcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBbTkFNRSwgJ0ZpcmVmb3gnXV0sIFtcblxuICAgICAgICAgICAgL3ZlcnNpb25cXC8oW1xcd1xcLl0rKS4rP21vYmlsZVxcL1xcdytcXHMoc2FmYXJpKS9pICAgICAgICAgICAgICAgICAgICAgICAvLyBNb2JpbGUgU2FmYXJpXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdNb2JpbGUgU2FmYXJpJ11dLCBbXG5cbiAgICAgICAgICAgIC92ZXJzaW9uXFwvKFtcXHdcXC5dKykuKz8obW9iaWxlXFxzP3NhZmFyaXxzYWZhcmkpL2kgICAgICAgICAgICAgICAgICAgIC8vIFNhZmFyaSAmIFNhZmFyaSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXSwgW1xuXG4gICAgICAgICAgICAvd2Via2l0Lis/KGdzYSlcXC8oW1xcd1xcLl0rKS4rPyhtb2JpbGVcXHM/c2FmYXJpfHNhZmFyaSkoXFwvW1xcd1xcLl0rKS9pICAvLyBHb29nbGUgU2VhcmNoIEFwcGxpYW5jZSBvbiBpT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0dTQSddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvd2Via2l0Lis/KG1vYmlsZVxccz9zYWZhcml8c2FmYXJpKShcXC9bXFx3XFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAvLyBTYWZhcmkgPCAzLjBcbiAgICAgICAgICAgIF0sIFtOQU1FLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5icm93c2VyLm9sZHNhZmFyaS52ZXJzaW9uXV0sIFtcblxuICAgICAgICAgICAgLyhrb25xdWVyb3IpXFwvKFtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLb25xdWVyb3JcbiAgICAgICAgICAgIC8od2Via2l0fGtodG1sKVxcLyhbXFx3XFwuXSspL2lcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBHZWNrbyBiYXNlZFxuICAgICAgICAgICAgLyhuYXZpZ2F0b3J8bmV0c2NhcGUpXFwvKFtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOZXRzY2FwZVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnTmV0c2NhcGUnXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oc3dpZnRmb3gpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3dpZnRmb3hcbiAgICAgICAgICAgIC8oaWNlZHJhZ29ufGljZXdlYXNlbHxjYW1pbm98Y2hpbWVyYXxmZW5uZWN8bWFlbW9cXHNicm93c2VyfG1pbmltb3xjb25rZXJvcilbXFwvXFxzXT8oW1xcd1xcLlxcK10rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJY2VEcmFnb24vSWNld2Vhc2VsL0NhbWluby9DaGltZXJhL0Zlbm5lYy9NYWVtby9NaW5pbW8vQ29ua2Vyb3JcbiAgICAgICAgICAgIC8oZmlyZWZveHxzZWFtb25rZXl8ay1tZWxlb258aWNlY2F0fGljZWFwZXxmaXJlYmlyZHxwaG9lbml4fHBhbGVtb29ufGJhc2lsaXNrfHdhdGVyZm94KVxcLyhbXFx3XFwuLV0rKSQvaSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94L1NlYU1vbmtleS9LLU1lbGVvbi9JY2VDYXQvSWNlQXBlL0ZpcmViaXJkL1Bob2VuaXhcbiAgICAgICAgICAgIC8obW96aWxsYSlcXC8oW1xcd1xcLl0rKS4rcnZcXDouK2dlY2tvXFwvXFxkKy9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW96aWxsYVxuXG4gICAgICAgICAgICAvLyBPdGhlclxuICAgICAgICAgICAgLyhwb2xhcmlzfGx5bnh8ZGlsbG98aWNhYnxkb3Jpc3xhbWF5YXx3M218bmV0c3VyZnxzbGVpcG5pcilbXFwvXFxzXT8oW1xcd1xcLl0rKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQb2xhcmlzL0x5bngvRGlsbG8vaUNhYi9Eb3Jpcy9BbWF5YS93M20vTmV0U3VyZi9TbGVpcG5pclxuICAgICAgICAgICAgLyhsaW5rcylcXHNcXCgoW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTGlua3NcbiAgICAgICAgICAgIC8oZ29icm93c2VyKVxcLz8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29Ccm93c2VyXG4gICAgICAgICAgICAvKGljZVxccz9icm93c2VyKVxcL3Y/KFtcXHdcXC5fXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQ0UgQnJvd3NlclxuICAgICAgICAgICAgLyhtb3NhaWMpW1xcL1xcc10oW1xcd1xcLl0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9zYWljXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cblxuICAgICAgICAgICAgLyogLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAgICAgICAvLyBNZWRpYSBwbGF5ZXJzIEJFR0lOXG4gICAgICAgICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICAgICAgICAgICAgLCBbXG5cbiAgICAgICAgICAgIC8oYXBwbGUoPzpjb3JlbWVkaWF8KSlcXC8oKFxcZCspW1xcd1xcLl9dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQXBwbGUgQ29yZU1lZGlhXG4gICAgICAgICAgICAvKGNvcmVtZWRpYSkgdigoXFxkKylbXFx3XFwuX10rKS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhhcXVhbHVuZ3xseXNzbmF8YnNwbGF5ZXIpXFwvKChcXGQrKT9bXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgLy8gQXF1YWx1bmcvTHlzc25hL0JTUGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhhcmVzfG9zc3Byb3h5KVxccygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXJlcy9PU1NQcm94eVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oYXVkYWNpb3VzfGF1ZGltdXNpY3N0cmVhbXxhbWFyb2t8YmFzc3xjb3JlfGRhbHZpa3xnbm9tZW1wbGF5ZXJ8bXVzaWMgb24gY29uc29sZXxuc3BsYXllcnxwc3AtaW50ZXJuZXRyYWRpb3BsYXllcnx2aWRlb3MpXFwvKChcXGQrKVtcXHdcXC4tXSspL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF1ZGFjaW91cy9BdWRpTXVzaWNTdHJlYW0vQW1hcm9rL0JBU1MvT3BlbkNPUkUvRGFsdmlrL0dub21lTXBsYXllci9Nb0NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTlNQbGF5ZXIvUFNQLUludGVybmV0UmFkaW9QbGF5ZXIvVmlkZW9zXG4gICAgICAgICAgICAvKGNsZW1lbnRpbmV8bXVzaWMgcGxheWVyIGRhZW1vbilcXHMoKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAvLyBDbGVtZW50aW5lL01QRFxuICAgICAgICAgICAgLyhsZyBwbGF5ZXJ8bmV4cGxheWVyKVxccygoXFxkKylbXFxkXFwuXSspL2ksXG4gICAgICAgICAgICAvcGxheWVyXFwvKG5leHBsYXllcnxsZyBwbGF5ZXIpXFxzKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgLy8gTmV4UGxheWVyL0xHIFBsYXllclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKG5leHBsYXllcilcXHMoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOZXhwbGF5ZXJcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKGZscnApXFwvKChcXGQrKVtcXHdcXC4tXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGbGlwIFBsYXllclxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnRmxpcCBQbGF5ZXInXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhmc3RyZWFtfG5hdGl2ZWhvc3R8cXVlcnlzZWVrc3BpZGVyfGlhLWFyY2hpdmVyfGZhY2Vib29rZXh0ZXJuYWxoaXQpL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRlN0cmVhbS9OYXRpdmVIb3N0L1F1ZXJ5U2Vla1NwaWRlci9JQSBBcmNoaXZlci9mYWNlYm9va2V4dGVybmFsaGl0XG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcblxuICAgICAgICAgICAgLyhnc3RyZWFtZXIpIHNvdXBodHRwc3JjICg/OlxcKFteXFwpXStcXCkpezAsMX0gbGlic291cFxcLygoXFxkKylbXFx3XFwuLV0rKS9pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdzdHJlYW1lclxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjIHN0cmVhbWluZyBwbGF5ZXIpXFxzW1xcd19dK1xcc1xcL1xccygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAvLyBIVEMgU3RyZWFtaW5nIFBsYXllclxuICAgICAgICAgICAgLyhqYXZhfHB5dGhvbi11cmxsaWJ8cHl0aG9uLXJlcXVlc3RzfHdnZXR8bGliY3VybClcXC8oKFxcZCspW1xcd1xcLi1fXSspL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEphdmEvdXJsbGliL3JlcXVlc3RzL3dnZXQvY1VSTFxuICAgICAgICAgICAgLyhsYXZmKSgoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMYXZmIChGRk1QRUcpXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhodGNfb25lX3MpXFwvKChcXGQrKVtcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFRDIE9uZSBTXG4gICAgICAgICAgICBdLCBbW05BTUUsIC9fL2csICcgJ10sIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikoPzpcXHN8XFwvKSg/Oig/OnNoZXJweWEtKXswLDF9c3ZuKSg/Oi18XFxzKShyXFxkKyg/Oi1cXGQrW1xcd1xcLi1dKyl7MCwxfSkvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyIFNWTlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8obXBsYXllcikoPzpcXHN8XFwvfFt1bmtvdy1dKykoKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhtcGxheWVyKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNUGxheWVyIChubyBvdGhlciBpbmZvKVxuICAgICAgICAgICAgLyh5b3VybXV6ZSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBZb3VyTXV6ZVxuICAgICAgICAgICAgLyhtZWRpYSBwbGF5ZXIgY2xhc3NpY3xuZXJvIHNob3d0aW1lKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNZWRpYSBQbGF5ZXIgQ2xhc3NpYy9OZXJvIFNob3dUaW1lXG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcblxuICAgICAgICAgICAgLyhuZXJvICg/OmhvbWV8c2NvdXQpKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmVybyBIb21lL05lcm8gU2NvdXRcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvKG5va2lhXFxkKylcXC8oKFxcZCspW1xcd1xcLi1dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvXFxzKHNvbmdiaXJkKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29uZ2JpcmQvUGhpbGlwcy1Tb25nYmlyZFxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8od2luYW1wKTMgdmVyc2lvbiAoKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luYW1wXG4gICAgICAgICAgICAvKHdpbmFtcClcXHMoKFxcZCspW1xcd1xcLi1dKykvaSxcbiAgICAgICAgICAgIC8od2luYW1wKW1wZWdcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8ob2Ntcy1ib3R8dGFwaW5yYWRpb3x0dW5laW4gcmFkaW98dW5rbm93bnx3aW5hbXB8aW5saWdodCByYWRpbykvaSAgLy8gT0NNUy1ib3QvdGFwIGluIHJhZGlvL3R1bmVpbi91bmtub3duL3dpbmFtcCAobm8gb3RoZXIgaW5mbylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5saWdodCByYWRpb1xuICAgICAgICAgICAgXSwgW05BTUVdLCBbXG5cbiAgICAgICAgICAgIC8ocXVpY2t0aW1lfHJtYXxyYWRpb2FwcHxyYWRpb2NsaWVudGFwcGxpY2F0aW9ufHNvdW5kdGFwfHRvdGVtfHN0YWdlZnJpZ2h0fHN0cmVhbWl1bSlcXC8oKFxcZCspW1xcd1xcLi1dKykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBRdWlja1RpbWUvUmVhbE1lZGlhL1JhZGlvQXBwL1JhZGlvQ2xpZW50QXBwbGljYXRpb24vXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvdW5kVGFwL1RvdGVtL1N0YWdlZnJpZ2h0L1N0cmVhbWl1bVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oc21wKSgoXFxkKylbXFxkXFwuXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU01QXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyh2bGMpIG1lZGlhIHBsYXllciAtIHZlcnNpb24gKChcXGQrKVtcXHdcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAvLyBWTEMgVmlkZW9sYW5cbiAgICAgICAgICAgIC8odmxjKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLFxuICAgICAgICAgICAgLyh4Ym1jfGd2ZnN8eGluZXx4bW1zfGlyYXBwKVxcLygoXFxkKylbXFx3XFwuLV0rKS9pLCAgICAgICAgICAgICAgICAgICAgLy8gWEJNQy9ndmZzL1hpbmUvWE1NUy9pcmFwcFxuICAgICAgICAgICAgLyhmb29iYXIyMDAwKVxcLygoXFxkKylbXFxkXFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRm9vYmFyMjAwMFxuICAgICAgICAgICAgLyhpdHVuZXMpXFwvKChcXGQrKVtcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVR1bmVzXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyh3bXBsYXllcilcXC8oKFxcZCspW1xcd1xcLi1dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBNZWRpYSBQbGF5ZXJcbiAgICAgICAgICAgIC8od2luZG93cy1tZWRpYS1wbGF5ZXIpXFwvKChcXGQrKVtcXHdcXC4tXSspL2lcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgLy0vZywgJyAnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgL3dpbmRvd3NcXC8oKFxcZCspW1xcd1xcLi1dKykgdXBucFxcL1tcXGRcXC5dKyBkbG5hZG9jXFwvW1xcZFxcLl0rIChob21lIG1lZGlhIHNlcnZlcikvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaW5kb3dzIE1lZGlhIFNlcnZlclxuICAgICAgICAgICAgXSwgW1ZFUlNJT04sIFtOQU1FLCAnV2luZG93cyddXSwgW1xuXG4gICAgICAgICAgICAvKGNvbVxcLnJpc2V1cHJhZGlvYWxhcm0pXFwvKChcXGQrKVtcXGRcXC5dKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmlzZVVQIFJhZGlvIEFsYXJtXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLyhyYWQuaW8pXFxzKChcXGQrKVtcXGRcXC5dKykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmFkLmlvXG4gICAgICAgICAgICAvKHJhZGlvLig/OmRlfGF0fGZyKSlcXHMoKFxcZCspW1xcZFxcLl0rKS9pXG4gICAgICAgICAgICBdLCBbW05BTUUsICdyYWQuaW8nXSwgVkVSU0lPTl1cblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gTWVkaWEgcGxheWVycyBFTkRcbiAgICAgICAgICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGNwdSA6IFtbXG5cbiAgICAgICAgICAgIC8oPzooYW1kfHgoPzooPzo4Nnw2NClbXy1dKT98d293fHdpbik2NClbO1xcKV0vaSAgICAgICAgICAgICAgICAgICAgIC8vIEFNRDY0XG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2FtZDY0J11dLCBbXG5cbiAgICAgICAgICAgIC8oaWEzMig/PTspKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSUEzMiAocXVpY2t0aW1lKVxuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIHV0aWwubG93ZXJpemVdXSwgW1xuXG4gICAgICAgICAgICAvKCg/OmlbMzQ2XXx4KTg2KVs7XFwpXS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQTMyXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2lhMzInXV0sIFtcblxuICAgICAgICAgICAgLy8gUG9ja2V0UEMgbWlzdGFrZW5seSBpZGVudGlmaWVkIGFzIFBvd2VyUENcbiAgICAgICAgICAgIC93aW5kb3dzXFxzKGNlfG1vYmlsZSk7XFxzcHBjOy9pXG4gICAgICAgICAgICBdLCBbW0FSQ0hJVEVDVFVSRSwgJ2FybSddXSwgW1xuXG4gICAgICAgICAgICAvKCg/OnBwY3xwb3dlcnBjKSg/OjY0KT8pKD86XFxzbWFjfDt8XFwpKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUG93ZXJQQ1xuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIC9vd2VyLywgJycsIHV0aWwubG93ZXJpemVdXSwgW1xuXG4gICAgICAgICAgICAvKHN1bjRcXHcpWztcXCldL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU1BBUkNcbiAgICAgICAgICAgIF0sIFtbQVJDSElURUNUVVJFLCAnc3BhcmMnXV0sIFtcblxuICAgICAgICAgICAgLygoPzphdnIzMnxpYTY0KD89OykpfDY4ayg/PVxcKSl8YXJtKD86NjR8KD89dlxcZCs7KSl8KD89YXRtZWxcXHMpYXZyfCg/OmlyaXh8bWlwc3xzcGFyYykoPzo2NCk/KD89Oyl8cGEtcmlzYykvaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJQTY0LCA2OEssIEFSTS82NCwgQVZSLzMyLCBJUklYLzY0LCBNSVBTLzY0LCBTUEFSQy82NCwgUEEtUklTQ1xuICAgICAgICAgICAgXSwgW1tBUkNISVRFQ1RVUkUsIHV0aWwubG93ZXJpemVdXVxuICAgICAgICBdLFxuXG4gICAgICAgIGRldmljZSA6IFtbXG5cbiAgICAgICAgICAgIC9cXCgoaXBhZHxwbGF5Ym9vayk7W1xcd1xcc1xcKTstXSsocmltfGFwcGxlKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQYWQvUGxheUJvb2tcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgVkVORE9SLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FwcGxlY29yZW1lZGlhXFwvW1xcd1xcLl0rIFxcKChpcGFkKS8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaVBhZFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQXBwbGUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oYXBwbGVcXHN7MCwxfXR2KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFwcGxlIFRWXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnQXBwbGUgVFYnXSwgW1ZFTkRPUiwgJ0FwcGxlJ11dLCBbXG5cbiAgICAgICAgICAgIC8oYXJjaG9zKVxccyhnYW1lcGFkMj8pL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFyY2hvc1xuICAgICAgICAgICAgLyhocCkuKyh0b3VjaHBhZCkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIUCBUb3VjaFBhZFxuICAgICAgICAgICAgLyhocCkuKyh0YWJsZXQpL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIUCBUYWJsZXRcbiAgICAgICAgICAgIC8oa2luZGxlKVxcLyhbXFx3XFwuXSspL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS2luZGxlXG4gICAgICAgICAgICAvXFxzKG5vb2spW1xcd1xcc10rYnVpbGRcXC8oXFx3KykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9va1xuICAgICAgICAgICAgLyhkZWxsKVxccyhzdHJlYVtrcHJcXHNcXGRdKltcXGRrb10pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVsbCBTdHJlYWtcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhrZltBLXpdKylcXHNidWlsZFxcLy4rc2lsa1xcLy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBLaW5kbGUgRmlyZSBIRFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhzZHxrZilbMDM0OWhpam9yc3R1d10rXFxzYnVpbGRcXC8uK3NpbGtcXC8vaSAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlIFBob25lXG4gICAgICAgICAgICBdLCBbW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5hbWF6b24ubW9kZWxdLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFwoKGlwW2hvbmVkfFxcc1xcdypdKyk7LisoYXBwbGUpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQb2QvaVBob25lXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFZFTkRPUiwgW1RZUEUsIE1PQklMRV1dLCBbXG4gICAgICAgICAgICAvXFwoKGlwW2hvbmVkfFxcc1xcdypdKyk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlQb2QvaVBob25lXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBcHBsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhibGFja2JlcnJ5KVtcXHMtXT8oXFx3KykvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnlcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeXxiZW5xfHBhbG0oPz1cXC0pfHNvbnllcmljc3NvbnxhY2VyfGFzdXN8ZGVsbHxtZWl6dXxtb3Rvcm9sYXxwb2x5dHJvbilbXFxzXy1dPyhbXFx3LV0qKS9pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCZW5RL1BhbG0vU29ueS1Fcmljc3Nvbi9BY2VyL0FzdXMvRGVsbC9NZWl6dS9Nb3Rvcm9sYS9Qb2x5dHJvblxuICAgICAgICAgICAgLyhocClcXHMoW1xcd1xcc10rXFx3KS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSFAgaVBBUVxuICAgICAgICAgICAgLyhhc3VzKS0/KFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXN1c1xuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL1xcKGJiMTA7XFxzKFxcdyspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBCbGFja0JlcnJ5IDEwXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdCbGFja0JlcnJ5J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBc3VzIFRhYmxldHNcbiAgICAgICAgICAgIC9hbmRyb2lkLisodHJhbnNmb1twcmltZVxcc117NCwxMH1cXHNcXHcrfGVlZXBjfHNsaWRlclxcc1xcdyt8bmV4dXMgN3xwYWRmb25lKS9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBc3VzJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKHNvbnkpXFxzKHRhYmxldFxcc1twc10pXFxzYnVpbGRcXC8vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueVxuICAgICAgICAgICAgLyhzb255KT8oPzpzZ3AuKylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NvbnknXSwgW01PREVMLCAnWHBlcmlhIFRhYmxldCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcbiAgICAgICAgICAgIC9hbmRyb2lkLitcXHMoW2MtZ11cXGR7NH18c29bLWxdXFx3KylcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvXFxzKG91eWEpXFxzL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3V5YVxuICAgICAgICAgICAgLyhuaW50ZW5kbylcXHMoW3dpZHMzdV0rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG9cbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKHNoaWVsZClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOdmlkaWFcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ052aWRpYSddLCBbVFlQRSwgQ09OU09MRV1dLCBbXG5cbiAgICAgICAgICAgIC8ocGxheXN0YXRpb25cXHNbMzRwb3J0YWJsZXZpXSspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYXlzdGF0aW9uXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTb255J10sIFtUWVBFLCBDT05TT0xFXV0sIFtcblxuICAgICAgICAgICAgLyhzcHJpbnRcXHMoXFx3KykpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNwcmludCBQaG9uZXNcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQudmVuZG9yXSwgW01PREVMLCBtYXBwZXIuc3RyLCBtYXBzLmRldmljZS5zcHJpbnQubW9kZWxdLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhsZW5vdm8pXFxzPyhTKD86NTAwMHw2MDAwKSsoPzpbLV1bXFx3K10pKS9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92byB0YWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC8oaHRjKVs7X1xccy1dKyhbXFx3XFxzXSsoPz1cXCkpfFxcdyspKi9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIVENcbiAgICAgICAgICAgIC8oenRlKS0oXFx3KikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURVxuICAgICAgICAgICAgLyhhbGNhdGVsfGdlZWtzcGhvbmV8bGVub3ZvfG5leGlhbnxwYW5hc29uaWN8KD89O1xccylzb255KVtfXFxzLV0/KFtcXHctXSopL2lcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxjYXRlbC9HZWVrc1Bob25lL0xlbm92by9OZXhpYW4vUGFuYXNvbmljL1NvbnlcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIFtNT0RFTCwgL18vZywgJyAnXSwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8obmV4dXNcXHM5KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhUQyBOZXh1cyA5XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdIVEMnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9kXFwvaHVhd2VpKFtcXHdcXHMtXSspWztcXCldL2ksXG4gICAgICAgICAgICAvKG5leHVzXFxzNnApL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdWF3ZWlcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0h1YXdlaSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtaWNyb3NvZnQpO1xccyhsdW1pYVtcXHNcXHddKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaWNyb3NvZnQgTHVtaWFcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL1tcXHNcXCg7XSh4Ym94KD86XFxzb25lKT8pW1xcc1xcKTtdL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1pY3Jvc29mdCBYYm94XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNaWNyb3NvZnQnXSwgW1RZUEUsIENPTlNPTEVdXSwgW1xuICAgICAgICAgICAgLyhraW5cXC5bb25ldHddezN9KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWljcm9zb2Z0IEtpblxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgL1xcLi9nLCAnICddLCBbVkVORE9SLCAnTWljcm9zb2Z0J10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1vdG9yb2xhXG4gICAgICAgICAgICAvXFxzKG1pbGVzdG9uZXxkcm9pZCg/OlsyLTR4XXxcXHMoPzpiaW9uaWN8eDJ8cHJvfHJhenIpKT86PyhcXHM0Zyk/KVtcXHdcXHNdK2J1aWxkXFwvL2ksXG4gICAgICAgICAgICAvbW90W1xccy1dPyhcXHcqKS9pLFxuICAgICAgICAgICAgLyhYVFxcZHszLDR9KSBidWlsZFxcLy9pLFxuICAgICAgICAgICAgLyhuZXh1c1xcczYpL2lcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01vdG9yb2xhJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuK1xccyhtejYwXFxkfHhvb21bXFxzMl17MCwyfSlcXHNidWlsZFxcLy9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNb3Rvcm9sYSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2hiYnR2XFwvXFxkK1xcLlxcZCtcXC5cXGQrXFxzK1xcKFtcXHdcXHNdKjtcXHMqKFxcd1teO10qKTsoW147XSopL2kgICAgICAgICAgICAvLyBIYmJUViBkZXZpY2VzXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgdXRpbC50cmltXSwgW01PREVMLCB1dGlsLnRyaW1dLCBbVFlQRSwgU01BUlRUVl1dLCBbXG5cbiAgICAgICAgICAgIC9oYmJ0di4rbWFwbGU7KFxcZCspL2lcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsIC9eLywgJ1NtYXJ0VFYnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFNNQVJUVFZdXSwgW1xuXG4gICAgICAgICAgICAvXFwoZHR2W1xcKTtdLisoYXF1b3MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2hhcnBcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1NoYXJwJ10sIFtUWVBFLCBTTUFSVFRWXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKygoc2NoLWlbODldMFxcZHxzaHctbTM4MHN8Z3QtcFxcZHs0fXxndC1uXFxkK3xzZ2gtdDhbNTZdOXxuZXh1cyAxMCkpL2ksXG4gICAgICAgICAgICAvKChTTS1UXFx3KykpL2lcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnU2Ftc3VuZyddLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZ1xuICAgICAgICAgICAgL3NtYXJ0LXR2Lisoc2Ftc3VuZykvaVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgW1RZUEUsIFNNQVJUVFZdLCBNT0RFTF0sIFtcbiAgICAgICAgICAgIC8oKHNbY2dwXWgtXFx3K3xndC1cXHcrfGdhbGF4eVxcc25leHVzfHNtLVxcd1tcXHdcXGRdKykpL2ksXG4gICAgICAgICAgICAvKHNhbVtzdW5nXSopW1xccy1dKihcXHcrLT9bXFx3LV0qKS9pLFxuICAgICAgICAgICAgL3NlYy0oKHNnaFxcdyspKS9pXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvc2llLShcXHcqKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTaWVtZW5zXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTaWVtZW5zJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKG1hZW1vfG5va2lhKS4qKG45MDB8bHVtaWFcXHNcXGQrKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm9raWFcbiAgICAgICAgICAgIC8obm9raWEpW1xcc18tXT8oW1xcdy1dKikvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdOb2tpYSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkXFxzM1xcLltcXHNcXHc7LV17MTB9KGFcXGR7M30pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBY2VyXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdBY2VyJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKFt2bF1rXFwtP1xcZHszfSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTEcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvYW5kcm9pZFxcczNcXC5bXFxzXFx3Oy1dezEwfShsZz8pLShbMDZjdjldezMsNH0pL2kgICAgICAgICAgICAgICAgICAgICAvLyBMRyBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtbVkVORE9SLCAnTEcnXSwgTU9ERUwsIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhsZykgbmV0Y2FzdFxcLnR2L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTEcgU21hcnRUVlxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBTTUFSVFRWXV0sIFtcbiAgICAgICAgICAgIC8obmV4dXNcXHNbNDVdKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExHXG4gICAgICAgICAgICAvbGdbZTtcXHNcXC8tXSsoXFx3KikvaSxcbiAgICAgICAgICAgIC9hbmRyb2lkLitsZyhcXC0/W1xcZFxcd10rKVxccytidWlsZC9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdMRyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKyhpZGVhdGFiW2EtejAtOVxcLVxcc10rKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIExlbm92b1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTGVub3ZvJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvbGludXg7LisoKGpvbGxhKSk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEpvbGxhXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC8oKHBlYmJsZSkpYXBwXFwvW1xcZFxcLl0rXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBlYmJsZVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBXRUFSQUJMRV1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKG9wcG8pXFxzPyhbXFx3XFxzXSspXFxzYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPUFBPXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbXG5cbiAgICAgICAgICAgIC9jcmtleS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIENocm9tZWNhc3RcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdDaHJvbWVjYXN0J10sIFtWRU5ET1IsICdHb29nbGUnXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMoZ2xhc3MpXFxzXFxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHb29nbGUgR2xhc3NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dvb2dsZSddLCBbVFlQRSwgV0VBUkFCTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhwaXhlbCBjKVxccy9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR29vZ2xlIFBpeGVsIENcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dvb2dsZSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMocGl4ZWwgeGx8cGl4ZWwpXFxzL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdvb2dsZSBQaXhlbFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnR29vZ2xlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rO1xccyhcXHcrKVxccytidWlsZFxcL2htXFwxL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWGlhb21pIEhvbmdtaSAnbnVtZXJpYycgbW9kZWxzXG4gICAgICAgICAgICAvYW5kcm9pZC4rKGhtW1xcc1xcLV9dKm5vdGU/W1xcc19dKig/OlxcZFxcdyk/KVxccytidWlsZC9pLCAgICAgICAgICAgICAgIC8vIFhpYW9taSBIb25nbWlcbiAgICAgICAgICAgIC9hbmRyb2lkLisobWlbXFxzXFwtX10qKD86b25lfG9uZVtcXHNfXXBsdXN8bm90ZSBsdGUpP1tcXHNfXSooPzpcXGQ/XFx3PylbXFxzX10qKD86cGx1cyk/KVxccytidWlsZC9pLCAgICAvLyBYaWFvbWkgTWlcbiAgICAgICAgICAgIC9hbmRyb2lkLisocmVkbWlbXFxzXFwtX10qKD86bm90ZSk/KD86W1xcc19dKltcXHdcXHNdKykpXFxzK2J1aWxkL2kgICAgICAgLy8gUmVkbWkgUGhvbmVzXG4gICAgICAgICAgICBdLCBbW01PREVMLCAvXy9nLCAnICddLCBbVkVORE9SLCAnWGlhb21pJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuKyhtaVtcXHNcXC1fXSooPzpwYWQpKD86W1xcc19dKltcXHdcXHNdKykpXFxzK2J1aWxkL2kgICAgICAgICAgICAvLyBNaSBQYWQgdGFibGV0c1xuICAgICAgICAgICAgXSxbW01PREVMLCAvXy9nLCAnICddLCBbVkVORE9SLCAnWGlhb21pJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgL2FuZHJvaWQuKztcXHMobVsxLTVdXFxzbm90ZSlcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNZWl6dSBUYWJsZXRcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ01laXp1J10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rYTAwMCgxKVxccytidWlsZC9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmVQbHVzXG4gICAgICAgICAgICAvYW5kcm9pZC4rb25lcGx1c1xccyhhXFxkezR9KVxccytidWlsZC9pXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdPbmVQbHVzJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihSQ1RbXFxkXFx3XSspXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUkNBIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1JDQSddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXFxzXSsoVmVudWVbXFxkXFxzXXsyLDd9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGwgVmVudWUgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnRGVsbCddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooUVtUfE1dW1xcZFxcd10rKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFZlcml6b24gVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdWZXJpem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhCYXJuZXNbJlxcc10rTm9ibGVcXHMrfEJOW1JUXSkoVj8uKilcXHMrYnVpbGQvaSAgICAgLy8gQmFybmVzICYgTm9ibGUgVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0Jhcm5lcyAmIE5vYmxlJ10sIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccysoVE1cXGR7M30uKlxcYilcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJhcm5lcyAmIE5vYmxlIFRhYmxldFxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnTnVWaXNpb24nXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLis7XFxzKGs4OClcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBaVEUgSyBTZXJpZXMgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdaVEUnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKGdlblxcZHszfSlcXHMrYnVpbGQuKjQ5aC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN3aXNzIEdFTiBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ1N3aXNzJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKih6dXJcXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTd2lzcyBaVVIgVGFibGV0XG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdTd2lzcyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooKFpla2kpP1RCLipcXGIpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgLy8gWmVraSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdaZWtpJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvKGFuZHJvaWQpLitbO1xcL11cXHMrKFtZUl1cXGR7Mn0pXFxzK2J1aWxkL2ksXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKyhEcmFnb25bXFwtXFxzXStUb3VjaFxccyt8RFQpKFxcd3s1fSlcXHNidWlsZC9pICAgICAgICAvLyBEcmFnb24gVG91Y2ggVGFibGV0XG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0RyYWdvbiBUb3VjaCddLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKE5TLT9cXHd7MCw5fSlcXHNidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluc2lnbmlhIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0luc2lnbmlhJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKigoTlh8TmV4dCktP1xcd3swLDl9KVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAvLyBOZXh0Qm9vayBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdOZXh0Qm9vayddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooWHRyZW1lXFxfKT8oVigxWzA0NV18MlswMTVdfDMwfDQwfDYwfDdbMDVdfDkwKSlcXHMrYnVpbGQvaVxuICAgICAgICAgICAgXSwgW1tWRU5ET1IsICdWb2ljZSddLCBNT0RFTCwgW1RZUEUsIE1PQklMRV1dLCBbICAgICAgICAgICAgICAgICAgICAvLyBWb2ljZSBYdHJlbWUgUGhvbmVzXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKExWVEVMXFwtKT8oVjFbMTJdKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgLy8gTHZUZWwgUGhvbmVzXG4gICAgICAgICAgICBdLCBbW1ZFTkRPUiwgJ0x2VGVsJ10sIE1PREVMLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooVigxMDBNRHw3MDBOQXw3MDExfDkxN0cpLipcXGIpXFxzK2J1aWxkL2kgICAgICAgICAgLy8gRW52aXplbiBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdFbnZpemVuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rWztcXC9dXFxzKihMZVtcXHNcXC1dK1BhbilbXFxzXFwtXSsoXFx3ezEsOX0pXFxzK2J1aWxkL2kgICAgICAgICAgLy8gTGUgUGFuIFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL2FuZHJvaWQuK1s7XFwvXVxccyooVHJpb1tcXHNcXC1dKi4qKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hY2hTcGVlZCBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbTU9ERUwsIFtWRU5ET1IsICdNYWNoU3BlZWQnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqKFRyaW5pdHkpW1xcLVxcc10qKFRcXGR7M30pXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgLy8gVHJpbml0eSBUYWJsZXRzXG4gICAgICAgICAgICBdLCBbVkVORE9SLCBNT0RFTCwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLitbO1xcL11cXHMqVFVfKDE0OTEpXFxzK2J1aWxkL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUm90b3IgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnUm90b3InXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG5cbiAgICAgICAgICAgIC9hbmRyb2lkLisoS1MoLispKVxccytidWlsZC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFtYXpvbiBLaW5kbGUgVGFibGV0c1xuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnQW1hem9uJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuXG4gICAgICAgICAgICAvYW5kcm9pZC4rKEdpZ2FzZXQpW1xcc1xcLV0rKFFcXHd7MSw5fSlcXHMrYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAvLyBHaWdhc2V0IFRhYmxldHNcbiAgICAgICAgICAgIF0sIFtWRU5ET1IsIE1PREVMLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgL1xccyh0YWJsZXR8dGFiKVs7XFwvXS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVuaWRlbnRpZmlhYmxlIFRhYmxldFxuICAgICAgICAgICAgL1xccyhtb2JpbGUpKD86WztcXC9dfFxcc3NhZmFyaSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVbmlkZW50aWZpYWJsZSBNb2JpbGVcbiAgICAgICAgICAgIF0sIFtbVFlQRSwgdXRpbC5sb3dlcml6ZV0sIFZFTkRPUiwgTU9ERUxdLCBbXG5cbiAgICAgICAgICAgIC8oYW5kcm9pZFtcXHdcXC5cXHNcXC1dezAsOX0pOy4rYnVpbGQvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdlbmVyaWMgQW5kcm9pZCBEZXZpY2VcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0dlbmVyaWMnXV1cblxuXG4gICAgICAgIC8qLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgICAgICAgIC8vIFRPRE86IG1vdmUgdG8gc3RyaW5nIG1hcFxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG4gICAgICAgICAgICAvKEM2NjAzKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbnkgWHBlcmlhIFogQzY2MDNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdYcGVyaWEgWiBDNjYwMyddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oQzY5MDMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29ueSBYcGVyaWEgWiAxXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnWHBlcmlhIFogMSddLCBbVkVORE9SLCAnU29ueSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhTTS1HOTAwW0Z8SF0pL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBTNVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBTNSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzcxMDIpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgR3JhbmQgMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCAyJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1HNTMwSCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBHcmFuZCBQcmltZVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBHcmFuZCBQcmltZSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tRzMxM0haKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ0dhbGF4eSBWJ10sIFtWRU5ET1IsICdTYW1zdW5nJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhTTS1UODA1KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYW1zdW5nIEdhbGF4eSBUYWIgUyAxMC41XG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiBTIDEwLjUnXSwgW1ZFTkRPUiwgJ1NhbXN1bmcnXSwgW1RZUEUsIFRBQkxFVF1dLCBbXG4gICAgICAgICAgICAvKFNNLUc4MDBGKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhbXN1bmcgR2FsYXh5IFM1IE1pbmlcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdHYWxheHkgUzUgTWluaSddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgTU9CSUxFXV0sIFtcbiAgICAgICAgICAgIC8oU00tVDMxMSkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2Ftc3VuZyBHYWxheHkgVGFiIDMgOC4wXG4gICAgICAgICAgICBdLCBbW01PREVMLCAnR2FsYXh5IFRhYiAzIDguMCddLCBbVkVORE9SLCAnU2Ftc3VuZyddLCBbVFlQRSwgVEFCTEVUXV0sIFtcblxuICAgICAgICAgICAgLyhUM0MpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBUM0NcbiAgICAgICAgICAgIF0sIFtNT0RFTCwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBUMUpcXCspL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWR2YW4gVmFuZHJvaWQgVDFKK1xuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1ZhbmRyb2lkIFQxSisnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBUQUJMRVRdXSwgW1xuICAgICAgICAgICAgLyhBRFZBTiBTNEEpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZHZhbiBWYW5kcm9pZCBTNEFcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdWYW5kcm9pZCBTNEEnXSwgW1ZFTkRPUiwgJ0FkdmFuJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKFY5NzJNKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFpURSBWOTcyTVxuICAgICAgICAgICAgXSwgW01PREVMLCBbVkVORE9SLCAnWlRFJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuXG4gICAgICAgICAgICAvKGktbW9iaWxlKVxccyhJUVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhJUTYuMykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBJUSBJUSA2LjNcbiAgICAgICAgICAgIF0sIFtbTU9ERUwsICdJUSA2LjMnXSwgW1ZFTkRPUiwgJ2ktbW9iaWxlJ10sIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLW1vYmlsZSlcXHMoaS1zdHlsZVxcc1tcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaS1tb2JpbGUgaS1TVFlMRVxuICAgICAgICAgICAgXSwgW1ZFTkRPUiwgTU9ERUwsIFtUWVBFLCBNT0JJTEVdXSwgW1xuICAgICAgICAgICAgLyhpLVNUWUxFMi4xKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpLW1vYmlsZSBpLVNUWUxFIDIuMVxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ2ktU1RZTEUgMi4xJ10sIFtWRU5ET1IsICdpLW1vYmlsZSddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLyhtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb2JpaXN0YXIgdG91Y2ggTEFJIDUxMlxuICAgICAgICAgICAgXSwgW1tNT0RFTCwgJ1RvdWNoIExBSSA1MTInXSwgW1ZFTkRPUiwgJ21vYmlpc3RhciddLCBbVFlQRSwgTU9CSUxFXV0sIFtcblxuICAgICAgICAgICAgLy8vLy8vLy8vLy8vL1xuICAgICAgICAgICAgLy8gRU5EIFRPRE9cbiAgICAgICAgICAgIC8vLy8vLy8vLy8vKi9cblxuICAgICAgICBdLFxuXG4gICAgICAgIGVuZ2luZSA6IFtbXG5cbiAgICAgICAgICAgIC93aW5kb3dzLitcXHNlZGdlXFwvKFtcXHdcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVkZ2VIVE1MXG4gICAgICAgICAgICBdLCBbVkVSU0lPTiwgW05BTUUsICdFZGdlSFRNTCddXSwgW1xuXG4gICAgICAgICAgICAvKHByZXN0bylcXC8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZXN0b1xuICAgICAgICAgICAgLyh3ZWJraXR8dHJpZGVudHxuZXRmcm9udHxuZXRzdXJmfGFtYXlhfGx5bnh8dzNtKVxcLyhbXFx3XFwuXSspL2ksICAgICAvLyBXZWJLaXQvVHJpZGVudC9OZXRGcm9udC9OZXRTdXJmL0FtYXlhL0x5bngvdzNtXG4gICAgICAgICAgICAvKGtodG1sfHRhc21hbnxsaW5rcylbXFwvXFxzXVxcKD8oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gS0hUTUwvVGFzbWFuL0xpbmtzXG4gICAgICAgICAgICAvKGljYWIpW1xcL1xcc10oWzIzXVxcLltcXGRcXC5dKykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaUNhYlxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC9ydlxcOihbXFx3XFwuXXsxLDl9KS4rKGdlY2tvKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2Vja29cbiAgICAgICAgICAgIF0sIFtWRVJTSU9OLCBOQU1FXVxuICAgICAgICBdLFxuXG4gICAgICAgIG9zIDogW1tcblxuICAgICAgICAgICAgLy8gV2luZG93cyBiYXNlZFxuICAgICAgICAgICAgL21pY3Jvc29mdFxccyh3aW5kb3dzKVxccyh2aXN0YXx4cCkvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgKGlUdW5lcylcbiAgICAgICAgICAgIF0sIFtOQU1FLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgLyh3aW5kb3dzKVxcc250XFxzNlxcLjI7XFxzKGFybSkvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2luZG93cyBSVFxuICAgICAgICAgICAgLyh3aW5kb3dzXFxzcGhvbmUoPzpcXHNvcykqKVtcXHNcXC9dPyhbXFxkXFwuXFxzXFx3XSopL2ksICAgICAgICAgICAgICAgICAgIC8vIFdpbmRvd3MgUGhvbmVcbiAgICAgICAgICAgIC8od2luZG93c1xcc21vYmlsZXx3aW5kb3dzKVtcXHNcXC9dPyhbbnRjZVxcZFxcLlxcc10rXFx3KS9pXG4gICAgICAgICAgICBdLCBbTkFNRSwgW1ZFUlNJT04sIG1hcHBlci5zdHIsIG1hcHMub3Mud2luZG93cy52ZXJzaW9uXV0sIFtcbiAgICAgICAgICAgIC8od2luKD89M3w5fG4pfHdpblxcczl4XFxzKShbbnRcXGRcXC5dKykvaVxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnV2luZG93cyddLCBbVkVSU0lPTiwgbWFwcGVyLnN0ciwgbWFwcy5vcy53aW5kb3dzLnZlcnNpb25dXSwgW1xuXG4gICAgICAgICAgICAvLyBNb2JpbGUvRW1iZWRkZWQgT1NcbiAgICAgICAgICAgIC9cXCgoYmIpKDEwKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrQmVycnkgMTBcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0JsYWNrQmVycnknXSwgVkVSU0lPTl0sIFtcbiAgICAgICAgICAgIC8oYmxhY2tiZXJyeSlcXHcqXFwvPyhbXFx3XFwuXSopL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJsYWNrYmVycnlcbiAgICAgICAgICAgIC8odGl6ZW4pW1xcL1xcc10oW1xcd1xcLl0rKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRpemVuXG4gICAgICAgICAgICAvKGFuZHJvaWR8d2Vib3N8cGFsbVxcc29zfHFueHxiYWRhfHJpbVxcc3RhYmxldFxcc29zfG1lZWdvfGNvbnRpa2kpW1xcL1xccy1dPyhbXFx3XFwuXSopL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFuZHJvaWQvV2ViT1MvUGFsbS9RTlgvQmFkYS9SSU0vTWVlR28vQ29udGlraVxuICAgICAgICAgICAgL2xpbnV4Oy4rKHNhaWxmaXNoKTsvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYWlsZmlzaCBPU1xuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG4gICAgICAgICAgICAvKHN5bWJpYW5cXHM/b3N8c3ltYm9zfHM2MCg/PTspKVtcXC9cXHMtXT8oW1xcd1xcLl0qKS9pICAgICAgICAgICAgICAgICAgLy8gU3ltYmlhblxuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU3ltYmlhbiddLCBWRVJTSU9OXSwgW1xuICAgICAgICAgICAgL1xcKChzZXJpZXM0MCk7L2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2VyaWVzIDQwXG4gICAgICAgICAgICBdLCBbTkFNRV0sIFtcbiAgICAgICAgICAgIC9tb3ppbGxhLitcXChtb2JpbGU7LitnZWNrby4rZmlyZWZveC9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0ZpcmVmb3ggT1MnXSwgVkVSU0lPTl0sIFtcblxuICAgICAgICAgICAgLy8gQ29uc29sZVxuICAgICAgICAgICAgLyhuaW50ZW5kb3xwbGF5c3RhdGlvbilcXHMoW3dpZHMzNHBvcnRhYmxldnVdKykvaSwgICAgICAgICAgICAgICAgICAgLy8gTmludGVuZG8vUGxheXN0YXRpb25cblxuICAgICAgICAgICAgLy8gR05VL0xpbnV4IGJhc2VkXG4gICAgICAgICAgICAvKG1pbnQpW1xcL1xcc1xcKF0/KFxcdyopL2ksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNaW50XG4gICAgICAgICAgICAvKG1hZ2VpYXx2ZWN0b3JsaW51eClbO1xcc10vaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWdlaWEvVmVjdG9yTGludXhcbiAgICAgICAgICAgIC8oam9saXxba3hsbl0/dWJ1bnR1fGRlYmlhbnxzdXNlfG9wZW5zdXNlfGdlbnRvb3woPz1cXHMpYXJjaHxzbGFja3dhcmV8ZmVkb3JhfG1hbmRyaXZhfGNlbnRvc3xwY2xpbnV4b3N8cmVkaGF0fHplbndhbGt8bGlucHVzKVtcXC9cXHMtXT8oPyFjaHJvbSkoW1xcd1xcLi1dKikvaSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSm9saS9VYnVudHUvRGViaWFuL1NVU0UvR2VudG9vL0FyY2gvU2xhY2t3YXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZlZG9yYS9NYW5kcml2YS9DZW50T1MvUENMaW51eE9TL1JlZEhhdC9aZW53YWxrL0xpbnB1c1xuICAgICAgICAgICAgLyhodXJkfGxpbnV4KVxccz8oW1xcd1xcLl0qKS9pLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIdXJkL0xpbnV4XG4gICAgICAgICAgICAvKGdudSlcXHM/KFtcXHdcXC5dKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdOVVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLCBbXG5cbiAgICAgICAgICAgIC8oY3JvcylcXHNbXFx3XStcXHMoW1xcd1xcLl0rXFx3KS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hyb21pdW0gT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ0Nocm9taXVtIE9TJ10sIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgLyhzdW5vcylcXHM/KFtcXHdcXC5cXGRdKikvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU29sYXJpc1xuICAgICAgICAgICAgXSwgW1tOQU1FLCAnU29sYXJpcyddLCBWRVJTSU9OXSwgW1xuXG4gICAgICAgICAgICAvLyBCU0QgYmFzZWRcbiAgICAgICAgICAgIC9cXHMoW2ZyZW50b3BjLV17MCw0fWJzZHxkcmFnb25mbHkpXFxzPyhbXFx3XFwuXSopL2kgICAgICAgICAgICAgICAgICAgIC8vIEZyZWVCU0QvTmV0QlNEL09wZW5CU0QvUEMtQlNEL0RyYWdvbkZseVxuICAgICAgICAgICAgXSwgW05BTUUsIFZFUlNJT05dLFtcblxuICAgICAgICAgICAgLyhoYWlrdSlcXHMoXFx3KykvaSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhhaWt1XG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl0sW1xuXG4gICAgICAgICAgICAvY2ZuZXR3b3JrXFwvLitkYXJ3aW4vaSxcbiAgICAgICAgICAgIC9pcFtob25lYWRdezIsNH0oPzouKm9zXFxzKFtcXHddKylcXHNsaWtlXFxzbWFjfDtcXHNvcGVyYSkvaSAgICAgICAgICAgICAvLyBpT1NcbiAgICAgICAgICAgIF0sIFtbVkVSU0lPTiwgL18vZywgJy4nXSwgW05BTUUsICdpT1MnXV0sIFtcblxuICAgICAgICAgICAgLyhtYWNcXHNvc1xcc3gpXFxzPyhbXFx3XFxzXFwuXSopL2ksXG4gICAgICAgICAgICAvKG1hY2ludG9zaHxtYWMoPz1fcG93ZXJwYylcXHMpL2kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWMgT1NcbiAgICAgICAgICAgIF0sIFtbTkFNRSwgJ01hYyBPUyddLCBbVkVSU0lPTiwgL18vZywgJy4nXV0sIFtcblxuICAgICAgICAgICAgLy8gT3RoZXJcbiAgICAgICAgICAgIC8oKD86b3Blbik/c29sYXJpcylbXFwvXFxzLV0/KFtcXHdcXC5dKikvaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNvbGFyaXNcbiAgICAgICAgICAgIC8oYWl4KVxccygoXFxkKSg/PVxcLnxcXCl8XFxzKVtcXHdcXC5dKSovaSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFJWFxuICAgICAgICAgICAgLyhwbGFuXFxzOXxtaW5peHxiZW9zfG9zXFwvMnxhbWlnYW9zfG1vcnBob3N8cmlzY1xcc29zfG9wZW52bXMpL2ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBsYW45L01pbml4L0JlT1MvT1MyL0FtaWdhT1MvTW9ycGhPUy9SSVNDT1MvT3BlblZNU1xuICAgICAgICAgICAgLyh1bml4KVxccz8oW1xcd1xcLl0qKS9pICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVTklYXG4gICAgICAgICAgICBdLCBbTkFNRSwgVkVSU0lPTl1cbiAgICAgICAgXVxuICAgIH07XG5cblxuICAgIC8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQ29uc3RydWN0b3JcbiAgICAvLy8vLy8vLy8vLy8vLy8vXG4gICAgLypcbiAgICB2YXIgQnJvd3NlciA9IGZ1bmN0aW9uIChuYW1lLCB2ZXJzaW9uKSB7XG4gICAgICAgIHRoaXNbTkFNRV0gPSBuYW1lO1xuICAgICAgICB0aGlzW1ZFUlNJT05dID0gdmVyc2lvbjtcbiAgICB9O1xuICAgIHZhciBDUFUgPSBmdW5jdGlvbiAoYXJjaCkge1xuICAgICAgICB0aGlzW0FSQ0hJVEVDVFVSRV0gPSBhcmNoO1xuICAgIH07XG4gICAgdmFyIERldmljZSA9IGZ1bmN0aW9uICh2ZW5kb3IsIG1vZGVsLCB0eXBlKSB7XG4gICAgICAgIHRoaXNbVkVORE9SXSA9IHZlbmRvcjtcbiAgICAgICAgdGhpc1tNT0RFTF0gPSBtb2RlbDtcbiAgICAgICAgdGhpc1tUWVBFXSA9IHR5cGU7XG4gICAgfTtcbiAgICB2YXIgRW5naW5lID0gQnJvd3NlcjtcbiAgICB2YXIgT1MgPSBCcm93c2VyO1xuICAgICovXG4gICAgdmFyIFVBUGFyc2VyID0gZnVuY3Rpb24gKHVhc3RyaW5nLCBleHRlbnNpb25zKSB7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB1YXN0cmluZyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGV4dGVuc2lvbnMgPSB1YXN0cmluZztcbiAgICAgICAgICAgIHVhc3RyaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFVBUGFyc2VyKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBVQVBhcnNlcih1YXN0cmluZywgZXh0ZW5zaW9ucykuZ2V0UmVzdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdWEgPSB1YXN0cmluZyB8fCAoKHdpbmRvdyAmJiB3aW5kb3cubmF2aWdhdG9yICYmIHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50KSA/IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50IDogRU1QVFkpO1xuICAgICAgICB2YXIgcmd4bWFwID0gZXh0ZW5zaW9ucyA/IHV0aWwuZXh0ZW5kKHJlZ2V4ZXMsIGV4dGVuc2lvbnMpIDogcmVnZXhlcztcbiAgICAgICAgLy92YXIgYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgIC8vdmFyIGNwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgLy92YXIgZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAvL3ZhciBlbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgIC8vdmFyIG9zID0gbmV3IE9TKCk7XG5cbiAgICAgICAgdGhpcy5nZXRCcm93c2VyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGJyb3dzZXIgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoYnJvd3NlciwgdWEsIHJneG1hcC5icm93c2VyKTtcbiAgICAgICAgICAgIGJyb3dzZXIubWFqb3IgPSB1dGlsLm1ham9yKGJyb3dzZXIudmVyc2lvbik7IC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgICAgIHJldHVybiBicm93c2VyO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENQVSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjcHUgPSB7IGFyY2hpdGVjdHVyZTogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwoY3B1LCB1YSwgcmd4bWFwLmNwdSk7XG4gICAgICAgICAgICByZXR1cm4gY3B1O1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldERldmljZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBkZXZpY2UgPSB7IHZlbmRvcjogdW5kZWZpbmVkLCBtb2RlbDogdW5kZWZpbmVkLCB0eXBlOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChkZXZpY2UsIHVhLCByZ3htYXAuZGV2aWNlKTtcbiAgICAgICAgICAgIHJldHVybiBkZXZpY2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0RW5naW5lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVuZ2luZSA9IHsgbmFtZTogdW5kZWZpbmVkLCB2ZXJzaW9uOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgIG1hcHBlci5yZ3guY2FsbChlbmdpbmUsIHVhLCByZ3htYXAuZW5naW5lKTtcbiAgICAgICAgICAgIHJldHVybiBlbmdpbmU7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0T1MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgb3MgPSB7IG5hbWU6IHVuZGVmaW5lZCwgdmVyc2lvbjogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICBtYXBwZXIucmd4LmNhbGwob3MsIHVhLCByZ3htYXAub3MpO1xuICAgICAgICAgICAgcmV0dXJuIG9zO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldFJlc3VsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdWEgICAgICA6IHRoaXMuZ2V0VUEoKSxcbiAgICAgICAgICAgICAgICBicm93c2VyIDogdGhpcy5nZXRCcm93c2VyKCksXG4gICAgICAgICAgICAgICAgZW5naW5lICA6IHRoaXMuZ2V0RW5naW5lKCksXG4gICAgICAgICAgICAgICAgb3MgICAgICA6IHRoaXMuZ2V0T1MoKSxcbiAgICAgICAgICAgICAgICBkZXZpY2UgIDogdGhpcy5nZXREZXZpY2UoKSxcbiAgICAgICAgICAgICAgICBjcHUgICAgIDogdGhpcy5nZXRDUFUoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRVQSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB1YTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZXRVQSA9IGZ1bmN0aW9uICh1YXN0cmluZykge1xuICAgICAgICAgICAgdWEgPSB1YXN0cmluZztcbiAgICAgICAgICAgIC8vYnJvd3NlciA9IG5ldyBCcm93c2VyKCk7XG4gICAgICAgICAgICAvL2NwdSA9IG5ldyBDUFUoKTtcbiAgICAgICAgICAgIC8vZGV2aWNlID0gbmV3IERldmljZSgpO1xuICAgICAgICAgICAgLy9lbmdpbmUgPSBuZXcgRW5naW5lKCk7XG4gICAgICAgICAgICAvL29zID0gbmV3IE9TKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIFVBUGFyc2VyLlZFUlNJT04gPSBMSUJWRVJTSU9OO1xuICAgIFVBUGFyc2VyLkJST1dTRVIgPSB7XG4gICAgICAgIE5BTUUgICAgOiBOQU1FLFxuICAgICAgICBNQUpPUiAgIDogTUFKT1IsIC8vIGRlcHJlY2F0ZWRcbiAgICAgICAgVkVSU0lPTiA6IFZFUlNJT05cbiAgICB9O1xuICAgIFVBUGFyc2VyLkNQVSA9IHtcbiAgICAgICAgQVJDSElURUNUVVJFIDogQVJDSElURUNUVVJFXG4gICAgfTtcbiAgICBVQVBhcnNlci5ERVZJQ0UgPSB7XG4gICAgICAgIE1PREVMICAgOiBNT0RFTCxcbiAgICAgICAgVkVORE9SICA6IFZFTkRPUixcbiAgICAgICAgVFlQRSAgICA6IFRZUEUsXG4gICAgICAgIENPTlNPTEUgOiBDT05TT0xFLFxuICAgICAgICBNT0JJTEUgIDogTU9CSUxFLFxuICAgICAgICBTTUFSVFRWIDogU01BUlRUVixcbiAgICAgICAgVEFCTEVUICA6IFRBQkxFVCxcbiAgICAgICAgV0VBUkFCTEU6IFdFQVJBQkxFLFxuICAgICAgICBFTUJFRERFRDogRU1CRURERURcbiAgICB9O1xuICAgIFVBUGFyc2VyLkVOR0lORSA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICBVQVBhcnNlci5PUyA9IHtcbiAgICAgICAgTkFNRSAgICA6IE5BTUUsXG4gICAgICAgIFZFUlNJT04gOiBWRVJTSU9OXG4gICAgfTtcbiAgICAvL1VBUGFyc2VyLlV0aWxzID0gdXRpbDtcblxuICAgIC8vLy8vLy8vLy8vXG4gICAgLy8gRXhwb3J0XG4gICAgLy8vLy8vLy8vL1xuXG5cbiAgICAvLyBjaGVjayBqcyBlbnZpcm9ubWVudFxuICAgIGlmICh0eXBlb2YoZXhwb3J0cykgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgLy8gbm9kZWpzIGVudlxuICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gVU5ERUZfVFlQRSAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogdGVzdCEhISEhISEhXG4gICAgICAgIC8qXG4gICAgICAgIGlmIChyZXF1aXJlICYmIHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlICYmIHByb2Nlc3MpIHtcbiAgICAgICAgICAgIC8vIGNsaVxuICAgICAgICAgICAgdmFyIGpzb25pemUgPSBmdW5jdGlvbiAoYXJyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gYXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wdXNoKG5ldyBVQVBhcnNlcihhcnJbaV0pLmdldFJlc3VsdCgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoSlNPTi5zdHJpbmdpZnkocmVzLCBudWxsLCAyKSArICdcXG4nKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAocHJvY2Vzcy5zdGRpbi5pc1RUWSkge1xuICAgICAgICAgICAgICAgIC8vIHZpYSBhcmdzXG4gICAgICAgICAgICAgICAganNvbml6ZShwcm9jZXNzLmFyZ3Yuc2xpY2UoMikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB2aWEgcGlwZVxuICAgICAgICAgICAgICAgIHZhciBzdHIgPSAnJztcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdyZWFkYWJsZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVhZCA9IHByb2Nlc3Muc3RkaW4ucmVhZCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVhZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyICs9IHJlYWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBwcm9jZXNzLnN0ZGluLm9uKCdlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGpzb25pemUoc3RyLnJlcGxhY2UoL1xcbiQvLCAnJykuc3BsaXQoJ1xcbicpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICBleHBvcnRzLlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVxdWlyZWpzIGVudiAob3B0aW9uYWwpXG4gICAgICAgIGlmICh0eXBlb2YoZGVmaW5lKSA9PT0gRlVOQ19UWVBFICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFVBUGFyc2VyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAod2luZG93KSB7XG4gICAgICAgICAgICAvLyBicm93c2VyIGVudlxuICAgICAgICAgICAgd2luZG93LlVBUGFyc2VyID0gVUFQYXJzZXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBqUXVlcnkvWmVwdG8gc3BlY2lmaWMgKG9wdGlvbmFsKVxuICAgIC8vIE5vdGU6XG4gICAgLy8gICBJbiBBTUQgZW52IHRoZSBnbG9iYWwgc2NvcGUgc2hvdWxkIGJlIGtlcHQgY2xlYW4sIGJ1dCBqUXVlcnkgaXMgYW4gZXhjZXB0aW9uLlxuICAgIC8vICAgalF1ZXJ5IGFsd2F5cyBleHBvcnRzIHRvIGdsb2JhbCBzY29wZSwgdW5sZXNzIGpRdWVyeS5ub0NvbmZsaWN0KHRydWUpIGlzIHVzZWQsXG4gICAgLy8gICBhbmQgd2Ugc2hvdWxkIGNhdGNoIHRoYXQuXG4gICAgdmFyICQgPSB3aW5kb3cgJiYgKHdpbmRvdy5qUXVlcnkgfHwgd2luZG93LlplcHRvKTtcbiAgICBpZiAodHlwZW9mICQgIT09IFVOREVGX1RZUEUpIHtcbiAgICAgICAgdmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcigpO1xuICAgICAgICAkLnVhID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAkLnVhLmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZXIuZ2V0VUEoKTtcbiAgICAgICAgfTtcbiAgICAgICAgJC51YS5zZXQgPSBmdW5jdGlvbiAodWFzdHJpbmcpIHtcbiAgICAgICAgICAgIHBhcnNlci5zZXRVQSh1YXN0cmluZyk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gcGFyc2VyLmdldFJlc3VsdCgpO1xuICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAkLnVhW3Byb3BdID0gcmVzdWx0W3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxufSkodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcgPyB3aW5kb3cgOiB0aGlzKTtcbiIsInZhciB2MSA9IHJlcXVpcmUoJy4vdjEnKTtcbnZhciB2NCA9IHJlcXVpcmUoJy4vdjQnKTtcblxudmFyIHV1aWQgPSB2NDtcbnV1aWQudjEgPSB2MTtcbnV1aWQudjQgPSB2NDtcblxubW9kdWxlLmV4cG9ydHMgPSB1dWlkO1xuIiwiLyoqXG4gKiBDb252ZXJ0IGFycmF5IG9mIDE2IGJ5dGUgdmFsdWVzIHRvIFVVSUQgc3RyaW5nIGZvcm1hdCBvZiB0aGUgZm9ybTpcbiAqIFhYWFhYWFhYLVhYWFgtWFhYWC1YWFhYLVhYWFhYWFhYWFhYWFxuICovXG52YXIgYnl0ZVRvSGV4ID0gW107XG5mb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgKytpKSB7XG4gIGJ5dGVUb0hleFtpXSA9IChpICsgMHgxMDApLnRvU3RyaW5nKDE2KS5zdWJzdHIoMSk7XG59XG5cbmZ1bmN0aW9uIGJ5dGVzVG9VdWlkKGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gb2Zmc2V0IHx8IDA7XG4gIHZhciBidGggPSBieXRlVG9IZXg7XG4gIHJldHVybiBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnl0ZXNUb1V1aWQ7XG4iLCIvLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiAgSW4gdGhlXG4vLyBicm93c2VyIHRoaXMgaXMgYSBsaXR0bGUgY29tcGxpY2F0ZWQgZHVlIHRvIHVua25vd24gcXVhbGl0eSBvZiBNYXRoLnJhbmRvbSgpXG4vLyBhbmQgaW5jb25zaXN0ZW50IHN1cHBvcnQgZm9yIHRoZSBgY3J5cHRvYCBBUEkuICBXZSBkbyB0aGUgYmVzdCB3ZSBjYW4gdmlhXG4vLyBmZWF0dXJlLWRldGVjdGlvblxuXG4vLyBnZXRSYW5kb21WYWx1ZXMgbmVlZHMgdG8gYmUgaW52b2tlZCBpbiBhIGNvbnRleHQgd2hlcmUgXCJ0aGlzXCIgaXMgYSBDcnlwdG8gaW1wbGVtZW50YXRpb24uXG52YXIgZ2V0UmFuZG9tVmFsdWVzID0gKHR5cGVvZihjcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChjcnlwdG8pKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICh0eXBlb2YobXNDcnlwdG8pICE9ICd1bmRlZmluZWQnICYmIG1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcy5iaW5kKG1zQ3J5cHRvKSk7XG5pZiAoZ2V0UmFuZG9tVmFsdWVzKSB7XG4gIC8vIFdIQVRXRyBjcnlwdG8gUk5HIC0gaHR0cDovL3dpa2kud2hhdHdnLm9yZy93aWtpL0NyeXB0b1xuICB2YXIgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHdoYXR3Z1JORygpIHtcbiAgICBnZXRSYW5kb21WYWx1ZXMocm5kczgpO1xuICAgIHJldHVybiBybmRzODtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIE1hdGgucmFuZG9tKCktYmFzZWQgKFJORylcbiAgLy9cbiAgLy8gSWYgYWxsIGVsc2UgZmFpbHMsIHVzZSBNYXRoLnJhbmRvbSgpLiAgSXQncyBmYXN0LCBidXQgaXMgb2YgdW5zcGVjaWZpZWRcbiAgLy8gcXVhbGl0eS5cbiAgdmFyIHJuZHMgPSBuZXcgQXJyYXkoMTYpO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWF0aFJORygpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgcjsgaSA8IDE2OyBpKyspIHtcbiAgICAgIGlmICgoaSAmIDB4MDMpID09PSAwKSByID0gTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMDAwO1xuICAgICAgcm5kc1tpXSA9IHIgPj4+ICgoaSAmIDB4MDMpIDw8IDMpICYgMHhmZjtcbiAgICB9XG5cbiAgICByZXR1cm4gcm5kcztcbiAgfTtcbn1cbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbi8vICoqYHYxKClgIC0gR2VuZXJhdGUgdGltZS1iYXNlZCBVVUlEKipcbi8vXG4vLyBJbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vTGlvc0svVVVJRC5qc1xuLy8gYW5kIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS91dWlkLmh0bWxcblxudmFyIF9ub2RlSWQ7XG52YXIgX2Nsb2Nrc2VxO1xuXG4vLyBQcmV2aW91cyB1dWlkIGNyZWF0aW9uIHRpbWVcbnZhciBfbGFzdE1TZWNzID0gMDtcbnZhciBfbGFzdE5TZWNzID0gMDtcblxuLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9icm9vZmEvbm9kZS11dWlkIGZvciBBUEkgZGV0YWlsc1xuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIHZhciBiID0gYnVmIHx8IFtdO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB2YXIgbm9kZSA9IG9wdGlvbnMubm9kZSB8fCBfbm9kZUlkO1xuICB2YXIgY2xvY2tzZXEgPSBvcHRpb25zLmNsb2Nrc2VxICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNsb2Nrc2VxIDogX2Nsb2Nrc2VxO1xuXG4gIC8vIG5vZGUgYW5kIGNsb2Nrc2VxIG5lZWQgdG8gYmUgaW5pdGlhbGl6ZWQgdG8gcmFuZG9tIHZhbHVlcyBpZiB0aGV5J3JlIG5vdFxuICAvLyBzcGVjaWZpZWQuICBXZSBkbyB0aGlzIGxhemlseSB0byBtaW5pbWl6ZSBpc3N1ZXMgcmVsYXRlZCB0byBpbnN1ZmZpY2llbnRcbiAgLy8gc3lzdGVtIGVudHJvcHkuICBTZWUgIzE4OVxuICBpZiAobm9kZSA9PSBudWxsIHx8IGNsb2Nrc2VxID09IG51bGwpIHtcbiAgICB2YXIgc2VlZEJ5dGVzID0gcm5nKCk7XG4gICAgaWYgKG5vZGUgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuNSwgY3JlYXRlIGFuZCA0OC1iaXQgbm9kZSBpZCwgKDQ3IHJhbmRvbSBiaXRzICsgbXVsdGljYXN0IGJpdCA9IDEpXG4gICAgICBub2RlID0gX25vZGVJZCA9IFtcbiAgICAgICAgc2VlZEJ5dGVzWzBdIHwgMHgwMSxcbiAgICAgICAgc2VlZEJ5dGVzWzFdLCBzZWVkQnl0ZXNbMl0sIHNlZWRCeXRlc1szXSwgc2VlZEJ5dGVzWzRdLCBzZWVkQnl0ZXNbNV1cbiAgICAgIF07XG4gICAgfVxuICAgIGlmIChjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC4yLjIsIHJhbmRvbWl6ZSAoMTQgYml0KSBjbG9ja3NlcVxuICAgICAgY2xvY2tzZXEgPSBfY2xvY2tzZXEgPSAoc2VlZEJ5dGVzWzZdIDw8IDggfCBzZWVkQnl0ZXNbN10pICYgMHgzZmZmO1xuICAgIH1cbiAgfVxuXG4gIC8vIFVVSUQgdGltZXN0YW1wcyBhcmUgMTAwIG5hbm8tc2Vjb25kIHVuaXRzIHNpbmNlIHRoZSBHcmVnb3JpYW4gZXBvY2gsXG4gIC8vICgxNTgyLTEwLTE1IDAwOjAwKS4gIEpTTnVtYmVycyBhcmVuJ3QgcHJlY2lzZSBlbm91Z2ggZm9yIHRoaXMsIHNvXG4gIC8vIHRpbWUgaXMgaGFuZGxlZCBpbnRlcm5hbGx5IGFzICdtc2VjcycgKGludGVnZXIgbWlsbGlzZWNvbmRzKSBhbmQgJ25zZWNzJ1xuICAvLyAoMTAwLW5hbm9zZWNvbmRzIG9mZnNldCBmcm9tIG1zZWNzKSBzaW5jZSB1bml4IGVwb2NoLCAxOTcwLTAxLTAxIDAwOjAwLlxuICB2YXIgbXNlY3MgPSBvcHRpb25zLm1zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1zZWNzIDogbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgLy8gUGVyIDQuMi4xLjIsIHVzZSBjb3VudCBvZiB1dWlkJ3MgZ2VuZXJhdGVkIGR1cmluZyB0aGUgY3VycmVudCBjbG9ja1xuICAvLyBjeWNsZSB0byBzaW11bGF0ZSBoaWdoZXIgcmVzb2x1dGlvbiBjbG9ja1xuICB2YXIgbnNlY3MgPSBvcHRpb25zLm5zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5zZWNzIDogX2xhc3ROU2VjcyArIDE7XG5cbiAgLy8gVGltZSBzaW5jZSBsYXN0IHV1aWQgY3JlYXRpb24gKGluIG1zZWNzKVxuICB2YXIgZHQgPSAobXNlY3MgLSBfbGFzdE1TZWNzKSArIChuc2VjcyAtIF9sYXN0TlNlY3MpLzEwMDAwO1xuXG4gIC8vIFBlciA0LjIuMS4yLCBCdW1wIGNsb2Nrc2VxIG9uIGNsb2NrIHJlZ3Jlc3Npb25cbiAgaWYgKGR0IDwgMCAmJiBvcHRpb25zLmNsb2Nrc2VxID09PSB1bmRlZmluZWQpIHtcbiAgICBjbG9ja3NlcSA9IGNsb2Nrc2VxICsgMSAmIDB4M2ZmZjtcbiAgfVxuXG4gIC8vIFJlc2V0IG5zZWNzIGlmIGNsb2NrIHJlZ3Jlc3NlcyAobmV3IGNsb2Nrc2VxKSBvciB3ZSd2ZSBtb3ZlZCBvbnRvIGEgbmV3XG4gIC8vIHRpbWUgaW50ZXJ2YWxcbiAgaWYgKChkdCA8IDAgfHwgbXNlY3MgPiBfbGFzdE1TZWNzKSAmJiBvcHRpb25zLm5zZWNzID09PSB1bmRlZmluZWQpIHtcbiAgICBuc2VjcyA9IDA7XG4gIH1cblxuICAvLyBQZXIgNC4yLjEuMiBUaHJvdyBlcnJvciBpZiB0b28gbWFueSB1dWlkcyBhcmUgcmVxdWVzdGVkXG4gIGlmIChuc2VjcyA+PSAxMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXVpZC52MSgpOiBDYW5cXCd0IGNyZWF0ZSBtb3JlIHRoYW4gMTBNIHV1aWRzL3NlYycpO1xuICB9XG5cbiAgX2xhc3RNU2VjcyA9IG1zZWNzO1xuICBfbGFzdE5TZWNzID0gbnNlY3M7XG4gIF9jbG9ja3NlcSA9IGNsb2Nrc2VxO1xuXG4gIC8vIFBlciA0LjEuNCAtIENvbnZlcnQgZnJvbSB1bml4IGVwb2NoIHRvIEdyZWdvcmlhbiBlcG9jaFxuICBtc2VjcyArPSAxMjIxOTI5MjgwMDAwMDtcblxuICAvLyBgdGltZV9sb3dgXG4gIHZhciB0bCA9ICgobXNlY3MgJiAweGZmZmZmZmYpICogMTAwMDAgKyBuc2VjcykgJSAweDEwMDAwMDAwMDtcbiAgYltpKytdID0gdGwgPj4+IDI0ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDE2ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfbWlkYFxuICB2YXIgdG1oID0gKG1zZWNzIC8gMHgxMDAwMDAwMDAgKiAxMDAwMCkgJiAweGZmZmZmZmY7XG4gIGJbaSsrXSA9IHRtaCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRtaCAmIDB4ZmY7XG5cbiAgLy8gYHRpbWVfaGlnaF9hbmRfdmVyc2lvbmBcbiAgYltpKytdID0gdG1oID4+PiAyNCAmIDB4ZiB8IDB4MTA7IC8vIGluY2x1ZGUgdmVyc2lvblxuICBiW2krK10gPSB0bWggPj4+IDE2ICYgMHhmZjtcblxuICAvLyBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGAgKFBlciA0LjIuMiAtIGluY2x1ZGUgdmFyaWFudClcbiAgYltpKytdID0gY2xvY2tzZXEgPj4+IDggfCAweDgwO1xuXG4gIC8vIGBjbG9ja19zZXFfbG93YFxuICBiW2krK10gPSBjbG9ja3NlcSAmIDB4ZmY7XG5cbiAgLy8gYG5vZGVgXG4gIGZvciAodmFyIG4gPSAwOyBuIDwgNjsgKytuKSB7XG4gICAgYltpICsgbl0gPSBub2RlW25dO1xuICB9XG5cbiAgcmV0dXJuIGJ1ZiA/IGJ1ZiA6IGJ5dGVzVG9VdWlkKGIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHYxO1xuIiwidmFyIHJuZyA9IHJlcXVpcmUoJy4vbGliL3JuZycpO1xudmFyIGJ5dGVzVG9VdWlkID0gcmVxdWlyZSgnLi9saWIvYnl0ZXNUb1V1aWQnKTtcblxuZnVuY3Rpb24gdjQob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgdmFyIGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG5cbiAgaWYgKHR5cGVvZihvcHRpb25zKSA9PSAnc3RyaW5nJykge1xuICAgIGJ1ZiA9IG9wdGlvbnMgPT09ICdiaW5hcnknID8gbmV3IEFycmF5KDE2KSA6IG51bGw7XG4gICAgb3B0aW9ucyA9IG51bGw7XG4gIH1cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgdmFyIHJuZHMgPSBvcHRpb25zLnJhbmRvbSB8fCAob3B0aW9ucy5ybmcgfHwgcm5nKSgpO1xuXG4gIC8vIFBlciA0LjQsIHNldCBiaXRzIGZvciB2ZXJzaW9uIGFuZCBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGBcbiAgcm5kc1s2XSA9IChybmRzWzZdICYgMHgwZikgfCAweDQwO1xuICBybmRzWzhdID0gKHJuZHNbOF0gJiAweDNmKSB8IDB4ODA7XG5cbiAgLy8gQ29weSBieXRlcyB0byBidWZmZXIsIGlmIHByb3ZpZGVkXG4gIGlmIChidWYpIHtcbiAgICBmb3IgKHZhciBpaSA9IDA7IGlpIDwgMTY7ICsraWkpIHtcbiAgICAgIGJ1ZltpICsgaWldID0gcm5kc1tpaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZiB8fCBieXRlc1RvVXVpZChybmRzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2NDtcbiIsIi8qXHJcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXHJcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXHJcblxyXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXHJcblxyXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcclxuXHJcbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcclxuXHJcbn0pO1xyXG5cclxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XHJcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cclxuKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XHJcblxyXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxyXG5cclxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcclxuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XHJcblxyXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XHJcblxyXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXHJcbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xyXG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cclxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxyXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcclxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xyXG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xyXG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xyXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXHJcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XHJcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxyXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXHJcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cclxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXHJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcclxuICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xyXG4gICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXHJcbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcclxuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxyXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXHJcbiAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgIGxlbixcclxuICAgICAgICAgICAgaXRlbSxcclxuICAgICAgICAgICAgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XHJcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcclxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLFxyXG4gICAgICAgICAgICBzcGxpdCxcclxuICAgICAgICAgICAgcmVzdWx0ID0gW107XHJcblxyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcclxuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9O1xyXG5cclxufTtcclxuXHJcbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcclxuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi40IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odGhpcyB8fCB7fSkpO1xuIiwiaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1L09wZW5WaWR1JztcblxuaWYgKHdpbmRvdykge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zdHJpbmctbGl0ZXJhbFxuICAgIHdpbmRvd1snT3BlblZpZHUnXSA9IE9wZW5WaWR1O1xufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0Nvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygoISF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwnIDogJ1JlbW90ZScpLCAnY2FuZGlkYXRlIGZvcicsXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCwgSlNPTi5zdHJpbmdpZnkoY2FuZGlkYXRlKSk7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdvbkljZUNhbmRpZGF0ZScsIHtcbiAgICAgICAgICAgIGVuZHBvaW50TmFtZTogdGhpcy5jb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IGNhbmRpZGF0ZS5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBjYW5kaWRhdGUuc2RwTUxpbmVJbmRleFxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzZW5kaW5nIElDRSBjYW5kaWRhdGU6ICdcbiAgICAgICAgICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdFJlbW90ZVN0cmVhbXMob3B0aW9uczogU3RyZWFtT3B0aW9uc1NlcnZlcltdKTogdm9pZCB7XG5cbiAgICAgICAgLy8gVGhpcyBpcyByZWFkeSBmb3Igc3VwcG9ydGluZyBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uIG9iamVjdC4gUmlnaHQgbm93IHRoZSBsb29wIHdpbGwgYWx3YXlzIHJ1biBqdXN0IG9uY2VcbiAgICAgICAgLy8gdGhpcy5zdHJlYW0gc2hvdWxkIGFsc28gYmUgcmVwbGFjZWQgYnkgYSBjb2xsZWN0aW9uIG9mIHN0cmVhbXMgdG8gc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uXG4gICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgZnJhbWVSYXRlOiBvcHRzLmZyYW1lUmF0ZSxcbiAgICAgICAgICAgICAgICByZWN2QXVkaW86IG9wdHMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgcmVjdlZpZGVvOiBvcHRzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiBvcHRzLnR5cGVPZlZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLnNlc3Npb24sIHN0cmVhbU9wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oXCJSZW1vdGUgJ0Nvbm5lY3Rpb24nIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiAnLCB0aGlzLnN0cmVhbS5pbmJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFkZFN0cmVhbShzdHJlYW06IFN0cmVhbSk6IHZvaWQge1xuICAgICAgICBzdHJlYW0uY29ubmVjdGlvbiA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVTdHJlYW0oc3RyZWFtSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3RyZWFtKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyU3RhdGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL0xvY2FsUmVjb3JkZXJTdGF0ZSc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuXG4gKlxuICogPiBXQVJOSU5HOiBQZXJmb3JtaW5nIGJyb3dzZXIgbG9jYWwgcmVjb3JkaW5nIG9mICoqcmVtb3RlIHN0cmVhbXMqKiBtYXkgY2F1c2Ugc29tZSB0cm91Ymxlcy4gQSBsb25nIHdhaXRpbmcgdGltZSBtYXkgYmUgcmVxdWlyZWQgYWZ0ZXIgY2FsbGluZyBfTG9jYWxSZWNvcmRlci5zdG9wKClfIGluIHRoaXMgY2FzZVxuICovXG5leHBvcnQgY2xhc3MgTG9jYWxSZWNvcmRlciB7XG5cbiAgICBzdGF0ZTogTG9jYWxSZWNvcmRlclN0YXRlO1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uSWQ6IHN0cmluZztcbiAgICBwcml2YXRlIG1lZGlhUmVjb3JkZXI6IGFueTtcbiAgICBwcml2YXRlIGNodW5rczogYW55W10gPSBbXTtcbiAgICBwcml2YXRlIGJsb2I6IEJsb2I7XG4gICAgcHJpdmF0ZSBjb3VudCA9IDA7XG4gICAgcHJpdmF0ZSBpZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3U3JjOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBodG1sUGFyZW50RWxlbWVudElkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXc6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzdHJlYW06IFN0cmVhbSkge1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9ICghIXRoaXMuc3RyZWFtLmNvbm5lY3Rpb24pID8gdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgOiAnZGVmYXVsdC1jb25uZWN0aW9uJztcbiAgICAgICAgdGhpcy5pZCA9IHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnX2xvY2FscmVjb3JkJztcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFN0YXJ0cyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUFEWWAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RhcnRlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVjb3JkKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRyeSB7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZWNvcmQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUFEWVxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLmNsZWFuKClcXCcgb3IgaW5pdCBhIG5ldyBMb2NhbFJlY29yZGVyIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJTdGFydGluZyBsb2NhbCByZWNvcmRpbmcgb2Ygc3RyZWFtICdcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgXCInIG9mIGNvbm5lY3Rpb24gJ1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyBcIidcIik7XG5cblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9wdGlvbnM7XG4gICAgICAgICAgICAgICAgICAgIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA5JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA5JyB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA4JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA4JyB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdVc2luZyBtaW1lVHlwZSAnICsgb3B0aW9ucy5taW1lVHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCksIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignaXNUeXBlU3VwcG9ydGVkIGlzIG5vdCBzdXBwb3J0ZWQsIHVzaW5nIGRlZmF1bHQgY29kZWNzIGZvciBicm93c2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdGFydCgxMCk7XG5cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25kYXRhYXZhaWxhYmxlID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUuZGF0YSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25lcnJvciA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBlcnJvcjogJywgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdGFydCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdGFydGVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25wYXVzZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBwYXVzZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucmVzdW1lID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHJlc3VtZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ud2FybmluZyA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgd2FybmluZzogJyArIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBFbmRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2Agb3IgYFBBVVNFRGAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYEZJTklTSEVEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdG9wcGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBzdG9wKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyBvciBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdG9wKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFBhdXNlcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBQQVVTRURgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSBwYXVzZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHBhdXNlKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQucGF1c2UoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIG9yIFxcJ0xvY2FsUmVjb3JkZXIucmVzdW1lKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucGF1c2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzdW1lcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSByZXN1bWVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZXN1bWUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZXN1bWUoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5wYXVzZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnJlc3VtZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByZXZpZXdzIHRoZSByZWNvcmRpbmcsIGFwcGVuZGluZyBhIG5ldyBIVE1MVmlkZW9FbGVtZW50IHRvIGVsZW1lbnQgd2l0aCBpZCBgcGFyZW50SWRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgcHJldmlldyhwYXJlbnRFbGVtZW50KTogSFRNTFZpZGVvRWxlbWVudCB7XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5wcmV2aWV3KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmlkID0gdGhpcy5pZDtcbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuYXV0b3BsYXkgPSB0cnVlO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcGFyZW50RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhcmVudEVsZW1lbnREb20gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYXJlbnRFbGVtZW50KTtcbiAgICAgICAgICAgIGlmIChwYXJlbnRFbGVtZW50RG9tKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50RG9tLmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaHRtbFBhcmVudEVsZW1lbnRJZCA9IHBhcmVudEVsZW1lbnQuaWQ7XG4gICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuc3JjID0gdGhpcy52aWRlb1ByZXZpZXdTcmM7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9QcmV2aWV3O1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogR3JhY2VmdWxseSBzdG9wcyBhbmQgY2xlYW5zIHRoZSBjdXJyZW50IHJlY29yZGluZyAoV0FSTklORzogaXQgaXMgY29tcGxldGVseSBkaXNtaXNzZWQpLiBTZXRzIFtbc3RhdGVdXSB0byBgUkVBRFlgIHNvIHRoZSByZWNvcmRpbmcgY2FuIHN0YXJ0IGFnYWluXG4gICAgICovXG4gICAgY2xlYW4oKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGYgPSAoKSA9PiB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5ibG9iO1xuICAgICAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuY291bnQgPSAwO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubWVkaWFSZWNvcmRlcjtcbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFk7XG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HIHx8IHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcCgpLnRoZW4oKCkgPT4gZigpKS5jYXRjaCgoKSA9PiBmKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBEb3dubG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIHRocm91Z2ggdGhlIGJyb3dzZXIuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBkb3dubG9hZCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5kb3dubG9hZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGE6IEhUTUxBbmNob3JFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICAgICAgYS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgICAgIGEuZG93bmxvYWQgPSB0aGlzLmlkICsgJy53ZWJtJztcbiAgICAgICAgICAgIGEuY2xpY2soKTtcbiAgICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSByYXcgQmxvYiBmaWxlLiBNZXRob2RzIHByZXZpZXcsIGRvd25sb2FkLCB1cGxvYWRBc0JpbmFyeSBhbmQgdXBsb2FkQXNNdWx0aXBhcnRmaWxlIHVzZSB0aGlzIHNhbWUgZmlsZSB0byBwZXJmb3JtIHRoZWlyIHNwZWNpZmljIGFjdGlvbnMuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBnZXRCbG9iKCk6IEJsb2Ige1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ0NhbGwgXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIGJlZm9yZSBnZXR0aW5nIEJsb2IgZmlsZScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJsb2I7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgYmluYXJ5IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3RcbiAgICAgKi9cbiAgICB1cGxvYWRBc0JpbmFyeShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzQmluYXJ5KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGh0dHAuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHRoaXMuYmxvYik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBsb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gYXMgYSBtdWx0aXBhcnQgZmlsZSBwZXJmb3JtaW5nIGFuIEhUVFAvUE9TVCBvcGVyYXRpb24gdG8gVVJMIGBlbmRwb2ludGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGAuIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBjYW4gYmUgcGFzc2VkIGFzIHNlY29uZCBwYXJhbWV0ZXIuIEZvciBleGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHZhciBoZWFkZXJzID0ge1xuICAgICAqICBcIkNvb2tpZVwiOiBcIiRWZXJzaW9uPTE7IFNraW49bmV3O1wiLFxuICAgICAqICBcIkF1dGhvcml6YXRpb25cIjpcIkJhc2ljIFFXeGhaR3BianB1SUhObGN0WlE9PVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB3aXRoIHRoZSBgaHR0cC5yZXNwb25zZVRleHRgIGZyb20gc2VydmVyIGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggdGhlIGZhaWxlZCBgaHR0cC5zdGF0dXNgIGlmIG5vdDpcbiAgICAgKi9cbiAgICB1cGxvYWRBc011bHRpcGFydGZpbGUoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc011bHRpcGFydGZpbGUoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3Qgc2VuZGFibGUgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgICAgICAgICBzZW5kYWJsZS5hcHBlbmQoJ2ZpbGUnLCB0aGlzLmJsb2IsIHRoaXMuaWQgKyAnLndlYm0nKTtcblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGh0dHAuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBodHRwLnNlbmQoc2VuZGFibGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBvblN0b3BEZWZhdWx0KCk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdG9wcGVkICAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG5cbiAgICAgICAgdGhpcy5ibG9iID0gbmV3IEJsb2IodGhpcy5jaHVua3MsIHsgdHlwZTogJ3ZpZGVvL3dlYm0nIH0pO1xuICAgICAgICB0aGlzLmNodW5rcyA9IFtdO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3U3JjID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5ibG9iKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEO1xuICAgIH1cblxufVxuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyIH0gZnJvbSAnLi9Mb2NhbFJlY29yZGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4vUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBScGNCdWlsZGVyIGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYyc7XG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbi8qKlxuICogRW50cnlwb2ludCBvZiBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKiBVc2UgaXQgdG8gaW5pdGlhbGl6ZSBvYmplY3RzIG9mIHR5cGUgW1tTZXNzaW9uXV0sIFtbUHVibGlzaGVyXV0gYW5kIFtbTG9jYWxSZWNvcmRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgcHJpdmF0ZSBqc29uUnBjQ2xpZW50OiBhbnk7XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlc3Npb246IFNlc3Npb247XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICB3c1VyaTogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VjcmV0ID0gJyc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByZWNvcmRlciA9IGZhbHNlO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgYWR2YW5jZWRDb25maWd1cmF0aW9uOiBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGNvbnNvbGUuaW5mbyhcIidPcGVuVmlkdScgaW5pdGlhbGl6ZWRcIik7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIG5ldyBzZXNzaW9uXG4gICAqL1xuICBpbml0U2Vzc2lvbigpOiBTZXNzaW9uIHtcbiAgICB0aGlzLnNlc3Npb24gPSBuZXcgU2Vzc2lvbih0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uO1xuICB9XG5cblxuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgcHVibGlzaGVyXG4gICAqXG4gICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0RpYWxvZ09wZW5lZGAgZXZlbnQsIG9ubHkgaWYgdGhlIHBvcC11cCBzaG93biBieSB0aGUgYnJvd3NlciB0byByZXF1ZXN0IHBlcm1pc3Npb25zIGZvciB0aGUgY2FtZXJhIGlzIG9wZW5lZC4gWW91IGNhbiB1c2UgdGhpcyBldmVudCB0byBhbGVydCB0aGUgdXNlciBhYm91dCBncmFudGluZyBwZXJtaXNzaW9uc1xuICAgKiBmb3IgeW91ciB3ZWJzaXRlLiBBbiBgYWNjZXNzRGlhbG9nQ2xvc2VkYCBldmVudCB3aWxsIGFsc28gYmUgZGlzcGF0Y2hlZCBhZnRlciB1c2VyIGNsaWNrcyBvbiBcIkFsbG93XCIgb3IgXCJCbG9ja1wiIGluIHRoZSBwb3AtdXAuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NBbGxvd2VkYCBvciBgYWNjZXNzRGVuaWVkYCBldmVudCBvbmNlIGl0IGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3QuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgYSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIGxvY2FsIHN0cmVhbXMgc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50ICBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgUHVibGlzaGVyLlxuICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1B1Ymxpc2hlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1B1Ymxpc2hlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgaW5pdFB1Ymxpc2hlcmAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgYGNvbXBsZXRpb25IYW5kbGVyYCBmdW5jdGlvbiBpcyBjYWxsZWQgYmVmb3JlIHRoZSBQdWJsaXNoZXIgZGlzcGF0Y2hlcyBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYW4gYGFjY2Vzc0RlbmllZGAgZXZlbnRcbiAgICovXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMj8sIHBhcmFtMz8pOiBQdWJsaXNoZXIge1xuXG4gICAgbGV0IHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXM7XG5cbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgIT09ICdmdW5jdGlvbicpKSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9ICg8UHVibGlzaGVyUHJvcGVydGllcz5wYXJhbTIpO1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBhdWRpb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlIDogdW5kZWZpbmVkLFxuICAgICAgICBmcmFtZVJhdGU6IHRoaXMuaXNNZWRpYVN0cmVhbVRyYWNrKHByb3BlcnRpZXMudmlkZW9Tb3VyY2UpID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5mcmFtZVJhdGUgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuZnJhbWVSYXRlIDogdW5kZWZpbmVkKSxcbiAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3Byb3BlcnRpZXMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiAodHlwZW9mIHByb3BlcnRpZXMubWlycm9yICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLm1pcnJvciA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaFZpZGVvIDogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogdGhpcy5pc01lZGlhU3RyZWFtVHJhY2socHJvcGVydGllcy52aWRlb1NvdXJjZSkgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLnJlc29sdXRpb24gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucmVzb2x1dGlvbiA6ICc2NDB4NDgwJyksXG4gICAgICAgIHZpZGVvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgOiB1bmRlZmluZWRcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50KScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiAnNjQweDQ4MCdcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgcHVibGlzaGVyOiBQdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIHRoaXMpO1xuXG4gICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0yO1xuICAgIH0gZWxzZSBpZiAoISFwYXJhbTMpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgIH1cblxuICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgfSk7XG5cbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHB1Ymxpc2hlcik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIGlmICghIXByb3BlcnRpZXMpIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IGxvY2FsIHJlY29yZGVyIGZvciByZWNvcmRpbmcgc3RyZWFtcyBzdHJhaWdodCBhd2F5IGZyb20gdGhlIGJyb3dzZXJcbiAgICogQHBhcmFtIHN0cmVhbSAgU3RyZWFtIHRvIHJlY29yZFxuICAgKi9cbiAgaW5pdExvY2FsUmVjb3JkZXIoc3RyZWFtOiBTdHJlYW0pOiBMb2NhbFJlY29yZGVyIHtcbiAgICByZXR1cm4gbmV3IExvY2FsUmVjb3JkZXIoc3RyZWFtKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdVxuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1LCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBicm93c2VyID0gcGxhdGZvcm0ubmFtZTtcbiAgICBjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0udmVyc2lvbjtcblxuICAgIGlmICgoYnJvd3NlciAhPT0gJ0Nocm9tZScpICYmIChicm93c2VyICE9PSAnQ2hyb21lIE1vYmlsZScpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ0ZpcmVmb3gnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggTW9iaWxlJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94IGZvciBpT1MnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVkaWEgaW5wdXQgZGV2aWNlcyBhdmFpbGFibGUgb24gdGhlIHN5c3RlbS4gWW91IGNhbiBwYXNzIHByb3BlcnR5IGBkZXZpY2VJZGAgb2YgYSBbW0RldmljZV1dIG9iamVjdCBhcyB2YWx1ZSBvZiBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICovXG4gIGdldERldmljZXMoKTogUHJvbWlzZTxEZXZpY2VbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEZXZpY2VbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCkudGhlbigoZGV2aWNlSW5mb3MpID0+IHtcbiAgICAgICAgY29uc3QgZGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICBpZiAoZGV2aWNlSW5mby5raW5kID09PSAnYXVkaW9pbnB1dCcgfHwgZGV2aWNlSW5mby5raW5kID09PSAndmlkZW9pbnB1dCcpIHtcbiAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgfSkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGdldHRpbmcgZGV2aWNlcycsIGVycm9yKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lICE9PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS5uYW1lICE9PSAnRmlyZWZveCcpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVELCAnWW91IGNhbiBvbmx5IHNjcmVlbiBzaGFyZSBpbiBkZXNrdG9wIENocm9tZSBhbmQgRmlyZWZveC4gRGV0ZWN0ZWQgYnJvd3NlcjogJyArIHBsYXRmb3JtLm5hbWUpO1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24pIHtcblxuICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbi5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbklkLCAoc3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWVuYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0U2NyZWVuQ29uc3RyYWludHMoKGVycm9yLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yICYmIGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICg8c3RyaW5nPnRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uKSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZVxuXG4gICAgICAgICAgICAgICAgc2NyZWVuU2hhcmluZ0F1dG8uZ2V0U2NyZWVuSWQoKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICdodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9zY3JlZW4tY2FwdHVyaW5nL2FqaGlmZGRpbWthcGdjaWZnY29kbW1mZGxrbmFoZmZrJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ2luc3RhbGxlZC1kaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQsICdZb3UgbXVzdCBhbGxvdyBhY2Nlc3MgdG8gb25lIHdpbmRvdyBvZiB5b3VyIGRlc2t0b3AnKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHMudmlkZW87XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID0gJ3NjcmVlbic7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLXN0cmluZy1saXRlcmFsXG4gICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvWydkZXZpY2VJZCddID0geyBleGFjdDogcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSB9O1xuICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzdGFydFdzKG9uQ29ubmVjdFN1Y2NlczogKGVycm9yOiBFcnJvcikgPT4gdm9pZCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIGhlYXJ0YmVhdDogNTAwMCxcbiAgICAgIHNlbmRDbG9zZU1lc3NhZ2U6IGZhbHNlLFxuICAgICAgd3M6IHtcbiAgICAgICAgdXJpOiB0aGlzLndzVXJpLFxuICAgICAgICB1c2VTb2NrSlM6IGZhbHNlLFxuICAgICAgICBvbmNvbm5lY3RlZDogb25Db25uZWN0U3VjY2VzLFxuICAgICAgICBvbmRpc2Nvbm5lY3Q6IHRoaXMuZGlzY29ubmVjdENhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0aW5nOiB0aGlzLnJlY29ubmVjdGluZ0NhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0ZWQ6IHRoaXMucmVjb25uZWN0ZWRDYWxsYmFjay5iaW5kKHRoaXMpXG4gICAgICB9LFxuICAgICAgcnBjOiB7XG4gICAgICAgIHJlcXVlc3RUaW1lb3V0OiAxNTAwMCxcbiAgICAgICAgcGFydGljaXBhbnRKb2luZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50Sm9pbmVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRQdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50UHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRVbnB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50TGVmdDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRMZWZ0LmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRFdmljdGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEV2aWN0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdGFydGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdGFydGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RvcHBlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RvcHBlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHNlbmRNZXNzYWdlOiB0aGlzLnNlc3Npb24ub25OZXdNZXNzYWdlLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgaWNlQ2FuZGlkYXRlOiB0aGlzLnNlc3Npb24ucmVjdkljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIG1lZGlhRXJyb3I6IHRoaXMuc2Vzc2lvbi5vbk1lZGlhRXJyb3IuYmluZCh0aGlzLnNlc3Npb24pXG4gICAgICB9XG4gICAgfTtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQgPSBuZXcgUnBjQnVpbGRlci5jbGllbnRzLkpzb25ScGNDbGllbnQoY29uZmlnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBjbG9zZVdzKCk6IHZvaWQge1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5jbG9zZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlbmRSZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCBwYXJhbXM6IGFueSwgY2FsbGJhY2s/KTogdm9pZCB7XG4gICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgY2FsbGJhY2sgPSBwYXJhbXM7XG4gICAgICBwYXJhbXMgPSB7fTtcbiAgICB9XG4gICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyByZXF1ZXN0OiB7bWV0aG9kOlwiJyArIG1ldGhvZCArICdcIiwgcGFyYW1zOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSArICd9Jyk7XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50LnNlbmQobWV0aG9kLCBwYXJhbXMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpc01lZGlhU3RyZWFtVHJhY2sobWVkaWFTb3VyY2U6IGFueSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGlzID0gKCEhbWVkaWFTb3VyY2UgJiZcbiAgICAgIG1lZGlhU291cmNlLmVuYWJsZWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuZW5hYmxlZCA9PT0gJ2Jvb2xlYW4nICYmXG4gICAgICBtZWRpYVNvdXJjZS5pZCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5pZCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLmtpbmQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2Uua2luZCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLmxhYmVsICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmxhYmVsID09PSAnc3RyaW5nJyAmJlxuICAgICAgbWVkaWFTb3VyY2UubXV0ZWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UubXV0ZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5yZWFkeVN0YXRlID09PSAnc3RyaW5nJyk7XG4gICAgcmV0dXJuIGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFdzVXJpKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMud3NVcmk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2V0U2VjcmV0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc2VjcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFJlY29yZGVyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnJlY29yZGVyO1xuICB9XG5cblxuICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICBwcml2YXRlIGRpc2Nvbm5lY3RDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGluZ0NhbGxiYWNrKCk6IHZvaWQge1xuICAgIGNvbnNvbGUud2FybignV2Vic29ja2V0IGNvbm5lY3Rpb24gbG9zdCAocmVjb25uZWN0aW5nKScpO1xuICAgIGlmICh0aGlzLmlzUm9vbUF2YWlsYWJsZSgpKSB7XG4gICAgICB0aGlzLnNlc3Npb24ub25Mb3N0Q29ubmVjdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbGVydCgnQ29ubmVjdGlvbiBlcnJvci4gUGxlYXNlIHJlbG9hZCBwYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVjb25uZWN0ZWRDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCByZWNvbm5lY3RlZCcpO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1Jvb21BdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuc2Vzc2lvbiAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc2Vzc2lvbiBpbnN0YW5jZW9mIFNlc3Npb24pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1Nlc3Npb24gaW5zdGFuY2Ugbm90IGZvdW5kJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgRXZlbnREaXNwYXRjaGVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9FdmVudERpc3BhdGNoZXInO1xuaW1wb3J0IHsgUHVibGlzaGVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvUHVibGlzaGVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbUV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cblxuLyoqXG4gKiBQYWNrcyBsb2NhbCBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgY2FuIHB1Ymxpc2ggaXQgdG8gYSBzZXNzaW9uLiBJbml0aWFsaXplZCB3aXRoIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBQdWJsaXNoZXIgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdFxuICAgICAqL1xuICAgIGFjY2Vzc0FsbG93ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgeW91IGhhdmUgY2FsbGVkIFtbUHVibGlzaGVyLnN1YnNjcmliZVRvUmVtb3RlXV0gd2l0aCB2YWx1ZSBgdHJ1ZWAgb3IgYGZhbHNlYCAoKmZhbHNlKiBieSBkZWZhdWx0KVxuICAgICAqL1xuICAgIGlzU3Vic2NyaWJlZFRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gdG8gd2hpY2ggdGhlIFB1Ymxpc2hlciBiZWxvbmdzXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjsgLy8gSW5pdGlhbGl6ZWQgYnkgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilcblxuICAgIHByaXZhdGUgYWNjZXNzRGVuaWVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBwcml2YXRlIG9wZW52aWR1OiBPcGVuVmlkdSkge1xuICAgICAgICBzdXBlcihuZXcgU3RyZWFtKCghIW9wZW52aWR1LnNlc3Npb24pID8gb3BlbnZpZHUuc2Vzc2lvbiA6IG5ldyBTZXNzaW9uKG9wZW52aWR1KSwgeyBwdWJsaXNoZXJQcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLCBtZWRpYUNvbnN0cmFpbnRzOiB7fSB9KSwgdGFyZ0VsKTtcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZC1ieS1kaXNjb25uZWN0JywgKHJlYXNvbjogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgdGhpcy5zdHJlYW0sIHJlYXNvbik7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIGF1ZGlvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoQXVkaW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmF1ZGlvRW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBoYXMgXCIgKyAodmFsdWUgPyAncHVibGlzaGVkJyA6ICd1bnB1Ymxpc2hlZCcpICsgJyBpdHMgYXVkaW8gc3RyZWFtJyk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaFZpZGVvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldFdlYlJ0Y1BlZXIoKS52aWRlb0VuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogQ2FsbCB0aGlzIG1ldGhvZCBiZWZvcmUgW1tTZXNzaW9uLnB1Ymxpc2hdXSB0byBzdWJzY3JpYmUgdG8geW91ciBQdWJsaXNoZXIncyByZW1vdGUgc3RyZWFtIGluc3RlYWQgb2YgdXNpbmcgdGhlIGxvY2FsIHN0cmVhbSwgYXMgYW55IG90aGVyIHVzZXIgd291bGQgZG8uXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9SZW1vdGUodmFsdWU/OiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHZhbHVlID0gKHZhbHVlICE9PSB1bmRlZmluZWQpID8gdmFsdWUgOiB0cnVlO1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlZFRvUmVtb3RlID0gdmFsdWU7XG4gICAgICAgIHRoaXMuc3RyZWFtLnN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWUpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICBzdXBlci5vbih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1DcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLm9uKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBlcnJvckNhbGxiYWNrID0gKG9wZW5WaWR1RXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc0NhbGxiYWNrID0gKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmlzTWVkaWFTdHJlYW1UcmFjayh0aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjaygoPE1lZGlhU3RyZWFtVHJhY2s+dGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuaXNNZWRpYVN0cmVhbVRyYWNrKHRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBBcHBseSBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyBhbmQgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW9cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZW5hYmxlZCA9ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuXG4gICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5maXJzdFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZVZpZGVvRWxlbWVudCh0aGlzLmZpcnN0VmlkZW9FbGVtZW50LnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+dGhpcy5wcm9wZXJ0aWVzLmluc2VydE1vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihjb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpIHx8IHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQgPSAoKGNvbnN0cmFpbnRzLmF1ZGlvID09PSB1bmRlZmluZWQpID8gdHJ1ZSA6IGNvbnN0cmFpbnRzLmF1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW86IGNvbnN0cmFpbnRzLnZpZGVvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuTk9fSU5QVVRfU09VUkNFX1NFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlByb3BlcnRpZXMgJ2F1ZGlvU291cmNlJyBhbmQgJ3ZpZGVvU291cmNlJyBjYW5ub3QgYmUgc2V0IHRvIGZhbHNlIG9yIG51bGwgYXQgdGhlIHNhbWUgdGltZSB3aGVuIGNhbGxpbmcgJ09wZW5WaWR1LmluaXRQdWJsaXNoZXInXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZVNlc3Npb24oc2Vzc2lvbjogU2Vzc2lvbik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lZS5nZXRMaXN0ZW5lcnMoJ3N0cmVhbVBsYXlpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ09wZW5lZCcsIFtdKTtcbiAgICAgICAgfSwgd2FpdFRpbWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lOiBudW1iZXIsIHdhaXRUaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQpO1xuICAgICAgICBpZiAoKERhdGUubm93KCkgLSBzdGFydFRpbWUpID4gd2FpdFRpbWUpIHtcbiAgICAgICAgICAgIC8vIFBlcm1pc3Npb24gZGlhbG9nIHdhcyBzaG93biBhbmQgbm93IGlzIGNsb3NlZFxuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2FjY2Vzc0RpYWxvZ0Nsb3NlZCcsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgT2JqTWFwIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT2JqTWFwJztcbmltcG9ydCB7IFNlc3Npb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU2Vzc2lvbk9wdGlvbnMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbkV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvbkV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFJlY29yZGluZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFNpZ25hbEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSB2aWRlbyBjYWxsLiBJdCBjYW4gYWxzbyBiZSBzZWVuIGFzIGEgdmlkZW9jb25mZXJlbmNlIHJvb20gd2hlcmUgbXVsdGlwbGUgdXNlcnMgY2FuIGNvbm5lY3QuXG4gKiBQYXJ0aWNpcGFudHMgd2hvIHB1Ymxpc2ggdGhlaXIgdmlkZW9zIHRvIGEgc2Vzc2lvbiBjYW4gYmUgc2VlbiBieSB0aGUgcmVzdCBvZiB1c2VycyBjb25uZWN0ZWQgdG8gdGhhdCBzcGVjaWZpYyBzZXNzaW9uLlxuICogSW5pdGlhbGl6ZWQgd2l0aCBbW09wZW5WaWR1LmluaXRTZXNzaW9uXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXNzaW9uIGltcGxlbWVudHMgRXZlbnREaXNwYXRjaGVyIHtcblxuICAgIC8qKlxuICAgICAqIExvY2FsIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24uIFRoaXMgb2JqZWN0IGlzIGRlZmluZWQgb25seSBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBleGVjdXRlZCwgYW5kIGNhbiBiZSByZXRyaWV2ZWQgc3Vic2NyaWJpbmcgdG8gYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgU2Vzc2lvblxuICAgICAqL1xuICAgIHNlc3Npb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ29sbGVjdGlvbiBvZiBhbGwgU3RyZWFtTWFuYWdlcnMgb2YgdGhpcyBTZXNzaW9uIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSlcbiAgICAgKi9cbiAgICBzdHJlYW1NYW5hZ2VyczogU3RyZWFtTWFuYWdlcltdID0gW107XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBPYmpNYXA8Ym9vbGVhbj4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVDb25uZWN0aW9uczogT2JqTWFwPENvbm5lY3Rpb24+ID0ge307XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PjtcbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnkpOiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0cyB0byB0aGUgc2Vzc2lvbiB1c2luZyBgdG9rZW5gLiBQYXJhbWV0ZXIgYG1ldGFkYXRhYCBhbGxvd3MgeW91IHRvIHBhc3MgZXh0cmEgZGF0YSB0byBzaGFyZSB3aXRoIG90aGVyIHVzZXJzIHdoZW5cbiAgICAgKiB0aGV5IHJlY2VpdmUgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LiBUaGUgc3RydWN0dXJlIG9mIGBtZXRhZGF0YWAgc3RyaW5nIGlzIHVwIHRvIHlvdSAobWF5YmUgc29tZSBzdGFuZGFyaXplZCBmb3JtYXRcbiAgICAgKiBhcyBKU09OIG9yIFhNTCBpcyBhIGdvb2QgaWRlYSksIHRoZSBvbmx5IHJlc3RyaWN0aW9uIGlzIGEgbWF4aW11bSBsZW5ndGggb2YgMTAwMDAgY2hhcnMuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGFkYXRhIGlzIG5vdCBjb25zaWRlcmVkIHNlY3VyZSwgYXMgaXQgaXMgZ2VuZXJhdGVkIGluIHRoZSBjbGllbnQgc2lkZS4gVG8gcGFzcyBzZWN1cml6ZWQgZGF0YSwgYWRkIGl0IGFzIGEgcGFyYW1ldGVyIGluIHRoZVxuICAgICAqIHRva2VuIGdlbmVyYXRpb24gb3BlcmF0aW9uICh0aHJvdWdoIHRoZSBBUEkgUkVTVCwgb3BlbnZpZHUtamF2YS1jbGllbnQgb3Igb3BlbnZpZHUtbm9kZS1jbGllbnQpLlxuICAgICAqXG4gICAgICogT25seSBhZnRlciB0aGUgcmV0dXJuZWQgUHJvbWlzZSBpcyBzdWNjZXNzZnVsbHkgcmVzb2x2ZWQgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBvYmplY3Qgd2lsbCBiZSBhdmFpbGFibGUgYW5kIHByb3Blcmx5IGRlZmluZWQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGZpcnN0IGRpc3BhdGNoIG9uZSBvciBtb3JlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzIHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZDpcbiAgICAgKiAtIEZpcnN0IG9uZSBmb3IgeW91ciBvd24gbG9jYWwgQ29ubmVjdGlvbiBvYmplY3QsIHNvIHlvdSBjYW4gcmV0cmlldmUgW1tTZXNzaW9uLmNvbm5lY3Rpb25dXSBwcm9wZXJ0eS5cbiAgICAgKiAtIFRoZW4gb25lIGZvciBlYWNoIHJlbW90ZSBDb25uZWN0aW9uIHByZXZpb3VzbHkgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uLCBpZiBhbnkuIEFueSBvdGhlciByZW1vdGUgdXNlciBjb25uZWN0aW5nIHRvIHRoZSBTZXNzaW9uIGFmdGVyIHlvdSBoYXZlXG4gICAgICogc3VjY2Vzc2Z1bGx5IGNvbm5lY3RlZCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50IHdoZW4gdGhleSBkbyBzby5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBmb3IgZWFjaCByZW1vdGUgYWN0aXZlIFtbUHVibGlzaGVyXV0gdGhhdCB3YXMgYWxyZWFkeSBzdHJlYW1pbmdcbiAgICAgKiB3aGVuIGNvbm5lY3RpbmcsIGp1c3QgYWZ0ZXIgZGlzcGF0Y2hpbmcgYWxsIHJlbW90ZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gYW5kIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlIHRvIHdoaWNoIHlvdSBtdXN0IHN1YnNjcmliZSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSB0aGUgY29ubmVjdGlvbiB0byB0aGUgU2Vzc2lvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICpcbiAgICAgKi9cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIW1ldGFkYXRhID8gdGhpcy5zdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YSkgOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0QXV4KHRva2VuKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkJST1dTRVJfTk9UX1NVUFBPUlRFRCwgJ0Jyb3dzZXIgJyArIHBsYXRmb3JtLm5hbWUgKyAnICcgKyBwbGF0Zm9ybS52ZXJzaW9uICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCB0byBhdm9pZCB0aGlzIGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgYWxsIHRoZSBTdWJzY3JpYmVyIG9iamVjdHMgeW91cnNlbGYuXG4gICAgICogU2VlIFtbU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGVyZSBpcyBhIFtbUHVibGlzaGVyXV0gb2JqZWN0IHB1Ymxpc2hpbmcgdG8gdGhlIHNlc3Npb24uXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgc3RvcCBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIGlmIHlvdSB3YW50IHRvIGNsZWFuIHRoZSBQdWJsaXNoZXIgb2JqZWN0IG9uIHlvdXIgb3duIG9yIHJlLXB1Ymxpc2ggaXQgaW4gYSBkaWZmZXJlbnQgU2Vzc2lvbiAodG8gZG8gc28gaXQgaXMgYSBtYW5kYXRvcnkgcmVxdWlyZW1lbnQgdG8gY2FsbCBgU2Vzc2lvbi51bnB1Ymxpc2goKWBcbiAgICAgKiBvci9hbmQgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBpbiB0aGUgcHJldmlvdXMgc2Vzc2lvbikuIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBkaXNjb25uZWN0ZWQgcGFydGljaXBhbnQgd2FzIHB1Ymxpc2hpbmcuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBpbiBhbnkgY2FzZS4gU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKi9cbiAgICBkaXNjb25uZWN0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxlYXZlKGZhbHNlLCAnZGlzY29ubmVjdCcpO1xuICAgIH1cblxuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZXMgdG8gYSBgc3RyZWFtYCwgYWRkaW5nIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCB0byBET00gd2l0aCBgc3Vic2NyaWJlclByb3BlcnRpZXNgIHNldHRpbmdzLiBUaGlzIG1ldGhvZCBpcyB1c3VhbGx5IGNhbGxlZCBpbiB0aGUgY2FsbGJhY2sgb2YgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIHJlbW90ZSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc3RyZWFtIFN0cmVhbSBvYmplY3QgdG8gc3Vic2NyaWJlIHRvXG4gICAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tTdWJzY3JpYmVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgU3Vic2NyaWJlci5cbiAgICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1N1YnNjcmliZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24pXG4gICAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYHN1YnNjcmliZWAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgICAqL1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMz86ICgoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSB8IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBwYXJhbTQ/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkpOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgbGV0IHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzID0ge307XG4gICAgICAgIGlmICghIXBhcmFtMyAmJiB0eXBlb2YgcGFyYW0zICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcGFyYW0zLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlID09PSAnc3RyaW5nJykgPyBWaWRlb0luc2VydE1vZGVbcGFyYW0zLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogKHR5cGVvZiBwYXJhbTMuc3Vic2NyaWJlVG9BdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gOiB0cnVlLFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvVmlkZW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvIDogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb0F1ZGlvOiB0cnVlLFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvVmlkZW86IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gICAgICAgIGlmICghIXBhcmFtMyAmJiAodHlwZW9mIHBhcmFtMyA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgICAgICB9IGVsc2UgaWYgKCEhcGFyYW00KSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtNDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJpbmcgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgc3RyZWFtLnN1YnNjcmliZSgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdTdWJzY3JpYmVkIGNvcnJlY3RseSB0byAnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qgc3Vic2NyaWJlciA9IG5ldyBTdWJzY3JpYmVyKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyk7XG4gICAgICAgIGlmICghIXN1YnNjcmliZXIudGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgc3RyZWFtLnN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KHN1YnNjcmliZXIudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT5wcm9wZXJ0aWVzLmluc2VydE1vZGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdWJzY3JpYmVyO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW1Nlc3Npb24uc3Vic2NyaWJlXV1cbiAgICAgKi9cbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFN1YnNjcmliZXI+O1xuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBQcm9taXNlPFN1YnNjcmliZXI+O1xuXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzPzogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBQcm9taXNlPFN1YnNjcmliZXI+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPFN1YnNjcmliZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgbGV0IHN1YnNjcmliZXI6IFN1YnNjcmliZXI7XG5cbiAgICAgICAgICAgIGNvbnN0IGNhbGxiYWNrID0gKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShzdWJzY3JpYmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAoISFwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyID0gdGhpcy5zdWJzY3JpYmUoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVbnN1YnNjcmliZXMgZnJvbSBgc3Vic2NyaWJlcmAsIGF1dG9tYXRpY2FsbHkgcmVtb3ZpbmcgaXRzIGFzc29jaWF0ZWQgSFRNTCB2aWRlbyBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50IGZvciBlYWNoIHZpZGVvIGFzc29jaWF0ZWQgdG8gaXQgdGhhdCB3YXMgcmVtb3ZlZCBmcm9tIERPTS5cbiAgICAgKiBPbmx5IHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IHJlbW92ZWRcbiAgICAgKlxuICAgICAqIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZVxuICAgICAqL1xuICAgIHVuc3Vic2NyaWJlKHN1YnNjcmliZXI6IFN1YnNjcmliZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbklkID0gc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQ7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliaW5nIGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICd1bnN1YnNjcmliZUZyb21WaWRlbycsXG4gICAgICAgICAgICB7IHNlbmRlcjogc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgfSxcbiAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgdW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ1Vuc3Vic2NyaWJlZCBjb3JyZWN0bHkgZnJvbSAnICsgY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2hlcyB0byB0aGUgU2Vzc2lvbiB0aGUgUHVibGlzaGVyIG9iamVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgdXBvbiBzdWNjZXNzZnVsIHRlcm1pbmF0aW9uIG9mIHRoaXMgbWV0aG9kLiBTZWUgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgbG9jYWwgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBvbmNlIHRoZSBtZWRpYSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHNvIHRoZXkgY2FuIHN1YnNjcmliZSB0byBpdC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHB1Ymxpc2hlciB3YXMgc3VjY2Vzc2Z1bGx5IHB1Ymxpc2hlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcik6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBwdWJsaXNoZXIuc2Vzc2lvbiA9IHRoaXM7XG4gICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnNlc3Npb24gPSB0aGlzO1xuXG4gICAgICAgICAgICBpZiAoIXB1Ymxpc2hlci5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgTk9UIGJlZW4gY2FsbGVkXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZFN0cmVhbShwdWJsaXNoZXIuc3RyZWFtKTtcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gJ1Nlc3Npb24udW5wdWJsaXNoKFB1Ymxpc2hlciknIGhhcyBiZWVuIGNhbGxlZC4gTXVzdCBpbml0aWFsaXplIGFnYWluIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZFN0cmVhbShwdWJsaXNoZXIuc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5yZWVzdGFibGlzaFN0cmVhbVBsYXlpbmdFdmVudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5wdWJsaXNoZXMgZnJvbSB0aGUgU2Vzc2lvbiB0aGUgUHVibGlzaGVyIG9iamVjdC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGlzIFB1Ymxpc2hlclxuICAgICAqIChvbmx5IHRob3NlIHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3VyIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyB0aGUgU3Vic2NyaWJlciBvYmplY3Qgb24geW91ciBvd24uXG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKi9cbiAgICB1bnB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzdHJlYW0gPSBwdWJsaXNoZXIuc3RyZWFtO1xuXG4gICAgICAgIGlmICghc3RyZWFtLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG51bGwnLCBzdHJlYW0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKHN0cmVhbS5jb25uZWN0aW9uICE9PSB0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG5vdCB5b3VyIGxvY2FsIENvbm5lY3Rpb24uJyArXG4gICAgICAgICAgICAgICAgXCJPbmx5IG1vZGVyYXRvcnMgY2FuIGZvcmNlIHVucHVibGlzaCBvbiByZW1vdGUgU3RyZWFtcyB2aWEgJ2ZvcmNlVW5wdWJsaXNoJyBtZXRob2RcIiwgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnB1Ymxpc2hpbmcgbG9jYWwgbWVkaWEgKCcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgKyAnKScpO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCd1bnB1Ymxpc2hWaWRlbycsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdNZWRpYSB1bnB1Ymxpc2hlZCBjb3JyZWN0bHknKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBkZWxldGUgc3RyZWFtLmNvbm5lY3Rpb24uc3RyZWFtO1xuXG4gICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCBwdWJsaXNoZXIsICdzdHJlYW1EZXN0cm95ZWQnLCBwdWJsaXNoZXIuc3RyZWFtLCAndW5wdWJsaXNoJyk7XG4gICAgICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlbmRzIG9uZSBzaWduYWwuIGBzaWduYWxgIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBvcHRpb25hbCBwcm9wZXJ0aWVzOlxuICAgICAqIGBgYGpzb25cbiAgICAgKiB7ZGF0YTpzdHJpbmcsIHRvOkNvbm5lY3Rpb25bXSwgdHlwZTpzdHJpbmd9XG4gICAgICogYGBgXG4gICAgICogQWxsIHVzZXJzIHN1YnNjcmliZWQgdG8gdGhhdCBzaWduYWwgKGBzZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIC4uLilgIG9yIGBzZXNzaW9uLm9uKCdzaWduYWwnLCAuLi4pYCBmb3IgYWxsIHNpZ25hbHMpIGFuZCB3aG9zZSBDb25uZWN0aW9uIG9iamVjdHMgYXJlIGluIGB0b2AgYXJyYXkgd2lsbCByZWNlaXZlIGl0LiBUaGVpciBsb2NhbFxuICAgICAqIFNlc3Npb24gb2JqZWN0cyB3aWxsIGRpc3BhdGNoIGEgYHNpZ25hbGAgb3IgYHNpZ25hbDp0eXBlYCBldmVudC4gU2VlIFtbU2lnbmFsRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSBtZXNzYWdlIHN1Y2Nlc3NmdWxseSByZWFjaGVkIG9wZW52aWR1LXNlcnZlciBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90LiBfVGhpcyBkb2Vzbid0XG4gICAgICogbWVhbiB0aGF0IG9wZW52aWR1LXNlcnZlciBjb3VsZCByZXNlbmQgdGhlIG1lc3NhZ2UgdG8gYWxsIHRoZSBsaXN0ZWQgcmVjZWl2ZXJzLl9cbiAgICAgKi9cbiAgICAvKiB0c2xpbnQ6ZGlzYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuICAgIHNpZ25hbChzaWduYWw6IFNpZ25hbE9wdGlvbnMpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBzaWduYWxNZXNzYWdlID0ge307XG5cbiAgICAgICAgICAgIGlmIChzaWduYWwudG8gJiYgc2lnbmFsLnRvLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uSWRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgICAgICAgICAgc2lnbmFsLnRvLmZvckVhY2goY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25JZHMucHVzaChjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndG8nXSA9IGNvbm5lY3Rpb25JZHM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsnZGF0YSddID0gc2lnbmFsLmRhdGEgPyBzaWduYWwuZGF0YSA6ICcnO1xuICAgICAgICAgICAgc2lnbmFsTWVzc2FnZVsndHlwZSddID0gc2lnbmFsLnR5cGUgPyBzaWduYWwudHlwZSA6ICcnO1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdzZW5kTWVzc2FnZScsIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBKU09OLnN0cmluZ2lmeShzaWduYWxNZXNzYWdlKVxuICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyogdHNsaW50OmVuYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcblxuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGVuYWJsZSBoYXJrICdzcGVha2luZycgZXZlbnQgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhc3RyLnNwZWVjaEV2ZW50ICYmIHN0ci5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZW5hYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGVuYWJsZSBoYXJrIGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuXG4gICAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAgICAgdGhpcy5lZS5yZW1vdmVBbGxMaXN0ZW5lcnModHlwZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVlLm9mZih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcywgZGlzYWJsYWUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICEhc3RyLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRKb2luZWQocmVzcG9uc2U6IENvbm5lY3Rpb25PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIC8vIENvbm5lY3Rpb24gc2hvdWxkbid0IGV4aXN0XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihyZXNwb25zZS5pZCwgJycpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQ29ubmVjdGlvbiAnICsgcmVzcG9uc2UuaWQgKyAnIGFscmVhZHkgZXhpc3RzIGluIGNvbm5lY3Rpb25zIGxpc3QnKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW3Jlc3BvbnNlLmlkXSA9IGNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRMZWZ0KG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLm5hbWUgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW0uc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBjb25uZWN0aW9uLCBtc2cucmVhc29uKV0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRQdWJsaXNoZWQocmVzcG9uc2U6IENvbm5lY3Rpb25PcHRpb25zKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgYWZ0ZXJDb25uZWN0aW9uRm91bmQgPSAoY29ubmVjdGlvbikgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdKSB7XG4gICAgICAgICAgICAgICAgLy8gQXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiBzdHJlYW0uc3Vic2NyaWJlKCkgaW4gXCJvblBhcnRpY2lwYW50UHVibGlzaGVkXCIgYW5kIGluIFwiam9pblJvb21cIiBycGMgY2FsbGJhY2tcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGNvbmRpdGlvbiBpcyBmYWxzZSBpZiBvcGVudmlkdS1zZXJ2ZXIgc2VuZHMgXCJwYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGV2ZW50IHRvIGEgc3Vic2NyaWJlciBwYXJ0aWNpcGFudCB0aGF0IGhhc1xuICAgICAgICAgICAgICAgIC8vIGFscmVhZHkgc3Vic2NyaWJlZCB0byBjZXJ0YWluIHN0cmVhbSBpbiB0aGUgY2FsbGJhY2sgb2YgXCJqb2luUm9vbVwiIG1ldGhvZFxuXG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIGNvbm5lY3Rpb24uc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEdldCB0aGUgZXhpc3RpbmcgQ29ubmVjdGlvbiBjcmVhdGVkIG9uICdvblBhcnRpY2lwYW50Sm9pbmVkJyBmb3JcbiAgICAgICAgLy8gZXhpc3RpbmcgcGFydGljaXBhbnRzIG9yIGNyZWF0ZSBhIG5ldyBvbmUgZm9yIG5ldyBwYXJ0aWNpcGFudHNcbiAgICAgICAgbGV0IGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG4gICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihyZXNwb25zZS5pZCwgXCJSZW1vdGUgY29ubmVjdGlvbiAnXCIgKyByZXNwb25zZS5pZCArIFwiJyB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb24gPT4ge1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBleGlzdGluZyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IGNvbjtcbiAgICAgICAgICAgICAgICByZXNwb25zZS5tZXRhZGF0YSA9IGNvbi5kYXRhO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ub3B0aW9ucyA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uaW5pdFJlbW90ZVN0cmVhbXMocmVzcG9uc2Uuc3RyZWFtcyk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBuZXcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFVucHVibGlzaGVkKG1zZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgbXNnLm5hbWUgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWxldGluZyB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oc3RyZWFtSWQpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRFdmljdGVkKG1zZyk6IHZvaWQge1xuICAgICAgICAvKnRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cubmFtZSwgJ1JlbW90ZSBjb25uZWN0aW9uICcgKyBtc2cubmFtZSArIFwiIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudExlZnQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgc3RyZWFtLCAnZm9yY2VEaXNjb25uZWN0Jyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW0uc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBjb25uZWN0aW9uLCAnZm9yY2VEaXNjb25uZWN0JyldKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pOyovXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTmV3TWVzc2FnZShtc2cpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcblxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmZyb20sIFwiQ29ubmVjdGlvbiAnXCIgKyBtc2cuZnJvbSArIFwiJyB1bmtub3cgd2hlbiAnb25OZXdNZXNzYWdlJy4gRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiBcIlxuICAgICAgICAgICAgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkgKyAnLiBFeGlzdGluZyBsb2NhbCBjb25uZWN0aW9uOiAnICsgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZClcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3NpZ25hbCcsIFtuZXcgU2lnbmFsRXZlbnQodGhpcywgbXNnLnR5cGUsIG1zZy5kYXRhLCBjb25uZWN0aW9uKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWw6JyArIG1zZy50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKG1zZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSB7XG4gICAgICAgICAgICBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IG1zZy5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBtc2cuc2RwTUxpbmVJbmRleFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24obXNnLmVuZHBvaW50TmFtZSwgJ0Nvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBlbmRwb2ludCAnICsgbXNnLmVuZHBvaW50TmFtZSArICcuIEljZSBjYW5kaWRhdGUgd2lsbCBiZSBpZ25vcmVkOiAnICsgY2FuZGlkYXRlKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGFkZGluZyBjYW5kaWRhdGUgZm9yICcgKyBzdHJlYW0uc3RyZWFtSWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU2Vzc2lvbkNsb3NlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5pbmZvKCdTZXNzaW9uIGNsb3NlZDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuICAgICAgICBjb25zdCBzID0gbXNnLnJvb207XG4gICAgICAgIGlmIChzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uLWNsb3NlZCcsIFt7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbjogc1xuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIHVuZGVmaW5lZCBvbiBzZXNzaW9uIGNsb3NlZCcsIG1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25Mb3N0Q29ubmVjdGlvbigpOiB2b2lkIHtcblxuICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBTZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKHBhcmFtcyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIGNvbnN0IGVyciA9IHBhcmFtcy5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOicsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsZWF2ZShmb3JjZWQ6IGJvb2xlYW4sIHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgZm9yY2VkID0gISFmb3JjZWQ7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnTGVhdmluZyBTZXNzaW9uIChmb3JjZWQ9JyArIGZvcmNlZCArICcpJyk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCAmJiAhZm9yY2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnbGVhdmVSb29tJywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgIC8vIERpc3Bvc2UgUHVibGlzaGVyJ3MgIGxvY2FsIHN0cmVhbVxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgUHVibGlzaGVyIG9iamVjdCBkaXNwYXRjaCAnc3RyZWFtRGVzdHJveWVkJyBldmVudCBpZiB0aGUgU3RyZWFtIHdhcyBwdWJsaXNoZWRcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQtYnktZGlzY29ubmVjdCcsIFtyZWFzb25dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBTZXNzaW9uIG9iamVjdCBkaXNwYXRjaCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcgZXZlbnQgKGlmIGl0IGlzIG5vdCBhbHJlYWR5IGRpc3Bvc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMsIHJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICAgICAgICAgIHNlc3Npb25EaXNjb25uZWN0RXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IHdlcmUgbm90IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc3RhcnRXcygoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgam9pblBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiAoISF0b2tlbikgPyB0b2tlbiA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISF0aGlzLm9wdGlvbnMubWV0YWRhdGEgPyB0aGlzLm9wdGlvbnMubWV0YWRhdGEgOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlY3JldDogdGhpcy5vcGVudmlkdS5nZXRTZWNyZXQoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZGVyOiB0aGlzLm9wZW52aWR1LmdldFJlY29yZGVyKCksXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnam9pblJvb20nLCBqb2luUGFyYW1zLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSBsb2NhbCBDb25uZWN0aW9uIG9iamVjdCB3aXRoIHZhbHVlcyByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmRhdGEgPSByZXNwb25zZS5tZXRhZGF0YTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgcmVtb3RlIENvbm5lY3Rpb25zIHdpdGggdmFsdWUgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXZlbnRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uczogbmV3IEFycmF5PENvbm5lY3Rpb24+KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbXM6IG5ldyBBcnJheTxTdHJlYW0+KClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nUGFydGljaXBhbnRzOiBDb25uZWN0aW9uT3B0aW9uc1tdID0gcmVzcG9uc2UudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdQYXJ0aWNpcGFudHMuZm9yRWFjaChwYXJ0aWNpcGFudCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCBwYXJ0aWNpcGFudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLnB1c2goY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5wdXNoKGNvbm5lY3Rpb24uc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3duICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgdGhpcy5jb25uZWN0aW9uLCAnJyldKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGV4aXN0aW5nIGNvbm5lY3Rpb24gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMuZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdzdHJlYW1DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBhY3RpdmUgc3RyZWFtIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMuZm9yRWFjaChzdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGE6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0YWRhdGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPT09IGNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGxvY2FsIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmVtb3RlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZywgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbm5lY3Rpb24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSByZW1vdGUgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgIHJlc29sdmUoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBjb25uZWN0aW9uIG5vdCBmb3VuZC4gUmVqZWN0IHdpdGggT3BlblZpZHVFcnJvclxuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHRva2VuKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSA8c3RyaW5nPnVybC5zZWFyY2hQYXJhbXMuZ2V0KCdzZXNzaW9uSWQnKTtcbiAgICAgICAgY29uc3Qgc2VjcmV0ID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3NlY3JldCcpO1xuICAgICAgICBjb25zdCByZWNvcmRlciA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyZWNvcmRlcicpO1xuXG4gICAgICAgIGlmICghIXNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcmVjb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucmVjb3JkZXIgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vcGVudmlkdS53c1VyaSA9ICd3c3M6Ly8nICsgdXJsLmhvc3QgKyAnL29wZW52aWR1JztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgT3V0Ym91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvT3V0Ym91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFdlYlJ0Y1N0YXRzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cyc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG5pbXBvcnQgKiBhcyBrdXJlbnRvVXRpbHMgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by11dGlscy1qcyc7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBzdHJlYW1cbiAgICAgKi9cbiAgICBzdHJlYW1JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogYFwiQ0FNRVJBXCJgIG9yIGBcIlNDUkVFTlwiYC4gKnVuZGVmaW5lZCogaWYgc3RyZWFtIGlzIGF1ZGlvLW9ubHlcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbU1hbmFnZXIgb2JqZWN0IChbW1B1Ymxpc2hlcl1dIG9yIFtbU3Vic2NyaWJlcl1dKSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGlzIHN0cmVhbSBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcjogU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIHByaXZhdGUgd2ViUnRjUGVlcjogYW55O1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5ib3VuZFN0cmVhbU9wdHM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3BlZWNoRXZlbnQ6IGFueTtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlc3Npb246IFNlc3Npb24sIG9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zIHwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIHwge30pIHtcblxuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCdpZCcpKSB7XG4gICAgICAgICAgICAvLyBJbmJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBTdWJzY3JpYmVyXG4gICAgICAgICAgICB0aGlzLmluYm91bmRTdHJlYW1PcHRzID0gPEluYm91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9ICdTQ1JFRU4nO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ1NDUkVFTic7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NBTUVSQSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSAnTUlDUk8nO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnR5cGVPZlZpZGVvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaXNTZW5kQXVkaW8oKTtcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmlzU2VuZFZpZGVvKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVlLm9uKCdtZWRpYXN0cmVhbS11cGRhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnVwZGF0ZU1lZGlhU3RyZWFtKHRoaXMubWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnVmlkZW8gc3JjT2JqZWN0IFsnICsgdGhpcy5tZWRpYVN0cmVhbSArICddIHVwZGF0ZWQgaW4gc3RyZWFtIFsnICsgdGhpcy5zdHJlYW1JZCArICddJyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRNZWRpYVN0cmVhbSgpOiBNZWRpYVN0cmVhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCkge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbWVkaWFzdHJlYW0tdXBkYXRlZCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRXZWJSdGNQZWVyKCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wZWVyQ29ubmVjdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLmhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1BlZXJTZW5kKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHVzZXJNZWRpYUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaXNTZW5kVmlkZW8oKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgb3B0aW9uczogYW55ID0ge1xuICAgICAgICAgICAgICAgIHZpZGVvU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzQ2FsbGJhY2sgPSAoZXJyb3IsIHNkcE9mZmVyUGFyYW0sIHdwKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhwdWJsaXNoKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTZW5kaW5nIFNEUCBvZmZlciB0byBwdWJsaXNoIGFzICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncHVibGlzaFZpZGVvJywge1xuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbSxcbiAgICAgICAgICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHRoaXMuaXNTZW5kVmlkZW8oKSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86ICgodGhpcy5pc1NlbmRWaWRlbygpKSA/ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJykgOiAnJyksXG4gICAgICAgICAgICAgICAgICAgIGZyYW1lUmF0ZTogISF0aGlzLmZyYW1lUmF0ZSA/IHRoaXMuZnJhbWVSYXRlIDogLTFcbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdFcnJvciBvbiBwdWJsaXNoVmlkZW86ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzU2RwQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiByZW1vdGUgbm93IHdlIGNhbiBzZXQgdGhlIHNyY09iamVjdCB2YWx1ZSBvZiB2aWRlbyBlbGVtZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gJ3N0cmVhbVBsYXlpbmcnIGV2ZW50IHdpbGwgYmUgdHJpZ2dlcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0ga3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIuV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGVyciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKHN1Y2Nlc3NDYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IGt1cmVudG9VdGlscy5XZWJSdGNQZWVyLldlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zLCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcihzdWNjZXNzQ2FsbGJhY2spO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbyxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5yZWN2VmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiJ1Nlc3Npb24uc3Vic2NyaWJlKFN0cmVhbSknIGNhbGxlZC4gQ29uc3RyYWludHMgb2YgZ2VuZXJhdGUgU0RQIG9mZmVyXCIsXG4gICAgICAgICAgICAgICAgb2ZmZXJDb25zdHJhaW50cyk7XG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogb2ZmZXJDb25zdHJhaW50c1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc0NhbGxiYWNrID0gKGVycm9yLCBzZHBPZmZlclBhcmFtLCB3cCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTZW5kaW5nIFNEUCBvZmZlciB0byBzdWJzY3JpYmUgdG8gJ1xuICAgICAgICAgICAgICAgICAgICArIHRoaXMuc3RyZWFtSWQsIHNkcE9mZmVyUGFyYW0pO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgncmVjZWl2ZVZpZGVvRnJvbScsIHtcbiAgICAgICAgICAgICAgICAgICAgc2VuZGVyOiB0aGlzLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBzZHBPZmZlcjogc2RwT2ZmZXJQYXJhbVxuICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdFcnJvciBvbiByZWN2VmlkZW9Gcm9tOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NTZHBBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBrdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5XZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZ2VuZXJhdGVPZmZlcihzdWNjZXNzQ2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcHJvY2Vzc1NkcEFuc3dlcihzZHBBbnN3ZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXIsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1Zyh0aGlzLnN0cmVhbUlkICsgJzogc2V0IHBlZXIgY29ubmVjdGlvbiB3aXRoIHJlY3ZkIFNEUCBhbnN3ZXInLCBzZHBBbnN3ZXIpO1xuXG4gICAgICAgICAgICBjb25zdCBzdHJlYW1JZCA9IHRoaXMuc3RyZWFtSWQ7XG4gICAgICAgICAgICBjb25zdCBwZWVyQ29ubmVjdGlvbiA9IHRoaXMud2ViUnRjUGVlci5wZWVyQ29ubmVjdGlvbjtcbiAgICAgICAgICAgIHBlZXJDb25uZWN0aW9uLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlciwgKCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHJlbW90ZSBNZWRpYVN0cmVhbSBvYmplY3QgZXhjZXB0IHdoZW4gbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzTG9jYWwoKSB8fCB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBwZWVyQ29ubmVjdGlvbi5nZXRSZW1vdGVTdHJlYW1zKClbMF07XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1BlZXIgcmVtb3RlIHN0cmVhbScsIHRoaXMubWVkaWFTdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghIXRoaXMubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0gJiYgdGhpcy5zZXNzaW9uLnNwZWFraW5nRXZlbnRzRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgICAgICB9LCBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcih0aGlzLnN0cmVhbUlkICsgJzogRXJyb3Igc2V0dGluZyBTRFAgdG8gdGhlIHBlZXIgY29ubmVjdGlvbjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzID0gbmV3IFdlYlJ0Y1N0YXRzKHRoaXMpO1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RvcFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLndlYlJ0Y1N0YXRzICYmIHRoaXMud2ViUnRjU3RhdHMuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbCgpOiBib29sZWFuIHtcbiAgICAgICAgLy8gaW5ib3VuZCBvcHRpb25zIHVuZGVmaW5lZCBhbmQgb3V0Ym91bmQgb3B0aW9ucyBkZWZpbmVkXG4gICAgICAgIHJldHVybiAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgJiYgISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyk7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGB2aWRlb2AgZWxlbWVudCBwYXJhbWV0ZXIgZGlzcGxheSB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IGFyZVxuICAgICAqIFttYW5hZ2luZyB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd25dKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpXG4gICAgICpcbiAgICAgKiBDYWxsaW5nIHRoaXMgbWV0aG9kIHdpdGggYSB2aWRlbyBhbHJlYWR5IGFkZGVkIHRvIG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgY2F1c2UgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYmVcbiAgICAgKiBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBwcmV2aW91cyBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgdG8gYmUgYXNzb2NpYXRlZCB0byB0aGlzIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIDEgaWYgdGhlIHZpZGVvIHdhc24ndCBhc3NvY2lhdGVkIHRvIGFueSBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqIDAgaWYgdGhlIHZpZGVvIHdhcyBhbHJlYWR5IGFkZGVkIHRvIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXIuIC0xIGlmIHRoZSB2aWRlbyB3YXMgcHJldmlvdXNseSBhc3NvY2lhdGVkIHRvIGFueSBvdGhlclxuICAgICAqIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgb25lIGFuZCBwcm9wZXJseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKi9cbiAgICBhZGRWaWRlb0VsZW1lbnQodmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgLy8gSWYgdGhlIHZpZGVvIGVsZW1lbnQgaXMgYWxyZWFkeSBwYXJ0IG9mIHRoaXMgU3RyZWFtTWFuYWdlciBkbyBub3RoaW5nXG4gICAgICAgIGZvciAoY29uc3QgdiBvZiB0aGlzLnZpZGVvcykge1xuICAgICAgICAgICAgaWYgKHYudmlkZW8gPT09IHZpZGVvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmV0dXJuTnVtYmVyID0gMTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3Muc2xpY2UoKS5yZXZlcnNlKCkuZm9yRWFjaCgoc3RyZWFtTWFuYWdlclZpZGVvLCBpbmRleCwgdmlkZW9zKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgb25jYW5wbGF5IGV2ZW50IGxpc3RlbmVyIChvbmx5IE9wZW5WaWR1IGJyb3dzZXIgb25lLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICAgICAgaWYgKCEhc3RyZWFtTWFuYWdlclZpZGVvLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbW92ZSB2aWRlb3MgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyICh0aG9zZSBnZW5lcmF0ZWQgYnkgcGFzc2luZyBhIHZhbGlkIHRhcmdldEVsZW1lbnQgaW4gT3BlblZpZHUuaW5pdFB1Ymxpc2hlciBhbmQgU2Vzc2lvbi5zdWJzY3JpYmVcbiAgICAgICAgICAgICAgICAvLyBvciB0aG9zZSBjcmVhdGVkIGJ5IFN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KS4gVGhlc2UgYXJlIGFsc28gdGhlIHZpZGVvcyB0aGF0IHRyaWdnZXJlZCBhIHZpZGVvRWxlbWVudENyZWF0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucGFyZW50Tm9kZSEucmVtb3ZlQ2hpbGQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50RGVzdHJveWVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZSh2aWRlb3MubGVuZ3RoIC0gMSAtIGluZGV4LCAxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHNyY09iamVjdCBpbiBhbGwgdmlkZW9zIG1hbmFnZWQgYnkgdGhlIHVzZXJcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwcG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gY2FwdHVyZSBzb21lIGRlc2t0b3Agc2NyZWVuIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBoYXMgYmVlbiBjYWxsZWQgd2l0aCBwcm9wZXJ0aWVzIGB2aWRlb1NvdXJjZWAgYW5kIGBhdWRpb1NvdXJjZWAgb2ZcbiAgICAgKiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBwYXJhbWV0ZXIgYm90aCBzZXQgdG8gKmZhbHNlKiBvciAqbnVsbCpcbiAgICAgKi9cbiAgICBOT19JTlBVVF9TT1VSQ0VfU0VUID0gJ05PX0lOUFVUX1NPVVJDRV9TRVQnLFxuXG4gICAgLyoqXG4gICAgICogU29tZSBtZWRpYSBwcm9wZXJ0eSBvZiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBzdWNoIGFzIGBmcmFtZVJhdGVgIG9yIGByZXNvbHV0aW9uYCBpcyBub3Qgc3VwcG9ydGVkXG4gICAgICogYnkgdGhlIGlucHV0IGRldmljZXMgKHdoZW5ldmVyIGl0IGlzIHBvc3NpYmxlIHRoZXkgYXJlIGF1dG9tYXRpY2FsbHkgYWRqdXN0ZWQgdG8gdGhlIG1vc3Qgc2ltaWxhciB2YWx1ZSkuXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEID0gJ09QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuLyoqXG4gKiBTaW1wbGUgb2JqZWN0IHRvIGlkZW50aWZ5IHJ1bnRpbWUgZXJyb3JzIG9uIHRoZSBjbGllbnQgc2lkZVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHVFcnJvciB7XG5cbiAgICBuYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBIb3cgdGhlIHZpZGVvIHdpbGwgYmUgaW5zZXJ0ZWQgaW4gdGhlIERPTSBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuIFNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dIGFuZCBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXVxuICovXG5leHBvcnQgZW51bSBWaWRlb0luc2VydE1vZGUge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHRhcmdldCBlbGVtZW50IChhcyBuZXh0IHNpYmxpbmcpXG4gICAgICovXG4gICAgQUZURVIgPSAnQUZURVInLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGxhc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgQVBQRU5EID0gJ0FQUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYmVmb3JlIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgcHJldmlvdXMgc2libGluZylcbiAgICAgKi9cbiAgICBCRUZPUkUgPSAnQkVGT1JFJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBmaXJzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBQUkVQRU5EID0gJ1BSRVBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIHJlcGxhY2VzIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUkVQTEFDRSA9ICdSRVBMQUNFJ1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYGNvbm5lY3Rpb25DcmVhdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgY29ubmVjdGlvbkRlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgd2FzIGNyZWF0ZWQgb3IgZGVzdHJveWVkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZvciAnY29ubmVjdGlvbkRlc3Ryb3llZCcgZXZlbnQ6XG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3VyIHRoYXQgbWF5IGJlIHByZXZlbnRlZCBieSBjYWxsaW5nIFtbRXZlbnQucHJldmVudERlZmF1bHRdXVxuICAgICAqL1xuICAgIGNhbmNlbGFibGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0IHRoYXQgZGlzcGF0Y2hlZCB0aGUgZXZlbnRcbiAgICAgKi9cbiAgICB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHR5cGUgb2YgZXZlbnQuIFRoaXMgaXMgdGhlIHNhbWUgc3RyaW5nIHlvdSBwYXNzIGFzIGZpcnN0IHBhcmFtZXRlciB3aGVuIGNhbGxpbmcgbWV0aG9kIGBvbigpYCBvZiBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBbW0V2ZW50RGlzcGF0Y2hlcl1dIGludGVyZmFjZVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIHByaXZhdGUgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvdXI6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvdXIgPSAoKSA9PiB7IH07XG4gICAgICAgIHRoaXMuaGFzQmVlblByZXZlbnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHJlY29yZGluZ1N0YXJ0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGByZWNvcmRpbmdTdG9wcGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIElEIGdlbmVyYXRlZCBpbiBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlY29yZGluZyBuYW1lIHlvdSBzdXBwbGllZCB0byBvcGVudmlkdS1zZXJ2ZXIuIEZvciBleGFtcGxlLCB0byBuYW1lIHlvdXIgcmVjb3JkaW5nIGZpbGUgTVlfUkVDT1JESU5HOlxuICAgICAqIC0gV2l0aCAqKkFQSSBSRVNUKio6IFBPU1QgdG8gYC9hcGkvcmVjb3JkaW5ncy9zdGFydGAgcGFzc2luZyBKU09OIGJvZHkgYHtcInNlc3Npb25cIjpcInNlc3Npb25JZFwiLFwibmFtZVwiOlwiTVlfUkVDT1JESU5HXCJ9YFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LWphdmEtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIE1ZX1JFQ09SRElORylgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKE1ZX1JFQ09SRElORykuYnVpbGQoKSlgXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtbm9kZS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgTVlfUkVDT1JESU5HKWAgb3IgYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgbmV3IFJlY29yZGluZ1Byb3BlcnRpZXMuQnVpbGRlcigpLm5hbWUoTVlfUkVDT1JESU5HKS5idWlsZCgpKWBcbiAgICAgKlxuICAgICAqIElmIG5vIG5hbWUgaXMgc3VwcGxpZWQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSB1bmRlZmluZWQgYW5kIHRoZSByZWNvcmRlZCBmaWxlIHdpbGwgYmUgbmFtZWQgYWZ0ZXIgcHJvcGVydHkgW1tpZF1dXG4gICAgICovXG4gICAgbmFtZT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIGlmIChuYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogeW91IGhhdmUgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogeW91ciBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHRydWUsIHRhcmdldCwgJ3Nlc3Npb25EaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkNhbGxpbmcgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvdXIoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEZvciAnc3RyZWFtRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwidW5wdWJsaXNoXCI6IG1ldGhvZCBgU2Vzc2lvbi51bnB1Ymxpc2goKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogbWV0aG9kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcIm5ldHdvcmtEaXNjb25uZWN0XCI6IHRoZSB1c2VyJ3MgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ3N0cmVhbUNyZWF0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFB1Ymxpc2hlciwgdHlwZTogc3RyaW5nLCBzdHJlYW06IFN0cmVhbSwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgUHVibGlzaGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9jYWwgU3RyZWFtXG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW91ciB1cG9uICdcIiArIHRoaXMudHlwZSArIFwiJyBldmVudCBkaXNwYXRjaGVkIGJ5ICdQdWJsaXNoZXInXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHZpZGVvRWxlbWVudENyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuIFNlZVxuICogW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uLlxuICogLSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSB3aGVuZXZlciBhbiBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWRlb0VsZW1lbnRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGVsZW1lbnQgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBlbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQsIHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiZnVuY3Rpb24gTWFwcGVyKClcbntcbiAgdmFyIHNvdXJjZXMgPSB7fTtcblxuXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKVxuICB7XG4gICAgZm9yKHZhciBrZXkgaW4gc291cmNlcylcbiAgICB7XG4gICAgICB2YXIgc291cmNlID0gc291cmNlc1trZXldO1xuXG4gICAgICBmb3IodmFyIGtleTIgaW4gc291cmNlKVxuICAgICAgICBjYWxsYmFjayhzb3VyY2Vba2V5Ml0pO1xuICAgIH07XG4gIH07XG5cbiAgdGhpcy5nZXQgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBpZHNbaWRdO1xuICB9O1xuXG4gIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcblxuICAgIGRlbGV0ZSBpZHNbaWRdO1xuXG4gICAgLy8gQ2hlY2sgaXQncyBlbXB0eVxuICAgIGZvcih2YXIgaSBpbiBpZHMpe3JldHVybiBmYWxzZX1cblxuICAgIGRlbGV0ZSBzb3VyY2VzW3NvdXJjZV07XG4gIH07XG5cbiAgdGhpcy5zZXQgPSBmdW5jdGlvbih2YWx1ZSwgaWQsIHNvdXJjZSlcbiAge1xuICAgIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHNvdXJjZXNbc291cmNlXSA9IGlkcyA9IHt9O1xuXG4gICAgaWRzW2lkXSA9IHZhbHVlO1xuICB9O1xufTtcblxuXG5NYXBwZXIucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG57XG4gIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGlkLCBzb3VyY2UpO1xuICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICByZXR1cm4gdmFsdWU7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gTWFwcGVyO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBKc29uUnBjQ2xpZW50ICA9IHJlcXVpcmUoJy4vanNvbnJwY2NsaWVudCcpO1xuXG5cbmV4cG9ydHMuSnNvblJwY0NsaWVudCAgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uLycpO1xudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5EYXRlLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiArbmV3IERhdGU7XG59O1xuXG52YXIgUElOR19JTlRFUlZBTCA9IDUwMDA7XG5cbnZhciBSRUNPTk5FQ1RJTkcgPSAnUkVDT05ORUNUSU5HJztcbnZhciBDT05ORUNURUQgPSAnQ09OTkVDVEVEJztcbnZhciBESVNDT05ORUNURUQgPSAnRElTQ09OTkVDVEVEJztcblxudmFyIExvZ2dlciA9IGNvbnNvbGU7XG5cbi8qKlxuICpcbiAqIGhlYXJ0YmVhdDogaW50ZXJ2YWwgaW4gbXMgZm9yIGVhY2ggaGVhcnRiZWF0IG1lc3NhZ2UsXG4gKiBzZW5kQ2xvc2VNZXNzYWdlIDogdHJ1ZSAvIGZhbHNlLCBiZWZvcmUgY2xvc2luZyB0aGUgY29ubmVjdGlvbiwgaXQgc2VuZHMgYSBjbG9zZVNlc3Npb24gbWVzc2FnZVxuICogPHByZT5cbiAqIHdzIDoge1xuICogXHR1cmkgOiBVUkkgdG8gY29ubnRlY3QgdG8sXG4gKiAgdXNlU29ja0pTIDogdHJ1ZSAodXNlIFNvY2tKUykgLyBmYWxzZSAodXNlIFdlYlNvY2tldCkgYnkgZGVmYXVsdCxcbiAqIFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuICogXHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcbiAqIFx0b25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG4gKiBcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbiAqIFx0b25lcnJvciA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGVyZSBpcyBhbiBlcnJvclxuICogfSxcbiAqIHJwYyA6IHtcbiAqIFx0cmVxdWVzdFRpbWVvdXQgOiB0aW1lb3V0IGZvciBhIHJlcXVlc3QsXG4gKiBcdHNlc3Npb25TdGF0dXNDaGFuZ2VkOiBjYWxsYmFjayBtZXRob2QgZm9yIGNoYW5nZXMgaW4gc2Vzc2lvbiBzdGF0dXMsXG4gKiBcdG1lZGlhUmVuZWdvdGlhdGlvbjogbWVkaWFSZW5lZ290aWF0aW9uXG4gKiB9XG4gKiA8L3ByZT5cbiAqL1xuZnVuY3Rpb24gSnNvblJwY0NsaWVudChjb25maWd1cmF0aW9uKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgd3NDb25maWcgPSBjb25maWd1cmF0aW9uLndzO1xuXG4gICAgdmFyIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSAtMTtcblxuICAgIHZhciBwaW5nTmV4dE51bSA9IDA7XG4gICAgdmFyIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgdmFyIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgIHZhciBwaW5nSW50ZXJ2YWw7XG5cbiAgICB2YXIgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgdmFyIG9ucmVjb25uZWN0aW5nID0gd3NDb25maWcub25yZWNvbm5lY3Rpbmc7XG4gICAgdmFyIG9ucmVjb25uZWN0ZWQgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGVkO1xuICAgIHZhciBvbmNvbm5lY3RlZCA9IHdzQ29uZmlnLm9uY29ubmVjdGVkO1xuICAgIHZhciBvbmVycm9yID0gd3NDb25maWcub25lcnJvcjtcblxuICAgIGNvbmZpZ3VyYXRpb24ucnBjLnB1bGwgPSBmdW5jdGlvbihwYXJhbXMsIHJlcXVlc3QpIHtcbiAgICAgICAgcmVxdWVzdC5yZXBseShudWxsLCBcInB1c2hcIik7XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNUSU5HIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBSRUNPTk5FQ1RJTkcpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIFJFQ09OTkVDVElORyBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVElORyBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXR1cyA9IFJFQ09OTkVDVElORztcbiAgICAgICAgaWYgKG9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9ucmVjb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uY29ubmVjdGVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05DT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVzZVBpbmcoKTtcblxuICAgICAgICBpZiAob25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9ORVJST1IgLS0tLS0tLS0tLS1cIik7XG5cbiAgICAgICAgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgICAgIGlmIChvbmVycm9yKSB7XG4gICAgICAgICAgICBvbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKHdzQ29uZmlnKTtcblxuICAgIExvZ2dlci5kZWJ1ZygnQ29ubmVjdGluZyB3ZWJzb2NrZXQgdG8gVVJJOiAnICsgd3NDb25maWcudXJpKTtcblxuICAgIHZhciBycGNCdWlsZGVyT3B0aW9ucyA9IHtcbiAgICAgICAgcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5yZXF1ZXN0VGltZW91dCxcbiAgICAgICAgcGluZ19yZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLmhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0XG4gICAgfTtcblxuICAgIHZhciBycGMgPSBuZXcgUnBjQnVpbGRlcihScGNCdWlsZGVyLnBhY2tlcnMuSnNvblJQQywgcnBjQnVpbGRlck9wdGlvbnMsIHdzLFxuICAgICAgICBmdW5jdGlvbihyZXF1ZXN0KSB7XG5cbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVjZWl2ZWQgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IGNvbmZpZ3VyYXRpb24ucnBjW3JlcXVlc3QubWV0aG9kXTtcblxuICAgICAgICAgICAgICAgIGlmIChmdW5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWV0aG9kIFwiICsgcmVxdWVzdC5tZXRob2QgKyBcIiBub3QgcmVnaXN0ZXJlZCBpbiBjbGllbnRcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyhyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKCdFeGNlcHRpb24gcHJvY2Vzc2luZyByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAobWV0aG9kICE9PSAncGluZycpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVxdWVzdDogbWV0aG9kOicgKyBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgcnBjLmVuY29kZShtZXRob2QsIHBhcmFtcywgZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1I6XCIgKyBlcnJvci5tZXNzYWdlICsgXCIgaW4gUmVxdWVzdDogbWV0aG9kOlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyBcIiByZXF1ZXN0OlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1IgREFUQTpcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yLmRhdGEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdFRpbWUgPSByZXF1ZXN0VGltZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT0gdW5kZWZpbmVkICYmIHJlc3VsdC52YWx1ZSAhPT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVzcG9uc2U6ICcgKyBKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIm5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBcIiArIHBpbmdOZXh0TnVtICsgJyAob2xkPScgK1xuICAgICAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiArICcpJyk7XG4gICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBwaW5nTmV4dE51bTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZW5kUGluZygpIHtcbiAgICAgICAgaWYgKGVuYWJsZWRQaW5ncykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG51bGw7XG4gICAgICAgICAgICBpZiAocGluZ05leHROdW0gPT0gMCB8fCBwaW5nTmV4dE51bSA9PSBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbDogY29uZmlndXJhdGlvbi5oZWFydGJlYXQgfHwgUElOR19JTlRFUlZBTFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwaW5nTmV4dE51bSsrO1xuXG4gICAgICAgICAgICBzZWxmLnNlbmQoJ3BpbmcnLCBwYXJhbXMsIChmdW5jdGlvbihwaW5nTnVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJFcnJvciBpbiBwaW5nIHJlcXVlc3QgI1wiICsgcGluZ051bSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubWVzc2FnZSArIFwiKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaW5nTnVtID4gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZXJ2ZXIgZGlkIG5vdCByZXNwb25kIHRvIHBpbmcgbWVzc2FnZSAjXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5nTnVtICsgXCIuIFJlY29ubmVjdGluZy4uLiBcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKHBpbmdOZXh0TnVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUcnlpbmcgdG8gc2VuZCBwaW5nLCBidXQgcGluZyBpcyBub3QgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgKiBJZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0IGhhcyBhbnkgdmFsdWUsIHRoZSBwaW5nLXBvbmcgd2lsbCB3b3JrIHdpdGggdGhlIGludGVydmFsXG4gICAgKiBvZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0XG4gICAgKi9cbiAgICBmdW5jdGlvbiB1c2VQaW5nKCkge1xuICAgICAgICBpZiAoIXBpbmdQb25nU3RhcnRlZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgcGluZyAoaWYgY29uZmlndXJlZClcIilcbiAgICAgICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwaW5nSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzZW5kUGluZywgY29uZmlndXJhdGlvbi5oZWFydGJlYXQpO1xuICAgICAgICAgICAgICAgIHNlbmRQaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NpbmcganNvblJwY0NsaWVudCBleHBsaWNpdGx5IGJ5IGNsaWVudFwiKTtcblxuICAgICAgICBpZiAocGluZ0ludGVydmFsICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xlYXJpbmcgcGluZyBpbnRlcnZhbFwiKTtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGNvbmZpZ3VyYXRpb24uc2VuZENsb3NlTWVzc2FnZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VuZGluZyBjbG9zZSBtZXNzYWdlXCIpXG4gICAgICAgICAgICB0aGlzLnNlbmQoJ2Nsb3NlU2Vzc2lvbicsIG51bGwsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyBjbG9zZSBtZXNzYWdlOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcblx0XHRcdHdzLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIHdzLmZvcmNlQ2xvc2UobWlsbGlzKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlY29ubmVjdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpzb25ScGNDbGllbnQ7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gID0gcmVxdWlyZSgnLi93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cblxuZXhwb3J0cy5XZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb247IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxMy0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIEJyb3dzZXJXZWJTb2NrZXQgPSBnbG9iYWwuV2ViU29ja2V0IHx8IGdsb2JhbC5Nb3pXZWJTb2NrZXQ7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqIEdldCBlaXRoZXIgdGhlIGBXZWJTb2NrZXRgIG9yIGBNb3pXZWJTb2NrZXRgIGdsb2JhbHNcbiAqIGluIHRoZSBicm93c2VyIG9yIHRyeSB0byByZXNvbHZlIFdlYlNvY2tldC1jb21wYXRpYmxlXG4gKiBpbnRlcmZhY2UgZXhwb3NlZCBieSBgd3NgIGZvciBOb2RlLWxpa2UgZW52aXJvbm1lbnQuXG4gKi9cblxuLyp2YXIgV2ViU29ja2V0ID0gQnJvd3NlcldlYlNvY2tldDtcbmlmICghV2ViU29ja2V0ICYmIHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgV2ViU29ja2V0ID0gcmVxdWlyZSgnd3MnKTtcbiAgICB9IGNhdGNoIChlKSB7IH1cbn0qL1xuXG4vL3ZhciBTb2NrSlMgPSByZXF1aXJlKCdzb2NranMtY2xpZW50Jyk7XG5cbnZhciBNQVhfUkVUUklFUyA9IDIwMDA7IC8vIEZvcmV2ZXIuLi5cbnZhciBSRVRSWV9USU1FX01TID0gMzAwMDsgLy8gRklYTUU6IEltcGxlbWVudCBleHBvbmVudGlhbCB3YWl0IHRpbWVzLi4uXG5cbnZhciBDT05ORUNUSU5HID0gMDtcbnZhciBPUEVOID0gMTtcbnZhciBDTE9TSU5HID0gMjtcbnZhciBDTE9TRUQgPSAzO1xuXG4vKlxuY29uZmlnID0ge1xuXHRcdHVyaSA6IHdzVXJpLFxuXHRcdHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG5cdFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuXHRcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuXHRcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuXHRcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNC0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKVxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIFVBUGFyc2VyID0gcmVxdWlyZSgndWEtcGFyc2VyLWpzJylcbnZhciB1dWlkID0gcmVxdWlyZSgndXVpZCcpXG52YXIgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKVxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyXG52YXIgcmVjdXJzaXZlID0gcmVxdWlyZSgnbWVyZ2UnKS5yZWN1cnNpdmUuYmluZCh1bmRlZmluZWQsIHRydWUpXG52YXIgc2RwVHJhbnNsYXRvciA9IHJlcXVpcmUoJ3NkcC10cmFuc2xhdG9yJylcbnZhciBsb2dnZXIgPSB3aW5kb3cuTG9nZ2VyIHx8IGNvbnNvbGVcblxuLy8gdmFyIGdVTSA9IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhIHx8IGZ1bmN0aW9uIChjb25zdHJhaW50cykge1xuLy8gICByZXR1cm4gbmV3IFByb21pc2UobmF2aWdhdG9yLmdldFVzZXJNZWRpYShjb25zdHJhaW50cywgZnVuY3Rpb24gKHN0cmVhbSkge1xuLy8gICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4vLyAgICAgc3RhcnQoKVxuLy8gICB9KS5lcm9yKGNhbGxiYWNrKSk7XG4vLyB9XG5cbi8qdHJ5IHtcbiAgcmVxdWlyZSgna3VyZW50by1icm93c2VyLWV4dGVuc2lvbnMnKVxufSBjYXRjaCAoZXJyb3IpIHtcbiAgaWYgKHR5cGVvZiBnZXRTY3JlZW5Db25zdHJhaW50cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBsb2dnZXIud2Fybignc2NyZWVuIHNoYXJpbmcgaXMgbm90IGF2YWlsYWJsZScpXG5cbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyA9IGZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKHNlbmRTb3VyY2UsIGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoXCJUaGlzIGxpYnJhcnkgaXMgbm90IGVuYWJsZWQgZm9yIHNjcmVlbiBzaGFyaW5nXCIpKVxuICAgIH1cbiAgfVxufSovXG5cbnZhciBNRURJQV9DT05TVFJBSU5UUyA9IHtcbiAgYXVkaW86IHRydWUsXG4gIHZpZGVvOiB7XG4gICAgd2lkdGg6IDY0MCxcbiAgICBmcmFtZXJhdGU6IDE1XG4gIH1cbn1cblxuLy8gU29tZWhvdywgdGhlIFVBUGFyc2VyIGNvbnN0cnVjdG9yIGdldHMgYW4gZW1wdHkgd2luZG93IG9iamVjdC5cbi8vIFdlIG5lZWQgdG8gcGFzcyB0aGUgdXNlciBhZ2VudCBzdHJpbmcgaW4gb3JkZXIgdG8gZ2V0IGluZm9ybWF0aW9uXG52YXIgdWEgPSAod2luZG93ICYmIHdpbmRvdy5uYXZpZ2F0b3IpID8gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQgOiAnJ1xudmFyIHBhcnNlciA9IG5ldyBVQVBhcnNlcih1YSlcbnZhciBicm93c2VyID0gcGFyc2VyLmdldEJyb3dzZXIoKVxuXG52YXIgdXNlUGxhbkIgPSBmYWxzZVxuaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gIGxvZ2dlci5kZWJ1Zyhicm93c2VyLm5hbWUgKyBcIjogdXNpbmcgU0RQIFBsYW5CXCIpXG4gIHVzZVBsYW5CID0gdHJ1ZVxufVxuXG5mdW5jdGlvbiBub29wKGVycm9yKSB7XG4gIGlmIChlcnJvcikgbG9nZ2VyLmVycm9yKGVycm9yKVxufVxuXG5mdW5jdGlvbiB0cmFja1N0b3AodHJhY2spIHtcbiAgdHJhY2suc3RvcCAmJiB0cmFjay5zdG9wKClcbn1cblxuZnVuY3Rpb24gc3RyZWFtU3RvcChzdHJlYW0pIHtcbiAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2godHJhY2tTdG9wKVxufVxuXG4vKipcbiAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBTZXNzaW9uRGVzY3JpcHRpb24gb2JqZWN0LlxuICovXG52YXIgZHVtcFNEUCA9IGZ1bmN0aW9uIChkZXNjcmlwdGlvbikge1xuICBpZiAodHlwZW9mIGRlc2NyaXB0aW9uID09PSAndW5kZWZpbmVkJyB8fCBkZXNjcmlwdGlvbiA9PT0gbnVsbCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgcmV0dXJuICd0eXBlOiAnICsgZGVzY3JpcHRpb24udHlwZSArICdcXHJcXG4nICsgZGVzY3JpcHRpb24uc2RwXG59XG5cbmZ1bmN0aW9uIGJ1ZmZlcml6ZUNhbmRpZGF0ZXMocGMsIG9uZXJyb3IpIHtcbiAgdmFyIGNhbmRpZGF0ZXNRdWV1ZSA9IFtdXG5cbiAgcGMuYWRkRXZlbnRMaXN0ZW5lcignc2lnbmFsaW5nc3RhdGVjaGFuZ2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlLmxlbmd0aCkge1xuICAgICAgICB2YXIgZW50cnkgPSBjYW5kaWRhdGVzUXVldWUuc2hpZnQoKVxuICAgICAgICBwYy5hZGRJY2VDYW5kaWRhdGUoZW50cnkuY2FuZGlkYXRlLCBlbnRyeS5jYWxsYmFjaywgZW50cnkuY2FsbGJhY2spXG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4gIHJldHVybiBmdW5jdGlvbiAoY2FuZGlkYXRlLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgb25lcnJvclxuXG4gICAgc3dpdGNoIChwYy5zaWduYWxpbmdTdGF0ZSkge1xuICAgIGNhc2UgJ2Nsb3NlZCc6XG4gICAgICBjYWxsYmFjayhuZXcgRXJyb3IoJ1BlZXJDb25uZWN0aW9uIG9iamVjdCBpcyBjbG9zZWQnKSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdzdGFibGUnOlxuICAgICAgaWYgKHBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgIHBjLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUsIGNhbGxiYWNrLCBjYWxsYmFjayk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgY2FuZGlkYXRlc1F1ZXVlLnB1c2goe1xuICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZSxcbiAgICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG4vKiBTaW11bGNhc3QgdXRpbGl0aWVzICovXG5cbmZ1bmN0aW9uIHJlbW92ZUZJREZyb21PZmZlcihzZHApIHtcbiAgdmFyIG4gPSBzZHAuaW5kZXhPZihcImE9c3NyYy1ncm91cDpGSURcIik7XG5cbiAgaWYgKG4gPiAwKSB7XG4gICAgcmV0dXJuIHNkcC5zbGljZSgwLCBuKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc2RwO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFNpbXVsY2FzdEluZm8odmlkZW9TdHJlYW0pIHtcbiAgdmFyIHZpZGVvVHJhY2tzID0gdmlkZW9TdHJlYW0uZ2V0VmlkZW9UcmFja3MoKTtcbiAgaWYgKCF2aWRlb1RyYWNrcy5sZW5ndGgpIHtcbiAgICBsb2dnZXIud2FybignTm8gdmlkZW8gdHJhY2tzIGF2YWlsYWJsZSBpbiB0aGUgdmlkZW8gc3RyZWFtJylcbiAgICByZXR1cm4gJydcbiAgfVxuICB2YXIgbGluZXMgPSBbXG4gICAgJ2E9eC1nb29nbGUtZmxhZzpjb25mZXJlbmNlJyxcbiAgICAnYT1zc3JjLWdyb3VwOlNJTSAxIDIgMycsXG4gICAgJ2E9c3NyYzoxIGNuYW1lOmxvY2FsVmlkZW8nLFxuICAgICdhPXNzcmM6MSBtc2lkOicgKyB2aWRlb1N0cmVhbS5pZCArICcgJyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MSBtc2xhYmVsOicgKyB2aWRlb1N0cmVhbS5pZCxcbiAgICAnYT1zc3JjOjEgbGFiZWw6JyArIHZpZGVvVHJhY2tzWzBdLmlkLFxuICAgICdhPXNzcmM6MiBjbmFtZTpsb2NhbFZpZGVvJyxcbiAgICAnYT1zc3JjOjIgbXNpZDonICsgdmlkZW9TdHJlYW0uaWQgKyAnICcgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjIgbXNsYWJlbDonICsgdmlkZW9TdHJlYW0uaWQsXG4gICAgJ2E9c3NyYzoyIGxhYmVsOicgKyB2aWRlb1RyYWNrc1swXS5pZCxcbiAgICAnYT1zc3JjOjMgY25hbWU6bG9jYWxWaWRlbycsXG4gICAgJ2E9c3NyYzozIG1zaWQ6JyArIHZpZGVvU3RyZWFtLmlkICsgJyAnICsgdmlkZW9UcmFja3NbMF0uaWQsXG4gICAgJ2E9c3NyYzozIG1zbGFiZWw6JyArIHZpZGVvU3RyZWFtLmlkLFxuICAgICdhPXNzcmM6MyBsYWJlbDonICsgdmlkZW9UcmFja3NbMF0uaWRcbiAgXTtcblxuICBsaW5lcy5wdXNoKCcnKTtcblxuICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG59XG5cbi8qKlxuICogV3JhcHBlciBvYmplY3Qgb2YgYW4gUlRDUGVlckNvbm5lY3Rpb24uIFRoaXMgb2JqZWN0IGlzIGFpbWVkIHRvIHNpbXBsaWZ5IHRoZVxuICogZGV2ZWxvcG1lbnQgb2YgV2ViUlRDLWJhc2VkIGFwcGxpY2F0aW9ucy5cbiAqXG4gKiBAY29uc3RydWN0b3IgbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1vZGUgTW9kZSBpbiB3aGljaCB0aGUgUGVlckNvbm5lY3Rpb24gd2lsbCBiZSBjb25maWd1cmVkLlxuICogIFZhbGlkIHZhbHVlcyBhcmU6ICdyZWN2JywgJ3NlbmQnLCBhbmQgJ3NlbmRSZWN2J1xuICogQHBhcmFtIGxvY2FsVmlkZW8gVmlkZW8gdGFnIGZvciB0aGUgbG9jYWwgc3RyZWFtXG4gKiBAcGFyYW0gcmVtb3RlVmlkZW8gVmlkZW8gdGFnIGZvciB0aGUgcmVtb3RlIHN0cmVhbVxuICogQHBhcmFtIHtNZWRpYVN0cmVhbX0gdmlkZW9TdHJlYW0gU3RyZWFtIHRvIGJlIHVzZWQgYXMgcHJpbWFyeSBzb3VyY2VcbiAqICAodHlwaWNhbGx5IHZpZGVvIGFuZCBhdWRpbywgb3Igb25seSB2aWRlbyBpZiBjb21iaW5lZCB3aXRoIGF1ZGlvU3RyZWFtKSBmb3JcbiAqICBsb2NhbFZpZGVvIGFuZCB0byBiZSBhZGRlZCBhcyBzdHJlYW0gdG8gdGhlIFJUQ1BlZXJDb25uZWN0aW9uXG4gKiBAcGFyYW0ge01lZGlhU3RyZWFtfSBhdWRpb1N0cmVhbSBTdHJlYW0gdG8gYmUgdXNlZCBhcyBzZWNvbmQgc291cmNlXG4gKiAgKHR5cGljYWxseSBmb3IgYXVkaW8pIGZvciBsb2NhbFZpZGVvIGFuZCB0byBiZSBhZGRlZCBhcyBzdHJlYW0gdG8gdGhlXG4gKiAgUlRDUGVlckNvbm5lY3Rpb25cbiAqL1xuZnVuY3Rpb24gV2ViUnRjUGVlcihtb2RlLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlcikpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXIobW9kZSwgb3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyLnN1cGVyXy5jYWxsKHRoaXMpXG5cbiAgaWYgKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIGNhbGxiYWNrID0gb3B0aW9uc1xuICAgIG9wdGlvbnMgPSB1bmRlZmluZWRcbiAgfVxuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gIGNhbGxiYWNrID0gKGNhbGxiYWNrIHx8IG5vb3ApLmJpbmQodGhpcylcblxuICB2YXIgc2VsZiA9IHRoaXNcbiAgdmFyIGxvY2FsVmlkZW8gPSBvcHRpb25zLmxvY2FsVmlkZW9cbiAgdmFyIHJlbW90ZVZpZGVvID0gb3B0aW9ucy5yZW1vdGVWaWRlb1xuICB2YXIgdmlkZW9TdHJlYW0gPSBvcHRpb25zLnZpZGVvU3RyZWFtXG4gIHZhciBhdWRpb1N0cmVhbSA9IG9wdGlvbnMuYXVkaW9TdHJlYW1cbiAgdmFyIG1lZGlhQ29uc3RyYWludHMgPSBvcHRpb25zLm1lZGlhQ29uc3RyYWludHNcblxuICB2YXIgY29ubmVjdGlvbkNvbnN0cmFpbnRzID0gb3B0aW9ucy5jb25uZWN0aW9uQ29uc3RyYWludHNcbiAgdmFyIHBjID0gb3B0aW9ucy5wZWVyQ29ubmVjdGlvblxuICB2YXIgc2VuZFNvdXJjZSA9IG9wdGlvbnMuc2VuZFNvdXJjZSB8fCAnd2ViY2FtJ1xuXG4gIC8qdmFyIGRhdGFDaGFubmVsQ29uZmlnID0gb3B0aW9ucy5kYXRhQ2hhbm5lbENvbmZpZ1xuICB2YXIgdXNlRGF0YUNoYW5uZWxzID0gb3B0aW9ucy5kYXRhQ2hhbm5lbHMgfHwgZmFsc2VcbiAgdmFyIGRhdGFDaGFubmVsKi9cblxuICB2YXIgZ3VpZCA9IHV1aWQudjQoKVxuICB2YXIgY29uZmlndXJhdGlvbiA9IHJlY3Vyc2l2ZSh7XG4gICAgICBpY2VTZXJ2ZXJzOiAoISFvcHRpb25zLmljZVNlcnZlcnMgJiYgb3B0aW9ucy5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDApID8gb3B0aW9ucy5pY2VTZXJ2ZXJzIDogZnJlZWljZSgpXG4gICAgfSxcbiAgICBvcHRpb25zLmNvbmZpZ3VyYXRpb24pXG5cbiAgdmFyIG9uaWNlY2FuZGlkYXRlID0gb3B0aW9ucy5vbmljZWNhbmRpZGF0ZVxuICBpZiAob25pY2VjYW5kaWRhdGUpIHRoaXMub24oJ2ljZWNhbmRpZGF0ZScsIG9uaWNlY2FuZGlkYXRlKVxuXG4gIHZhciBvbmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBvcHRpb25zLm9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZVxuICBpZiAob25jYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgdGhpcy5vbignY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScsIG9uY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSlcbiAgfVxuXG4gIHZhciBzaW11bGNhc3QgPSBvcHRpb25zLnNpbXVsY2FzdFxuICB2YXIgbXVsdGlzdHJlYW0gPSBvcHRpb25zLm11bHRpc3RyZWFtXG4gIHZhciBpbnRlcm9wID0gbmV3IHNkcFRyYW5zbGF0b3IuSW50ZXJvcCgpXG4gIHZhciBjYW5kaWRhdGVzUXVldWVPdXQgPSBbXVxuICB2YXIgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGhpcywge1xuICAgICdwZWVyQ29ubmVjdGlvbic6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcGNcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgJ2lkJzoge1xuICAgICAgdmFsdWU6IG9wdGlvbnMuaWQgfHwgZ3VpZCxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZVxuICAgIH0sXG5cbiAgICAncmVtb3RlVmlkZW8nOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHJlbW90ZVZpZGVvXG4gICAgICB9XG4gICAgfSxcblxuICAgICdsb2NhbFZpZGVvJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBsb2NhbFZpZGVvXG4gICAgICB9XG4gICAgfSxcblxuICAgIC8qJ2RhdGFDaGFubmVsJzoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkYXRhQ2hhbm5lbFxuICAgICAgfVxuICAgIH0sKi9cblxuICAgIC8qKlxuICAgICAqIEBtZW1iZXIgeyhleHRlcm5hbDpJbWFnZURhdGF8dW5kZWZpbmVkKX0gY3VycmVudEZyYW1lXG4gICAgICovXG4gICAgJ2N1cnJlbnRGcmFtZSc6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBbVG9Eb10gRmluZCBzb2x1dGlvbiB3aGVuIHdlIGhhdmUgYSByZW1vdGUgc3RyZWFtIGJ1dCB3ZSBkaWRuJ3Qgc2V0XG4gICAgICAgIC8vIGEgcmVtb3RlVmlkZW8gdGFnXG4gICAgICAgIGlmICghcmVtb3RlVmlkZW8pIHJldHVybjtcblxuICAgICAgICBpZiAocmVtb3RlVmlkZW8ucmVhZHlTdGF0ZSA8IHJlbW90ZVZpZGVvLkhBVkVfQ1VSUkVOVF9EQVRBKVxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gdmlkZW8gc3RyZWFtIGRhdGEgYXZhaWxhYmxlJylcblxuICAgICAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcbiAgICAgICAgY2FudmFzLndpZHRoID0gcmVtb3RlVmlkZW8udmlkZW9XaWR0aFxuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gcmVtb3RlVmlkZW8udmlkZW9IZWlnaHRcblxuICAgICAgICBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKS5kcmF3SW1hZ2UocmVtb3RlVmlkZW8sIDAsIDApXG5cbiAgICAgICAgcmV0dXJuIGNhbnZhc1xuICAgICAgfVxuICAgIH1cbiAgfSlcblxuICAvLyBJbml0IFBlZXJDb25uZWN0aW9uXG4gIGlmICghcGMpIHtcbiAgICBwYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbihjb25maWd1cmF0aW9uKTtcbiAgICAvKmlmICh1c2VEYXRhQ2hhbm5lbHMgJiYgIWRhdGFDaGFubmVsKSB7XG4gICAgICB2YXIgZGNJZCA9ICdXZWJSdGNQZWVyLScgKyBzZWxmLmlkXG4gICAgICB2YXIgZGNPcHRpb25zID0gdW5kZWZpbmVkXG4gICAgICBpZiAoZGF0YUNoYW5uZWxDb25maWcpIHtcbiAgICAgICAgZGNJZCA9IGRhdGFDaGFubmVsQ29uZmlnLmlkIHx8IGRjSWRcbiAgICAgICAgZGNPcHRpb25zID0gZGF0YUNoYW5uZWxDb25maWcub3B0aW9uc1xuICAgICAgfVxuICAgICAgZGF0YUNoYW5uZWwgPSBwYy5jcmVhdGVEYXRhQ2hhbm5lbChkY0lkLCBkY09wdGlvbnMpO1xuICAgICAgaWYgKGRhdGFDaGFubmVsQ29uZmlnKSB7XG4gICAgICAgIGRhdGFDaGFubmVsLm9ub3BlbiA9IGRhdGFDaGFubmVsQ29uZmlnLm9ub3BlbjtcbiAgICAgICAgZGF0YUNoYW5uZWwub25jbG9zZSA9IGRhdGFDaGFubmVsQ29uZmlnLm9uY2xvc2U7XG4gICAgICAgIGRhdGFDaGFubmVsLm9ubWVzc2FnZSA9IGRhdGFDaGFubmVsQ29uZmlnLm9ubWVzc2FnZTtcbiAgICAgICAgZGF0YUNoYW5uZWwub25idWZmZXJlZGFtb3VudGxvdyA9IGRhdGFDaGFubmVsQ29uZmlnLm9uYnVmZmVyZWRhbW91bnRsb3c7XG4gICAgICAgIGRhdGFDaGFubmVsLm9uZXJyb3IgPSBkYXRhQ2hhbm5lbENvbmZpZy5vbmVycm9yIHx8IG5vb3A7XG4gICAgICB9XG4gICAgfSovXG4gIH1cblxuICBwYy5hZGRFdmVudExpc3RlbmVyKCdpY2VjYW5kaWRhdGUnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgY2FuZGlkYXRlID0gZXZlbnQuY2FuZGlkYXRlXG5cbiAgICBpZiAoRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQoc2VsZiwgJ2ljZWNhbmRpZGF0ZScpIHx8XG4gICAgICBFdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudChcbiAgICAgICAgc2VsZiwgJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSkge1xuICAgICAgaWYgKGNhbmRpZGF0ZSkge1xuICAgICAgICB2YXIgY2FuZFxuXG4gICAgICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgICAgIGNhbmQgPSBpbnRlcm9wLmNhbmRpZGF0ZVRvVW5pZmllZFBsYW4oY2FuZGlkYXRlKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbmQgPSBjYW5kaWRhdGVcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYuZW1pdCgnaWNlY2FuZGlkYXRlJywgY2FuZClcbiAgICAgICAgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlXG4gICAgICB9IGVsc2UgaWYgKCFjYW5kaWRhdGVnYXRoZXJpbmdkb25lKSB7XG4gICAgICAgIHNlbGYuZW1pdCgnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpXG4gICAgICAgIGNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgLy8gTm90IGxpc3RlbmluZyB0byAnaWNlY2FuZGlkYXRlJyBvciAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScgZXZlbnRzLCBxdWV1ZVxuICAgICAgLy8gdGhlIGNhbmRpZGF0ZSB1bnRpbCBvbmUgb2YgdGhlbSBpcyBsaXN0ZW5lZFxuICAgICAgY2FuZGlkYXRlc1F1ZXVlT3V0LnB1c2goY2FuZGlkYXRlKVxuXG4gICAgICBpZiAoIWNhbmRpZGF0ZSkgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWVcbiAgICB9XG4gIH0pXG5cbiAgcGMub25hZGRzdHJlYW0gPSBvcHRpb25zLm9uYWRkc3RyZWFtXG4gIHBjLm9ubmVnb3RpYXRpb25uZWVkZWQgPSBvcHRpb25zLm9ubmVnb3RpYXRpb25uZWVkZWRcbiAgdGhpcy5vbignbmV3TGlzdGVuZXInLCBmdW5jdGlvbiAoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgaWYgKGV2ZW50ID09PSAnaWNlY2FuZGlkYXRlJyB8fCBldmVudCA9PT0gJ2NhbmRpZGF0ZWdhdGhlcmluZ2RvbmUnKSB7XG4gICAgICB3aGlsZSAoY2FuZGlkYXRlc1F1ZXVlT3V0Lmxlbmd0aCkge1xuICAgICAgICB2YXIgY2FuZGlkYXRlID0gY2FuZGlkYXRlc1F1ZXVlT3V0LnNoaWZ0KClcblxuICAgICAgICBpZiAoIWNhbmRpZGF0ZSA9PT0gKGV2ZW50ID09PSAnY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZScpKSB7XG4gICAgICAgICAgbGlzdGVuZXIoY2FuZGlkYXRlKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4gIHZhciBhZGRJY2VDYW5kaWRhdGUgPSBidWZmZXJpemVDYW5kaWRhdGVzKHBjKVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYW4gSUNFIGNhbmRpZGF0ZSBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUuYWRkSWNlQ2FuZGlkYXRlXG4gICAqXG4gICAqIEBwYXJhbSBpY2VDYW5kaWRhdGUgLSBMaXRlcmFsIG9iamVjdCB3aXRoIHRoZSBJQ0UgY2FuZGlkYXRlIGRlc2NyaXB0aW9uXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtIENhbGxlZCB3aGVuIHRoZSBJQ0UgY2FuZGlkYXRlIGhhcyBiZWVuIGFkZGVkLlxuICAgKi9cbiAgdGhpcy5hZGRJY2VDYW5kaWRhdGUgPSBmdW5jdGlvbiAoaWNlQ2FuZGlkYXRlLCBjYWxsYmFjaykge1xuICAgIHZhciBjYW5kaWRhdGVcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgY2FuZGlkYXRlID0gaW50ZXJvcC5jYW5kaWRhdGVUb1BsYW5CKGljZUNhbmRpZGF0ZSlcbiAgICB9IGVsc2Uge1xuICAgICAgY2FuZGlkYXRlID0gbmV3IFJUQ0ljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpXG4gICAgfVxuXG4gICAgbG9nZ2VyLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSlcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSwgY2FsbGJhY2spXG4gIH1cblxuICB0aGlzLmdlbmVyYXRlT2ZmZXIgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrLmJpbmQodGhpcylcblxuICAgIHZhciBvZmZlckF1ZGlvID0gdHJ1ZVxuICAgIHZhciBvZmZlclZpZGVvID0gdHJ1ZVxuICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgIGlmIChtZWRpYUNvbnN0cmFpbnRzKSB7XG4gICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvID09PSAnYm9vbGVhbicpID9cbiAgICAgICAgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA6IHRydWVcbiAgICAgIG9mZmVyVmlkZW8gPSAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMudmlkZW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZVxuICAgIH1cblxuICAgIHZhciBicm93c2VyRGVwZW5kYW50Q29uc3RyYWludHMgPSB7XG4gICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiAobW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgIG9mZmVyVG9SZWNlaXZlVmlkZW86IChtb2RlICE9PSAnc2VuZG9ubHknICYmIG9mZmVyVmlkZW8pXG4gICAgfVxuXG4gICAgLy9GSVhNRTogY2xhcmlmeSBwb3NzaWJsZSBjb25zdHJhaW50cyBwYXNzZWQgdG8gY3JlYXRlT2ZmZXIoKVxuICAgIC8qdmFyIGNvbnN0cmFpbnRzID0gcmVjdXJzaXZlKGJyb3dzZXJEZXBlbmRhbnRDb25zdHJhaW50cyxcbiAgICAgIGNvbm5lY3Rpb25Db25zdHJhaW50cykqL1xuXG4gICAgdmFyIGNvbnN0cmFpbnRzID0gYnJvd3NlckRlcGVuZGFudENvbnN0cmFpbnRzO1xuXG4gICAgbG9nZ2VyLmRlYnVnKCdjb25zdHJhaW50czogJyArIEpTT04uc3RyaW5naWZ5KGNvbnN0cmFpbnRzKSlcblxuICAgIHBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKGZ1bmN0aW9uIChvZmZlcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpXG4gICAgICBvZmZlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KG9mZmVyKVxuICAgICAgcmV0dXJuIHBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgbG9jYWxEZXNjcmlwdGlvbiA9IHBjLmxvY2FsRGVzY3JpcHRpb25cbiAgICAgIGxvZ2dlci5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApXG4gICAgICBpZiAobXVsdGlzdHJlYW0gJiYgdXNlUGxhbkIpIHtcbiAgICAgICAgbG9jYWxEZXNjcmlwdGlvbiA9IGludGVyb3AudG9VbmlmaWVkUGxhbihsb2NhbERlc2NyaXB0aW9uKVxuICAgICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpvcmlnUGxhbkItPlVuaWZpZWRQbGFuJywgZHVtcFNEUChcbiAgICAgICAgICBsb2NhbERlc2NyaXB0aW9uKSlcbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwLCBzZWxmLnByb2Nlc3NBbnN3ZXIuYmluZChcbiAgICAgICAgc2VsZikpXG4gICAgfSkuY2F0Y2goY2FsbGJhY2spXG4gIH1cblxuICB0aGlzLmdldExvY2FsU2Vzc2lvbkRlc2NyaXB0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHBjLmxvY2FsRGVzY3JpcHRpb25cbiAgfVxuXG4gIHRoaXMuZ2V0UmVtb3RlU2Vzc2lvbkRlc2NyaXB0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHBjLnJlbW90ZURlc2NyaXB0aW9uXG4gIH1cblxuICBmdW5jdGlvbiBzZXRSZW1vdGVWaWRlbygpIHtcbiAgICBpZiAocmVtb3RlVmlkZW8pIHtcbiAgICAgIHJlbW90ZVZpZGVvLnBhdXNlKClcblxuICAgICAgdmFyIHN0cmVhbSA9IHBjLmdldFJlbW90ZVN0cmVhbXMoKVswXVxuICAgICAgcmVtb3RlVmlkZW8uc3JjT2JqZWN0ID0gc3RyZWFtXG4gICAgICBsb2dnZXIuZGVidWcoJ1JlbW90ZSBzdHJlYW06Jywgc3RyZWFtKVxuXG4gICAgICByZW1vdGVWaWRlby5sb2FkKClcbiAgICB9XG4gIH1cblxuICB0aGlzLnNob3dMb2NhbFZpZGVvID0gZnVuY3Rpb24gKCkge1xuICAgIGxvY2FsVmlkZW8uc3JjT2JqZWN0ID0gdmlkZW9TdHJlYW1cbiAgICBsb2NhbFZpZGVvLm11dGVkID0gdHJ1ZVxuICB9XG5cbiAgLyp0aGlzLnNlbmQgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIGlmIChkYXRhQ2hhbm5lbCAmJiBkYXRhQ2hhbm5lbC5yZWFkeVN0YXRlID09PSAnb3BlbicpIHtcbiAgICAgIGRhdGFDaGFubmVsLnNlbmQoZGF0YSlcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICdUcnlpbmcgdG8gc2VuZCBkYXRhIG92ZXIgYSBub24tZXhpc3Rpbmcgb3IgY2xvc2VkIGRhdGEgY2hhbm5lbCcpXG4gICAgfVxuICB9Ki9cblxuICAvKipcbiAgICogQ2FsbGJhY2sgZnVuY3Rpb24gaW52b2tlZCB3aGVuIGEgU0RQIGFuc3dlciBpcyByZWNlaXZlZC4gRGV2ZWxvcGVycyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gaW52b2tlIHRoaXMgZnVuY3Rpb24gaW4gb3JkZXIgdG8gY29tcGxldGUgdGhlIFNEUCBuZWdvdGlhdGlvbi5cbiAgICpcbiAgICogQGZ1bmN0aW9uIG1vZHVsZTprdXJlbnRvVXRpbHMuV2ViUnRjUGVlci5wcm90b3R5cGUucHJvY2Vzc0Fuc3dlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwQW5zd2VyIC0gRGVzY3JpcHRpb24gb2Ygc2RwQW5zd2VyXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtXG4gICAqICAgICAgICAgICAgSW52b2tlZCBhZnRlciB0aGUgU0RQIGFuc3dlciBpcyBwcm9jZXNzZWQsIG9yIHRoZXJlIGlzIGFuIGVycm9yLlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzQW5zd2VyID0gZnVuY3Rpb24gKHNkcEFuc3dlciwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IChjYWxsYmFjayB8fCBub29wKS5iaW5kKHRoaXMpXG5cbiAgICB2YXIgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICB0eXBlOiAnYW5zd2VyJyxcbiAgICAgIHNkcDogc2RwQW5zd2VyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CQW5zd2VyID0gaW50ZXJvcC50b1BsYW5CKGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnYXNud2VyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJBbnN3ZXIpKVxuICAgICAgYW5zd2VyID0gcGxhbkJBbnN3ZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJylcblxuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjaygnUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJylcbiAgICB9XG5cbiAgICBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2V0UmVtb3RlVmlkZW8oKVxuXG4gICAgICAgIGNhbGxiYWNrKClcbiAgICAgIH0sXG4gICAgICBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBpbnZva2VkIHdoZW4gYSBTRFAgb2ZmZXIgaXMgcmVjZWl2ZWQuIERldmVsb3BlcnMgYXJlXG4gICAqIGV4cGVjdGVkIHRvIGludm9rZSB0aGlzIGZ1bmN0aW9uIGluIG9yZGVyIHRvIGNvbXBsZXRlIHRoZSBTRFAgbmVnb3RpYXRpb24uXG4gICAqXG4gICAqIEBmdW5jdGlvbiBtb2R1bGU6a3VyZW50b1V0aWxzLldlYlJ0Y1BlZXIucHJvdG90eXBlLnByb2Nlc3NPZmZlclxuICAgKlxuICAgKiBAcGFyYW0gc2RwT2ZmZXIgLSBEZXNjcmlwdGlvbiBvZiBzZHBPZmZlclxuICAgKiBAcGFyYW0gY2FsbGJhY2sgLSBDYWxsZWQgd2hlbiB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIGhhcyBiZWVuIHNldFxuICAgKiAgc3VjY2Vzc2Z1bGx5LlxuICAgKi9cbiAgdGhpcy5wcm9jZXNzT2ZmZXIgPSBmdW5jdGlvbiAoc2RwT2ZmZXIsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjay5iaW5kKHRoaXMpXG5cbiAgICB2YXIgb2ZmZXIgPSBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICBzZHA6IHNkcE9mZmVyXG4gICAgfSlcblxuICAgIGlmIChtdWx0aXN0cmVhbSAmJiB1c2VQbGFuQikge1xuICAgICAgdmFyIHBsYW5CT2ZmZXIgPSBpbnRlcm9wLnRvUGxhbkIob2ZmZXIpXG4gICAgICBsb2dnZXIuZGVidWcoJ29mZmVyOjpwbGFuQicsIGR1bXBTRFAocGxhbkJPZmZlcikpXG4gICAgICBvZmZlciA9IHBsYW5CT2ZmZXJcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKVxuXG4gICAgaWYgKHBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCdQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQnKVxuICAgIH1cblxuICAgIHBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBzZXRSZW1vdGVWaWRlbygpXG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcGMuY3JlYXRlQW5zd2VyKClcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChhbnN3ZXIpIHtcbiAgICAgIGFuc3dlciA9IG1hbmdsZVNkcFRvQWRkU2ltdWxjYXN0KGFuc3dlcilcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ3JlYXRlZCBTRFAgYW5zd2VyJylcbiAgICAgIHJldHVybiBwYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcilcbiAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBsb2NhbERlc2NyaXB0aW9uID0gcGMubG9jYWxEZXNjcmlwdGlvblxuICAgICAgaWYgKG11bHRpc3RyZWFtICYmIHVzZVBsYW5CKSB7XG4gICAgICAgIGxvY2FsRGVzY3JpcHRpb24gPSBpbnRlcm9wLnRvVW5pZmllZFBsYW4obG9jYWxEZXNjcmlwdGlvbilcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdhbnN3ZXI6Om9yaWdQbGFuQi0+VW5pZmllZFBsYW4nLCBkdW1wU0RQKFxuICAgICAgICAgIGxvY2FsRGVzY3JpcHRpb24pKVxuICAgICAgfVxuICAgICAgbG9nZ2VyLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcClcbiAgICAgIGNhbGxiYWNrKG51bGwsIGxvY2FsRGVzY3JpcHRpb24uc2RwKVxuICAgIH0pLmNhdGNoKGNhbGxiYWNrKVxuICB9XG5cbiAgZnVuY3Rpb24gbWFuZ2xlU2RwVG9BZGRTaW11bGNhc3QoYW5zd2VyKSB7XG4gICAgaWYgKHNpbXVsY2FzdCkge1xuICAgICAgaWYgKGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9tZScgfHwgYnJvd3Nlci5uYW1lID09PSAnQ2hyb21pdW0nKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnQWRkaW5nIG11bHRpY2FzdCBpbmZvJylcbiAgICAgICAgYW5zd2VyID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgICAgJ3R5cGUnOiBhbnN3ZXIudHlwZSxcbiAgICAgICAgICAnc2RwJzogcmVtb3ZlRklERnJvbU9mZmVyKGFuc3dlci5zZHApICsgZ2V0U2ltdWxjYXN0SW5mbyhcbiAgICAgICAgICAgIHZpZGVvU3RyZWFtKVxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1NpbXVsY2FzdCBpcyBvbmx5IGF2YWlsYWJsZSBpbiBDaHJvbWUgYnJvd3Nlci4nKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhbnN3ZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdCB0YWtpbmcgaW50byBhY2NvdW50IHRoZVxuICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICogcHJvY2VzczogZ2VuZXJhdGVzIHRoZSBTRFAgb2ZmZXIgYW5kIGludm9rZXMgdGhlIG9uc2Rwb2ZmZXIgY2FsbGJhY2suIFRoaXNcbiAgICogY2FsbGJhY2sgaXMgZXhwZWN0ZWQgdG8gc2VuZCB0aGUgU0RQIG9mZmVyLCBpbiBvcmRlciB0byBvYnRhaW4gYW4gU0RQXG4gICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICovXG4gIGZ1bmN0aW9uIHN0YXJ0KCkge1xuICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgIGNhbGxiYWNrKFxuICAgICAgICAnVGhlIHBlZXIgY29ubmVjdGlvbiBvYmplY3QgaXMgaW4gXCJjbG9zZWRcIiBzdGF0ZS4gVGhpcyBpcyBtb3N0IGxpa2VseSBkdWUgdG8gYW4gaW52b2NhdGlvbiBvZiB0aGUgZGlzcG9zZSBtZXRob2QgYmVmb3JlIGFjY2VwdGluZyBpbiB0aGUgZGlhbG9ndWUnXG4gICAgICApXG4gICAgfVxuXG4gICAgaWYgKHZpZGVvU3RyZWFtICYmIGxvY2FsVmlkZW8pIHtcbiAgICAgIHNlbGYuc2hvd0xvY2FsVmlkZW8oKVxuICAgIH1cblxuICAgIGlmICh2aWRlb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKHZpZGVvU3RyZWFtKVxuICAgIH1cblxuICAgIGlmIChhdWRpb1N0cmVhbSkge1xuICAgICAgcGMuYWRkU3RyZWFtKGF1ZGlvU3RyZWFtKVxuICAgIH1cblxuICAgIC8vIFtIYWNrXSBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQzNTU4XG4gICAgdmFyIGJyb3dzZXIgPSBwYXJzZXIuZ2V0QnJvd3NlcigpXG4gICAgaWYgKG1vZGUgPT09ICdzZW5kb25seScgJiZcbiAgICAgIChicm93c2VyLm5hbWUgPT09ICdDaHJvbWUnIHx8IGJyb3dzZXIubmFtZSA9PT0gJ0Nocm9taXVtJykgJiZcbiAgICAgIGJyb3dzZXIubWFqb3IgPT09IDM5KSB7XG4gICAgICBtb2RlID0gJ3NlbmRyZWN2J1xuICAgIH1cblxuICAgIGNhbGxiYWNrKClcbiAgfVxuXG4gIGlmIChtb2RlICE9PSAncmVjdm9ubHknICYmICF2aWRlb1N0cmVhbSAmJiAhYXVkaW9TdHJlYW0pIHtcbiAgICBmdW5jdGlvbiBnZXRNZWRpYShjb25zdHJhaW50cykge1xuICAgICAgaWYgKGNvbnN0cmFpbnRzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3RyYWludHMgPSBNRURJQV9DT05TVFJBSU5UU1xuICAgICAgfVxuXG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cykudGhlbihmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgIHZpZGVvU3RyZWFtID0gc3RyZWFtXG4gICAgICAgIHN0YXJ0KClcbiAgICAgIH0pLmNhdGNoKGNhbGxiYWNrKTtcbiAgICB9XG4gICAgaWYgKHNlbmRTb3VyY2UgPT09ICd3ZWJjYW0nKSB7XG4gICAgICBnZXRNZWRpYShtZWRpYUNvbnN0cmFpbnRzKVxuICAgIH0gZWxzZSB7XG4gICAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhzZW5kU291cmNlLCBmdW5jdGlvbiAoZXJyb3IsIGNvbnN0cmFpbnRzXykge1xuICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycm9yKVxuXG4gICAgICAgIGNvbnN0cmFpbnRzID0gW21lZGlhQ29uc3RyYWludHNdXG4gICAgICAgIGNvbnN0cmFpbnRzLnVuc2hpZnQoY29uc3RyYWludHNfKVxuICAgICAgICBnZXRNZWRpYShyZWN1cnNpdmUuYXBwbHkodW5kZWZpbmVkLCBjb25zdHJhaW50cykpXG4gICAgICB9LCBndWlkKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBzZXRUaW1lb3V0KHN0YXJ0LCAwKVxuICB9XG5cbiAgdGhpcy5vbignX2Rpc3Bvc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGxvY2FsVmlkZW8pIHtcbiAgICAgIGxvY2FsVmlkZW8ucGF1c2UoKVxuICAgICAgbG9jYWxWaWRlby5zcmNPYmplY3QgPSBudWxsXG4gICAgICBsb2NhbFZpZGVvLmxvYWQoKVxuICAgICAgLy9Vbm11dGUgbG9jYWwgdmlkZW8gaW4gY2FzZSB0aGUgdmlkZW8gdGFnIGlzIGxhdGVyIHVzZWQgZm9yIHJlbW90ZSB2aWRlb1xuICAgICAgbG9jYWxWaWRlby5tdXRlZCA9IGZhbHNlXG4gICAgfVxuICAgIGlmIChyZW1vdGVWaWRlbykge1xuICAgICAgcmVtb3RlVmlkZW8ucGF1c2UoKVxuICAgICAgcmVtb3RlVmlkZW8uc3JjT2JqZWN0ID0gbnVsbFxuICAgICAgcmVtb3RlVmlkZW8ubG9hZCgpXG4gICAgfVxuICAgIHNlbGYucmVtb3ZlQWxsTGlzdGVuZXJzKClcblxuICAgIGlmICh3aW5kb3cuY2FuY2VsQ2hvb3NlRGVza3RvcE1lZGlhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHdpbmRvdy5jYW5jZWxDaG9vc2VEZXNrdG9wTWVkaWEoZ3VpZClcbiAgICB9XG4gIH0pXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyLCBFdmVudEVtaXR0ZXIpXG5cbmZ1bmN0aW9uIGNyZWF0ZUVuYWJsZURlc2NyaXB0b3IodHlwZSkge1xuICB2YXIgbWV0aG9kID0gJ2dldCcgKyB0eXBlICsgJ1RyYWNrcydcblxuICByZXR1cm4ge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBbVG9Eb10gU2hvdWxkIHJldHVybiB1bmRlZmluZWQgaWYgbm90IGFsbCB0cmFja3MgaGF2ZSB0aGUgc2FtZSB2YWx1ZT9cblxuICAgICAgaWYgKCF0aGlzLnBlZXJDb25uZWN0aW9uKSByZXR1cm5cblxuICAgICAgdmFyIHN0cmVhbXMgPSB0aGlzLnBlZXJDb25uZWN0aW9uLmdldExvY2FsU3RyZWFtcygpXG4gICAgICBpZiAoIXN0cmVhbXMubGVuZ3RoKSByZXR1cm5cblxuICAgICAgZm9yICh2YXIgaSA9IDAsIHN0cmVhbTsgc3RyZWFtID0gc3RyZWFtc1tpXTsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFja3MgPSBzdHJlYW1bbWV0aG9kXSgpXG4gICAgICAgIGZvciAodmFyIGogPSAwLCB0cmFjazsgdHJhY2sgPSB0cmFja3Nbal07IGorKylcbiAgICAgICAgICBpZiAoIXRyYWNrLmVuYWJsZWQpIHJldHVybiBmYWxzZVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgIGZ1bmN0aW9uIHRyYWNrU2V0RW5hYmxlKHRyYWNrKSB7XG4gICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZVxuICAgICAgfVxuXG4gICAgICB0aGlzLnBlZXJDb25uZWN0aW9uLmdldExvY2FsU3RyZWFtcygpLmZvckVhY2goZnVuY3Rpb24gKHN0cmVhbSkge1xuICAgICAgICBzdHJlYW1bbWV0aG9kXSgpLmZvckVhY2godHJhY2tTZXRFbmFibGUpXG4gICAgICB9KVxuICAgIH1cbiAgfVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydGllcyhXZWJSdGNQZWVyLnByb3RvdHlwZSwge1xuICAnZW5hYmxlZCc6IHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuYXVkaW9FbmFibGVkICYmIHRoaXMudmlkZW9FbmFibGVkXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgdGhpcy5hdWRpb0VuYWJsZWQgPSB0aGlzLnZpZGVvRW5hYmxlZCA9IHZhbHVlXG4gICAgfVxuICB9LFxuICAnYXVkaW9FbmFibGVkJzogY3JlYXRlRW5hYmxlRGVzY3JpcHRvcignQXVkaW8nKSxcbiAgJ3ZpZGVvRW5hYmxlZCc6IGNyZWF0ZUVuYWJsZURlc2NyaXB0b3IoJ1ZpZGVvJylcbn0pXG5cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmdldExvY2FsU3RyZWFtID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gIGlmICh0aGlzLnBlZXJDb25uZWN0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMucGVlckNvbm5lY3Rpb24uZ2V0TG9jYWxTdHJlYW1zKClbaW5kZXggfHwgMF1cbiAgfVxufVxuXG5XZWJSdGNQZWVyLnByb3RvdHlwZS5nZXRSZW1vdGVTdHJlYW0gPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgaWYgKHRoaXMucGVlckNvbm5lY3Rpb24pIHtcbiAgICByZXR1cm4gdGhpcy5wZWVyQ29ubmVjdGlvbi5nZXRSZW1vdGVTdHJlYW1zKClbaW5kZXggfHwgMF1cbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUaGlzIG1ldGhvZCBmcmVlcyB0aGUgcmVzb3VyY2VzIHVzZWQgYnkgV2ViUnRjUGVlci5cbiAqXG4gKiBAZnVuY3Rpb24gbW9kdWxlOmt1cmVudG9VdGlscy5XZWJSdGNQZWVyLnByb3RvdHlwZS5kaXNwb3NlXG4gKi9cbldlYlJ0Y1BlZXIucHJvdG90eXBlLmRpc3Bvc2UgPSBmdW5jdGlvbiAoKSB7XG4gIGxvZ2dlci5kZWJ1ZygnRGlzcG9zaW5nIFdlYlJ0Y1BlZXInKVxuXG4gIHZhciBwYyA9IHRoaXMucGVlckNvbm5lY3Rpb25cbiAgLy92YXIgZGMgPSB0aGlzLmRhdGFDaGFubmVsXG4gIHRyeSB7XG4gICAgLyppZiAoZGMpIHtcbiAgICAgIGlmIChkYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHJldHVyblxuXG4gICAgICBkYy5jbG9zZSgpXG4gICAgfSovXG5cbiAgICBpZiAocGMpIHtcbiAgICAgIGlmIChwYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHJldHVyblxuXG4gICAgICBwYy5nZXRMb2NhbFN0cmVhbXMoKS5mb3JFYWNoKHN0cmVhbVN0b3ApXG5cbiAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAvLyBpZih2aWRlb1N0cmVhbSkgcGMucmVtb3ZlU3RyZWFtKHZpZGVvU3RyZWFtKTtcbiAgICAgIC8vIGlmKGF1ZGlvU3RyZWFtKSBwYy5yZW1vdmVTdHJlYW0oYXVkaW9TdHJlYW0pO1xuXG4gICAgICBwYy5jbG9zZSgpXG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIud2FybignRXhjZXB0aW9uIGRpc3Bvc2luZyB3ZWJydGMgcGVlciAnICsgZXJyKVxuICB9XG5cbiAgdGhpcy5lbWl0KCdfZGlzcG9zZScpXG59XG5cbi8vXG4vLyBTcGVjaWFsaXplZCBjaGlsZCBjbGFzc2VzXG4vL1xuXG5mdW5jdGlvbiBXZWJSdGNQZWVyUmVjdm9ubHkob3B0aW9ucywgY2FsbGJhY2spIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFdlYlJ0Y1BlZXJSZWN2b25seSkpIHtcbiAgICByZXR1cm4gbmV3IFdlYlJ0Y1BlZXJSZWN2b25seShvcHRpb25zLCBjYWxsYmFjaylcbiAgfVxuXG4gIFdlYlJ0Y1BlZXJSZWN2b25seS5zdXBlcl8uY2FsbCh0aGlzLCAncmVjdm9ubHknLCBvcHRpb25zLCBjYWxsYmFjaylcbn1cbmluaGVyaXRzKFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlcilcblxuZnVuY3Rpb24gV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBXZWJSdGNQZWVyU2VuZG9ubHkpKSB7XG4gICAgcmV0dXJuIG5ldyBXZWJSdGNQZWVyU2VuZG9ubHkob3B0aW9ucywgY2FsbGJhY2spXG4gIH1cblxuICBXZWJSdGNQZWVyU2VuZG9ubHkuc3VwZXJfLmNhbGwodGhpcywgJ3NlbmRvbmx5Jywgb3B0aW9ucywgY2FsbGJhY2spXG59XG5pbmhlcml0cyhXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXIpXG5cbmZ1bmN0aW9uIFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zLCBjYWxsYmFjaykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgV2ViUnRjUGVlclNlbmRyZWN2KSkge1xuICAgIHJldHVybiBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMsIGNhbGxiYWNrKVxuICB9XG5cbiAgV2ViUnRjUGVlclNlbmRyZWN2LnN1cGVyXy5jYWxsKHRoaXMsICdzZW5kcmVjdicsIG9wdGlvbnMsIGNhbGxiYWNrKVxufVxuaW5oZXJpdHMoV2ViUnRjUGVlclNlbmRyZWN2LCBXZWJSdGNQZWVyKVxuXG5mdW5jdGlvbiBoYXJrVXRpbHMoc3RyZWFtLCBvcHRpb25zKSB7XG4gIHJldHVybiBoYXJrKHN0cmVhbSwgb3B0aW9ucyk7XG59XG5cbmV4cG9ydHMuYnVmZmVyaXplQ2FuZGlkYXRlcyA9IGJ1ZmZlcml6ZUNhbmRpZGF0ZXNcblxuZXhwb3J0cy5XZWJSdGNQZWVyUmVjdm9ubHkgPSBXZWJSdGNQZWVyUmVjdm9ubHlcbmV4cG9ydHMuV2ViUnRjUGVlclNlbmRvbmx5ID0gV2ViUnRjUGVlclNlbmRvbmx5XG5leHBvcnRzLldlYlJ0Y1BlZXJTZW5kcmVjdiA9IFdlYlJ0Y1BlZXJTZW5kcmVjdlxuZXhwb3J0cy5oYXJrID0gaGFya1V0aWxzXG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBUaGlzIG1vZHVsZSBjb250YWlucyBhIHNldCBvZiByZXVzYWJsZSBjb21wb25lbnRzIHRoYXQgaGF2ZSBiZWVuIGZvdW5kIHVzZWZ1bFxuICogZHVyaW5nIHRoZSBkZXZlbG9wbWVudCBvZiB0aGUgV2ViUlRDIGFwcGxpY2F0aW9ucyB3aXRoIEt1cmVudG8uXG4gKiBcbiAqIEBtb2R1bGUga3VyZW50b1V0aWxzXG4gKiBcbiAqIEBjb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICogQGxpY2Vuc2UgQUx2MlxuICovXG5cbnZhciBXZWJSdGNQZWVyID0gcmVxdWlyZSgnLi9XZWJSdGNQZWVyJyk7XG5cbmV4cG9ydHMuV2ViUnRjUGVlciA9IFdlYlJ0Y1BlZXI7XG4iLCIvLyBMYXN0IHRpbWUgdXBkYXRlZCBvbiBEZWNlbWJlciAxMywgMjAxN1xuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYoc291cmNlSWQgPT0gJ2ZpcmVmb3gnKSB7XG4gICAgICAgIG5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzLCBvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2UgbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMsIG9uU3VjY2Vzcywgb25GYWlsdXJlKTtcbn0pO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhlcnJvciwgc291cmNlSWQpIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmIChzb3VyY2VJZCkge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMudmlkZW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2NyZWVuX2NvbnN0cmFpbnRzO1xufVxuXG52YXIgaWZyYW1lO1xuXG5mdW5jdGlvbiBwb3N0R2V0U291cmNlSWRNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldFNvdXJjZUlkTWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGNhcHR1cmVTb3VyY2VJZDogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmZ1bmN0aW9uIGxvYWRJRnJhbWUobG9hZENhbGxiYWNrKSB7XG4gICAgaWYgKGlmcmFtZSkge1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO1xuICAgIGlmcmFtZS5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmcmFtZS5pc0xvYWRlZCA9IHRydWU7XG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgIH07XG4gICAgaWZyYW1lLnNyYyA9ICdodHRwczovL3d3dy53ZWJydGMtZXhwZXJpbWVudC5jb20vZ2V0U291cmNlSWQvJztcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbn07XG5cbmZ1bmN0aW9uIHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKCkge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSwgMTAwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzOiB0cnVlXG4gICAgfSwgJyonKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5JZCA9IGdldFNjcmVlbklkOyIsIi8vIGdsb2JhbCB2YXJpYWJsZXNcbnZhciBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xudmFyIHNjcmVlbkNhbGxiYWNrO1xudmFyIGlzRmlyZWZveCA9IHR5cGVvZiB3aW5kb3cuSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnO1xudmFyIGlzT3BlcmEgPSAhIXdpbmRvdy5vcGVyYSB8fCBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJyBPUFIvJykgPj0gMDtcbnZhciBpc0Nocm9tZSA9ICEhd2luZG93LmNocm9tZSAmJiAhaXNPcGVyYTtcblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBpZiAoZXZlbnQub3JpZ2luICE9IHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBvbk1lc3NhZ2VDYWxsYmFjayhldmVudC5kYXRhKTtcbn0pO1xuXG4vLyBhbmQgdGhlIGZ1bmN0aW9uIHRoYXQgaGFuZGxlcyByZWNlaXZlZCBtZXNzYWdlc1xuZnVuY3Rpb24gb25NZXNzYWdlQ2FsbGJhY2soZGF0YSkge1xuICAgIC8vIFwiY2FuY2VsXCIgYnV0dG9uIGlzIGNsaWNrZWRcbiAgICBpZiAoZGF0YSA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJykge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InO1xuICAgICAgICBpZiAoc2NyZWVuQ2FsbGJhY2spXG4gICAgICAgICAgICByZXR1cm4gc2NyZWVuQ2FsbGJhY2soJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gbm90aWZpZWQgaGlzIHByZXNlbmNlXG4gICAgaWYgKGRhdGEgPT0gJ3J0Y211bHRpY29ubmVjdGlvbi1leHRlbnNpb24tbG9hZGVkJykge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdkZXNrdG9wJztcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIHNoYXJlZCB0ZW1wIHNvdXJjZUlkXG4gICAgaWYgKGRhdGEuc291cmNlSWQgJiYgc2NyZWVuQ2FsbGJhY2spIHtcbiAgICAgICAgc2NyZWVuQ2FsbGJhY2soc291cmNlSWQgPSBkYXRhLnNvdXJjZUlkKTtcbiAgICB9XG59XG5cbi8vIHRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIHRvIGNoZWNrIGlmIGNocm9tZSBleHRlbnNpb24gaXMgaW5zdGFsbGVkICYgZW5hYmxlZC5cbmZ1bmN0aW9uIGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlKGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGZhbHNlKTtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKVxuICAgICAgICByZXR1cm4gY2FsbGJhY2soJ2lzRmlyZWZveCcpO1xuICAgIC8vIGFzayBleHRlbnNpb24gaWYgaXQgaXMgYXZhaWxhYmxlXG4gICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICBjYWxsYmFjaygndW5hdmFpbGFibGUnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBjYWxsYmFjaygnYXZhaWxhYmxlJyk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnYWpoaWZkZGlta2FwZ2NpZmdjb2RtbWZkbGtuYWhmZmsnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhleHRlbnNpb25pZCA9PSBleHRlbnNpb25pZCA/ICdpbnN0YWxsZWQtZW5hYmxlZCcgOiAnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIH0sIDIwMDApO1xuICAgIH07XG4gICAgaW1hZ2Uub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2FsbGJhY2soJ25vdC1pbnN0YWxsZWQnKTtcbiAgICB9O1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaykge1xuICAgIHNvdXJjZUlkID0gJyc7XG4gICAgdmFyIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyA9IHtcbiAgICAgICAgbW96TWVkaWFTb3VyY2U6ICd3aW5kb3cnLFxuICAgICAgICBtZWRpYVNvdXJjZTogJ3dpbmRvdydcbiAgICB9O1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMpO1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IGRlZmluZXMgZ2V0VXNlck1lZGlhIGNvbnN0cmFpbnRzXG4gICAgLy8gdGhhdCB3aWxsIGJlIHVzZWQgdG8gY2FwdHVyZSBjb250ZW50IG9mIHNjcmVlblxuICAgIHZhciBzY3JlZW5fY29uc3RyYWludHMgPSB7XG4gICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGNocm9tZU1lZGlhU291cmNlLFxuICAgICAgICAgICAgbWF4V2lkdGg6IHNjcmVlbi53aWR0aCA+IDE5MjAgPyBzY3JlZW4ud2lkdGggOiAxOTIwLFxuICAgICAgICAgICAgbWF4SGVpZ2h0OiBzY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHNjcmVlbi5oZWlnaHQgOiAxMDgwXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbmFsOiBbXVxuICAgIH07XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgdmVyaWZpZXMgY2hyb21lIGV4dGVuc2lvbiBhdmFpbGFiaWxpdHlcbiAgICAvLyBpZiBpbnN0YWxsZWQgYW5kIGF2YWlsYWJsZSB0aGVuIGl0IHdpbGwgaW52b2tlIGV4dGVuc2lvbiBBUElcbiAgICAvLyBvdGhlcndpc2UgaXQgd2lsbCBmYWxsYmFjayB0byBjb21tYW5kLWxpbmUgYmFzZWQgc2NyZWVuIGNhcHR1cmluZyBBUElcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnICYmICFzb3VyY2VJZCkge1xuICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG4gICAgLy8gbm93IGludm9raW5nIG5hdGl2ZSBnZXRVc2VyTWVkaWEgQVBJXG4gICAgY2FsbGJhY2sobnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50cyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzO1xuZXhwb3J0cy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSA9IGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG5leHBvcnRzLmdldFNvdXJjZUlkID0gZ2V0U291cmNlSWQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vLyB0c2xpbnQ6ZGlzYWJsZTpuby1zdHJpbmctbGl0ZXJhbFxuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0ICogYXMgYWRhcHRlciBmcm9tICd3ZWJydGMtYWRhcHRlcic7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5leHBvcnQgY2xhc3MgV2ViUnRjU3RhdHMge1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0VuYWJsZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzSW50ZXJ2YWxJZDogTm9kZUpTLlRpbWVyO1xuICAgIHByaXZhdGUgc3RhdHNJbnRlcnZhbCA9IDE7XG4gICAgcHJpdmF0ZSBzdGF0czogYW55ID0ge1xuICAgICAgICBpbmJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvdXRib3VuZDoge1xuICAgICAgICAgICAgYXVkaW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IDAsXG4gICAgICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogMCxcbiAgICAgICAgICAgICAgICBuYWNrQ291bnQ6IDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7IH1cblxuICAgIHB1YmxpYyBpc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZDtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2VsYXN0ZXN0LWluc3RydW1lbnRhdGlvbicpO1xuXG4gICAgICAgIGlmIChlbGFzdGVzdEluc3RydW1lbnRhdGlvbikge1xuICAgICAgICAgICAgLy8gRWxhc1Rlc3QgaW5zdHJ1bWVudGF0aW9uIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBjb25zdCBpbnN0cnVtZW50YXRpb24gPSBKU09OLnBhcnNlKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHNJbnRlcnZhbCA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaW50ZXJ2YWw7ICAvLyBJbnRlcnZhbCBpbiBzZWNvbmRzXG5cbiAgICAgICAgICAgIGNvbnNvbGUud2FybignbG9jYWxTdG9yYWdlIGl0ZW06ICcgKyBKU09OLnN0cmluZ2lmeShpbnN0cnVtZW50YXRpb24pKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1dlYlJ0YyBzdGF0cyBub3QgZW5hYmxlZCcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wV2ViUnRjU3RhdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHNlbmRQb3N0ID0gKGpzb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGh0dHA6IFhNTEh0dHBSZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICBjb25zdCB1cmw6IHN0cmluZyA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaHR0cEVuZHBvaW50O1xuICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgdXJsLCB0cnVlKTtcblxuICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKCdDb250ZW50LXR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuXG4gICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHsgLy8gQ2FsbCBhIGZ1bmN0aW9uIHdoZW4gdGhlIHN0YXRlIGNoYW5nZXMuXG4gICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCAmJiBodHRwLnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdXZWJSdGMgc3RhdHMgc3VjY2Vzc2Z1bGx5IHNlbnQgdG8gJyArIHVybCArICcgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaHR0cC5zZW5kKGpzb24pO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGYgPSAoc3RhdHMpID0+IHtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBzdGF0cy5mb3JFYWNoKChzdGF0KSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGpzb24gPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoKHN0YXQudHlwZSA9PT0gJ2luYm91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IG91dGJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5uYWNrQ291bnQgIT09IG51bGwgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5yZW1vdGVJZC5zdGFydHNXaXRoKCdpbmJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgaml0ID0gc3RhdC5qaXR0ZXIgKiAxMDAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IChzdGF0LmJ5dGVzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogaml0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6ICdtcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snbmFja0NvdW50J10gPSAoc3RhdC5uYWNrQ291bnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ25hY2tDb3VudCddID0gJ3BhY2tldHMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQubmFja0NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCA9IHN0YXQucGFja2V0c1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKHN0YXQudHlwZSA9PT0gJ291dGJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBpbmJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ291dGJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX291dGJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IChzdGF0LnBhY2tldHNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQgPSBzdGF0LmZyYW1lc0VuY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQgPSBzdGF0LnBhY2tldHNTZW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhzdGF0cykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdCA9IHN0YXRzW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdzc3JjJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2J5dGVzUmVjZWl2ZWQnIGluIHN0YXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ2F1ZGlvJyAmJiAnYXVkaW9PdXRwdXRMZXZlbCcgaW4gc3RhdCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycgJiYgJ3FwU3VtJyBpbiBzdGF0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluYm91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogKHN0YXQuYnl0ZXNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogc3RhdC5nb29nSml0dGVyQnVmZmVyTXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogJ21zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWyduYWNrQ291bnQnXSA9IChzdGF0Lmdvb2dOYWNrc1NlbnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snbmFja0NvdW50J10gPSAncGFja2V0cyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lmdvb2dOYWNrc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkID0gc3RhdC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCdieXRlc1NlbnQnIGluIHN0YXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdXRib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfb3V0Ym91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogKHN0YXQucGFja2V0c1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCA9IHN0YXQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzU2VudCA9IHN0YXQucGFja2V0c1NlbnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5nZXRTdGF0c0Fnbm9zdGljKHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCksIGYsIChlcnJvcikgPT4geyBjb25zb2xlLmxvZyhlcnJvcik7IH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2goKHJlcG9ydCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RhbmRhcmRTdGF0cyA9IHtcbiAgICAgICAgICAgICAgICBpZDogcmVwb3J0LmlkLFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogcmVwb3J0LnRpbWVzdGFtcCxcbiAgICAgICAgICAgICAgICB0eXBlOiByZXBvcnQudHlwZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcG9ydC5uYW1lcygpLmZvckVhY2goKG5hbWUpID0+IHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFN0YXRzW25hbWVdID0gcmVwb3J0LnN0YXQobmFtZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHN0YW5kYXJkUmVwb3J0W3N0YW5kYXJkU3RhdHMuaWRdID0gc3RhbmRhcmRTdGF0cztcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHN0YW5kYXJkUmVwb3J0O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0U3RhdHNBZ25vc3RpYyhwYywgc3VjY2Vzc0NiLCBmYWlsdXJlQ2IpIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIGdldFN0YXRzIHRha2VzIGFyZ3MgaW4gZGlmZmVyZW50IG9yZGVyIGluIENocm9tZSBhbmQgRmlyZWZveFxuICAgICAgICAgICAgcmV0dXJuIHBjLmdldFN0YXRzKG51bGwsIChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcG9ydCA9IHRoaXMuc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYihyZXBvcnQpO1xuICAgICAgICAgICAgfSwgZmFpbHVyZUNiKTtcbiAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdDaHJvbWUnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIEluIENocm9tZSwgdGhlIGZpcnN0IHR3byBhcmd1bWVudHMgYXJlIHJldmVyc2VkXG4gICAgICAgICAgICByZXR1cm4gcGMuZ2V0U3RhdHMoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwb3J0ID0gdGhpcy5zdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NiKHJlcG9ydCk7XG4gICAgICAgICAgICB9LCBudWxsLCBmYWlsdXJlQ2IpO1xuICAgICAgICB9XG4gICAgfVxuXG59Il19 diff --git a/openvidu-mvc-node/public/openvidu-browser-2.2.0.js b/openvidu-mvc-node/public/openvidu-browser-2.2.0.js new file mode 100644 index 00000000..e57248f3 --- /dev/null +++ b/openvidu-mvc-node/public/openvidu-browser-2.2.0.js @@ -0,0 +1,7371 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1) + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Unhandled "error" event. (' + er + ')'); + err.context = er; + throw err; + } + return false; + } + + handler = events[type]; + + if (!handler) + return false; + + var isFn = typeof handler === 'function'; + len = arguments.length; + switch (len) { + // fast cases + case 1: + emitNone(handler, isFn, this); + break; + case 2: + emitOne(handler, isFn, this, arguments[1]); + break; + case 3: + emitTwo(handler, isFn, this, arguments[1], arguments[2]); + break; + case 4: + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + emitMany(handler, isFn, this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = target._events; + if (!events) { + events = target._events = objectCreate(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (!existing) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + } else { + // If we've already got an array, just append. + if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + } + + // Check for listener leak + if (!existing.warned) { + m = $getMaxListeners(target); + if (m && m > 0 && existing.length > m) { + existing.warned = true; + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' "' + String(type) + '" listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit.'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + if (typeof console === 'object' && console.warn) { + console.warn('%s: %s', w.name, w.message); + } + } + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + switch (arguments.length) { + case 0: + return this.listener.call(this.target); + case 1: + return this.listener.call(this.target, arguments[0]); + case 2: + return this.listener.call(this.target, arguments[0], arguments[1]); + case 3: + return this.listener.call(this.target, arguments[0], arguments[1], + arguments[2]); + default: + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) + args[i] = arguments[i]; + this.listener.apply(this.target, args); + } + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = bind.call(onceWrapper, state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = this._events; + if (!events) + return this; + + list = events[type]; + if (!list) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else + spliceOne(list, position); + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (!events) + return this; + + // not listening for removeListener, no need to emit + if (!events.removeListener) { + if (arguments.length === 0) { + this._events = objectCreate(null); + this._eventsCount = 0; + } else if (events[type]) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = objectKeys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = objectCreate(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (!events) + return []; + + var evlistener = events[type]; + if (!evlistener) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function objectCreatePolyfill(proto) { + var F = function() {}; + F.prototype = proto; + return new F; +} +function objectKeysPolyfill(obj) { + var keys = []; + for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { + keys.push(k); + } + return k; +} +function functionBindPolyfill(context) { + var fn = this; + return function () { + return fn.apply(context, arguments); + }; +} + +},{}],2:[function(require,module,exports){ +/* jshint node: true */ +'use strict'; + +var normalice = require('normalice'); + +/** + # freeice + + The `freeice` module is a simple way of getting random STUN or TURN server + for your WebRTC application. The list of servers (just STUN at this stage) + were sourced from this [gist](https://gist.github.com/zziuni/3741933). + + ## Example Use + + The following demonstrates how you can use `freeice` with + [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): + + <<< examples/quickconnect.js + + As the `freeice` module generates ice servers in a list compliant with the + WebRTC spec you will be able to use it with raw `RTCPeerConnection` + constructors and other WebRTC libraries. + + ## Hey, don't use my STUN/TURN server! + + If for some reason your free STUN or TURN server ends up in the + list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or + [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) + that is used in this module, you can feel + free to open an issue on this repository and those servers will be removed + within 24 hours (or sooner). This is the quickest and probably the most + polite way to have something removed (and provides us some visibility + if someone opens a pull request requesting that a server is added). + + ## Please add my server! + + If you have a server that you wish to add to the list, that's awesome! I'm + sure I speak on behalf of a whole pile of WebRTC developers who say thanks. + To get it into the list, feel free to either open a pull request or if you + find that process a bit daunting then just create an issue requesting + the addition of the server (make sure you provide all the details, and if + you have a Terms of Service then including that in the PR/issue would be + awesome). + + ## I know of a free server, can I add it? + + Sure, if you do your homework and make sure it is ok to use (I'm currently + in the process of reviewing the terms of those STUN servers included from + the original list). If it's ok to go, then please see the previous entry + for how to add it. + + ## Current List of Servers + + * current as at the time of last `README.md` file generation + + ### STUN + + <<< stun.json + + ### TURN + + <<< turn.json + +**/ + +var freeice = module.exports = function(opts) { + // if a list of servers has been provided, then use it instead of defaults + var servers = { + stun: (opts || {}).stun || require('./stun.json'), + turn: (opts || {}).turn || require('./turn.json') + }; + + var stunCount = (opts || {}).stunCount || 2; + var turnCount = (opts || {}).turnCount || 0; + var selected; + + function getServers(type, count) { + var out = []; + var input = [].concat(servers[type]); + var idx; + + while (input.length && out.length < count) { + idx = (Math.random() * input.length) | 0; + out = out.concat(input.splice(idx, 1)); + } + + return out.map(function(url) { + //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up + if ((typeof url !== 'string') && (! (url instanceof String))) { + return url; + } else { + return normalice(type + ':' + url); + } + }); + } + + // add stun servers + selected = [].concat(getServers('stun', stunCount)); + + if (turnCount) { + selected = selected.concat(getServers('turn', turnCount)); + } + + return selected; +}; + +},{"./stun.json":3,"./turn.json":4,"normalice":7}],3:[function(require,module,exports){ +module.exports=[ + "stun.l.google.com:19302", + "stun1.l.google.com:19302", + "stun2.l.google.com:19302", + "stun3.l.google.com:19302", + "stun4.l.google.com:19302", + "stun.ekiga.net", + "stun.ideasip.com", + "stun.schlund.de", + "stun.stunprotocol.org:3478", + "stun.voiparound.com", + "stun.voipbuster.com", + "stun.voipstunt.com", + "stun.voxgratia.org", + "stun.services.mozilla.com" +] + +},{}],4:[function(require,module,exports){ +module.exports=[] + +},{}],5:[function(require,module,exports){ +var WildEmitter = require('wildemitter'); + +function getMaxVolume (analyser, fftBins) { + var maxVolume = -Infinity; + analyser.getFloatFrequencyData(fftBins); + + for(var i=4, ii=fftBins.length; i < ii; i++) { + if (fftBins[i] > maxVolume && fftBins[i] < 0) { + maxVolume = fftBins[i]; + } + }; + + return maxVolume; +} + + +var audioContextType; +if (typeof window !== 'undefined') { + audioContextType = window.AudioContext || window.webkitAudioContext; +} +// use a single audio context due to hardware limits +var audioContext = null; +module.exports = function(stream, options) { + var harker = new WildEmitter(); + + + // make it not break in non-supported browsers + if (!audioContextType) return harker; + + //Config + var options = options || {}, + smoothing = (options.smoothing || 0.1), + interval = (options.interval || 50), + threshold = options.threshold, + play = options.play, + history = options.history || 10, + running = true; + + //Setup Audio Context + if (!audioContext) { + audioContext = new audioContextType(); + } + var sourceNode, fftBins, analyser; + + analyser = audioContext.createAnalyser(); + analyser.fftSize = 512; + analyser.smoothingTimeConstant = smoothing; + fftBins = new Float32Array(analyser.frequencyBinCount); + + if (stream.jquery) stream = stream[0]; + if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { + //Audio Tag + sourceNode = audioContext.createMediaElementSource(stream); + if (typeof play === 'undefined') play = true; + threshold = threshold || -50; + } else { + //WebRTC Stream + sourceNode = audioContext.createMediaStreamSource(stream); + threshold = threshold || -50; + } + + sourceNode.connect(analyser); + if (play) analyser.connect(audioContext.destination); + + harker.speaking = false; + + harker.suspend = function() { + audioContext.suspend(); + } + harker.resume = function() { + audioContext.resume(); + } + Object.defineProperty(harker, 'state', { get: function() { + return audioContext.state; + }}); + audioContext.onstatechange = function() { + harker.emit('state_change', audioContext.state); + } + + harker.setThreshold = function(t) { + threshold = t; + }; + + harker.setInterval = function(i) { + interval = i; + }; + + harker.stop = function() { + running = false; + harker.emit('volume_change', -100, threshold); + if (harker.speaking) { + harker.speaking = false; + harker.emit('stopped_speaking'); + } + analyser.disconnect(); + sourceNode.disconnect(); + }; + harker.speakingHistory = []; + for (var i = 0; i < history; i++) { + harker.speakingHistory.push(0); + } + + // Poll the analyser node to determine if speaking + // and emit events if changed + var looper = function() { + setTimeout(function() { + + //check if stop has been called + if(!running) { + return; + } + + var currentVolume = getMaxVolume(analyser, fftBins); + + harker.emit('volume_change', currentVolume, threshold); + + var history = 0; + if (currentVolume > threshold && !harker.speaking) { + // trigger quickly, short history + for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { + history += harker.speakingHistory[i]; + } + if (history >= 2) { + harker.speaking = true; + harker.emit('speaking'); + } + } else if (currentVolume < threshold && harker.speaking) { + for (var i = 0; i < harker.speakingHistory.length; i++) { + history += harker.speakingHistory[i]; + } + if (history == 0) { + harker.speaking = false; + harker.emit('stopped_speaking'); + } + } + harker.speakingHistory.shift(); + harker.speakingHistory.push(0 + (currentVolume > threshold)); + + looper(); + }, interval); + }; + looper(); + + + return harker; +} + +},{"wildemitter":14}],6:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],7:[function(require,module,exports){ +/** + # normalice + + Normalize an ice server configuration object (or plain old string) into a format + that is usable in all browsers supporting WebRTC. Primarily this module is designed + to help with the transition of the `url` attribute of the configuration object to + the `urls` attribute. + + ## Example Usage + + <<< examples/simple.js + +**/ + +var protocols = [ + 'stun:', + 'turn:' +]; + +module.exports = function(input) { + var url = (input || {}).url || input; + var protocol; + var parts; + var output = {}; + + // if we don't have a string url, then allow the input to passthrough + if (typeof url != 'string' && (! (url instanceof String))) { + return input; + } + + // trim the url string, and convert to an array + url = url.trim(); + + // if the protocol is not known, then passthrough + protocol = protocols[protocols.indexOf(url.slice(0, 5))]; + if (! protocol) { + return input; + } + + // now let's attack the remaining url parts + url = url.slice(5); + parts = url.split('@'); + + output.username = input.username; + output.credential = input.credential; + // if we have an authentication part, then set the credentials + if (parts.length > 1) { + url = parts[1]; + parts = parts[0].split(':'); + + // add the output credential and username + output.username = parts[0]; + output.credential = (input || {}).credential || parts[1] || ''; + } + + output.url = protocol + url; + output.urls = [ output.url ]; + + return output; +}; + +},{}],8:[function(require,module,exports){ +(function (global){ +/*! + * Platform.js + * Copyright 2014-2018 Benjamin Tan + * Copyright 2011-2013 John-David Dalton + * Available under MIT license + */ +;(function() { + 'use strict'; + + /** Used to determine if values are of the language type `Object`. */ + var objectTypes = { + 'function': true, + 'object': true + }; + + /** Used as a reference to the global object. */ + var root = (objectTypes[typeof window] && window) || this; + + /** Backup possible global object. */ + var oldRoot = root; + + /** Detect free variable `exports`. */ + var freeExports = objectTypes[typeof exports] && exports; + + /** Detect free variable `module`. */ + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + + /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ + var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; + if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { + root = freeGlobal; + } + + /** + * Used as the maximum length of an array-like object. + * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) + * for more details. + */ + var maxSafeInteger = Math.pow(2, 53) - 1; + + /** Regular expression to detect Opera. */ + var reOpera = /\bOpera/; + + /** Possible global object. */ + var thisBinding = this; + + /** Used for native method references. */ + var objectProto = Object.prototype; + + /** Used to check for own properties of an object. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to resolve the internal `[[Class]]` of values. */ + var toString = objectProto.toString; + + /*--------------------------------------------------------------------------*/ + + /** + * Capitalizes a string value. + * + * @private + * @param {string} string The string to capitalize. + * @returns {string} The capitalized string. + */ + function capitalize(string) { + string = String(string); + return string.charAt(0).toUpperCase() + string.slice(1); + } + + /** + * A utility function to clean up the OS name. + * + * @private + * @param {string} os The OS name to clean up. + * @param {string} [pattern] A `RegExp` pattern matching the OS name. + * @param {string} [label] A label for the OS. + */ + function cleanupOS(os, pattern, label) { + // Platform tokens are defined at: + // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + var data = { + '10.0': '10', + '6.4': '10 Technical Preview', + '6.3': '8.1', + '6.2': '8', + '6.1': 'Server 2008 R2 / 7', + '6.0': 'Server 2008 / Vista', + '5.2': 'Server 2003 / XP 64-bit', + '5.1': 'XP', + '5.01': '2000 SP1', + '5.0': '2000', + '4.0': 'NT', + '4.90': 'ME' + }; + // Detect Windows version from platform tokens. + if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && + (data = data[/[\d.]+$/.exec(os)])) { + os = 'Windows ' + data; + } + // Correct character case and cleanup string. + os = String(os); + + if (pattern && label) { + os = os.replace(RegExp(pattern, 'i'), label); + } + + os = format( + os.replace(/ ce$/i, ' CE') + .replace(/\bhpw/i, 'web') + .replace(/\bMacintosh\b/, 'Mac OS') + .replace(/_PowerPC\b/i, ' OS') + .replace(/\b(OS X) [^ \d]+/i, '$1') + .replace(/\bMac (OS X)\b/, '$1') + .replace(/\/(\d)/, ' $1') + .replace(/_/g, '.') + .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') + .replace(/\bx86\.64\b/gi, 'x86_64') + .replace(/\b(Windows Phone) OS\b/, '$1') + .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') + .split(' on ')[0] + ); + + return os; + } + + /** + * An iteration utility for arrays and objects. + * + * @private + * @param {Array|Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + */ + function each(object, callback) { + var index = -1, + length = object ? object.length : 0; + + if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { + while (++index < length) { + callback(object[index], index, object); + } + } else { + forOwn(object, callback); + } + } + + /** + * Trim and conditionally capitalize string values. + * + * @private + * @param {string} string The string to format. + * @returns {string} The formatted string. + */ + function format(string) { + string = trim(string); + return /^(?:webOS|i(?:OS|P))/.test(string) + ? string + : capitalize(string); + } + + /** + * Iterates over an object's own properties, executing the `callback` for each. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function executed per own property. + */ + function forOwn(object, callback) { + for (var key in object) { + if (hasOwnProperty.call(object, key)) { + callback(object[key], key, object); + } + } + } + + /** + * Gets the internal `[[Class]]` of a value. + * + * @private + * @param {*} value The value. + * @returns {string} The `[[Class]]`. + */ + function getClassOf(value) { + return value == null + ? capitalize(value) + : toString.call(value).slice(8, -1); + } + + /** + * Host objects can return type values that are different from their actual + * data type. The objects we are concerned with usually return non-primitive + * types of "object", "function", or "unknown". + * + * @private + * @param {*} object The owner of the property. + * @param {string} property The property to check. + * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. + */ + function isHostType(object, property) { + var type = object != null ? typeof object[property] : 'number'; + return !/^(?:boolean|number|string|undefined)$/.test(type) && + (type == 'object' ? !!object[property] : true); + } + + /** + * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. + * + * @private + * @param {string} string The string to qualify. + * @returns {string} The qualified string. + */ + function qualify(string) { + return String(string).replace(/([ -])(?!$)/g, '$1?'); + } + + /** + * A bare-bones `Array#reduce` like utility function. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @returns {*} The accumulated result. + */ + function reduce(array, callback) { + var accumulator = null; + each(array, function(value, index) { + accumulator = callback(accumulator, value, index, array); + }); + return accumulator; + } + + /** + * Removes leading and trailing whitespace from a string. + * + * @private + * @param {string} string The string to trim. + * @returns {string} The trimmed string. + */ + function trim(string) { + return String(string).replace(/^ +| +$/g, ''); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a new platform object. + * + * @memberOf platform + * @param {Object|string} [ua=navigator.userAgent] The user agent string or + * context object. + * @returns {Object} A platform object. + */ + function parse(ua) { + + /** The environment context object. */ + var context = root; + + /** Used to flag when a custom context is provided. */ + var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; + + // Juggle arguments. + if (isCustomContext) { + context = ua; + ua = null; + } + + /** Browser navigator object. */ + var nav = context.navigator || {}; + + /** Browser user agent string. */ + var userAgent = nav.userAgent || ''; + + ua || (ua = userAgent); + + /** Used to flag when `thisBinding` is the [ModuleScope]. */ + var isModuleScope = isCustomContext || thisBinding == oldRoot; + + /** Used to detect if browser is like Chrome. */ + var likeChrome = isCustomContext + ? !!nav.likeChrome + : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); + + /** Internal `[[Class]]` value shortcuts. */ + var objectClass = 'Object', + airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', + enviroClass = isCustomContext ? objectClass : 'Environment', + javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), + phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; + + /** Detect Java environments. */ + var java = /\bJava/.test(javaClass) && context.java; + + /** Detect Rhino. */ + var rhino = java && getClassOf(context.environment) == enviroClass; + + /** A character to represent alpha. */ + var alpha = java ? 'a' : '\u03b1'; + + /** A character to represent beta. */ + var beta = java ? 'b' : '\u03b2'; + + /** Browser document object. */ + var doc = context.document || {}; + + /** + * Detect Opera browser (Presto-based). + * http://www.howtocreate.co.uk/operaStuff/operaObject.html + * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini + */ + var opera = context.operamini || context.opera; + + /** Opera `[[Class]]`. */ + var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) + ? operaClass + : (opera = null); + + /*------------------------------------------------------------------------*/ + + /** Temporary variable used over the script's lifetime. */ + var data; + + /** The CPU architecture. */ + var arch = ua; + + /** Platform description array. */ + var description = []; + + /** Platform alpha/beta indicator. */ + var prerelease = null; + + /** A flag to indicate that environment features should be used to resolve the platform. */ + var useFeatures = ua == userAgent; + + /** The browser/environment version. */ + var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); + + /** A flag to indicate if the OS ends with "/ Version" */ + var isSpecialCasedOS; + + /* Detectable layout engines (order is important). */ + var layout = getLayout([ + { 'label': 'EdgeHTML', 'pattern': 'Edge' }, + 'Trident', + { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, + 'iCab', + 'Presto', + 'NetFront', + 'Tasman', + 'KHTML', + 'Gecko' + ]); + + /* Detectable browser names (order is important). */ + var name = getName([ + 'Adobe AIR', + 'Arora', + 'Avant Browser', + 'Breach', + 'Camino', + 'Electron', + 'Epiphany', + 'Fennec', + 'Flock', + 'Galeon', + 'GreenBrowser', + 'iCab', + 'Iceweasel', + 'K-Meleon', + 'Konqueror', + 'Lunascape', + 'Maxthon', + { 'label': 'Microsoft Edge', 'pattern': 'Edge' }, + 'Midori', + 'Nook Browser', + 'PaleMoon', + 'PhantomJS', + 'Raven', + 'Rekonq', + 'RockMelt', + { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' }, + 'SeaMonkey', + { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Sleipnir', + 'SlimBrowser', + { 'label': 'SRWare Iron', 'pattern': 'Iron' }, + 'Sunrise', + 'Swiftfox', + 'Waterfox', + 'WebPositive', + 'Opera Mini', + { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, + 'Opera', + { 'label': 'Opera', 'pattern': 'OPR' }, + 'Chrome', + { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, + { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, + { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' }, + { 'label': 'IE', 'pattern': 'IEMobile' }, + { 'label': 'IE', 'pattern': 'MSIE' }, + 'Safari' + ]); + + /* Detectable products (order is important). */ + var product = getProduct([ + { 'label': 'BlackBerry', 'pattern': 'BB10' }, + 'BlackBerry', + { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, + { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, + { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, + { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, + { 'label': 'Galaxy S5', 'pattern': 'SM-G900' }, + { 'label': 'Galaxy S6', 'pattern': 'SM-G920' }, + { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' }, + { 'label': 'Galaxy S7', 'pattern': 'SM-G930' }, + { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' }, + 'Google TV', + 'Lumia', + 'iPad', + 'iPod', + 'iPhone', + 'Kindle', + { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Nexus', + 'Nook', + 'PlayBook', + 'PlayStation Vita', + 'PlayStation', + 'TouchPad', + 'Transformer', + { 'label': 'Wii U', 'pattern': 'WiiU' }, + 'Wii', + 'Xbox One', + { 'label': 'Xbox 360', 'pattern': 'Xbox' }, + 'Xoom' + ]); + + /* Detectable manufacturers. */ + var manufacturer = getManufacturer({ + 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, + 'Archos': {}, + 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, + 'Asus': { 'Transformer': 1 }, + 'Barnes & Noble': { 'Nook': 1 }, + 'BlackBerry': { 'PlayBook': 1 }, + 'Google': { 'Google TV': 1, 'Nexus': 1 }, + 'HP': { 'TouchPad': 1 }, + 'HTC': {}, + 'LG': {}, + 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, + 'Motorola': { 'Xoom': 1 }, + 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, + 'Nokia': { 'Lumia': 1 }, + 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, + 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 } + }); + + /* Detectable operating systems (order is important). */ + var os = getOS([ + 'Windows Phone', + 'Android', + 'CentOS', + { 'label': 'Chrome OS', 'pattern': 'CrOS' }, + 'Debian', + 'Fedora', + 'FreeBSD', + 'Gentoo', + 'Haiku', + 'Kubuntu', + 'Linux Mint', + 'OpenBSD', + 'Red Hat', + 'SuSE', + 'Ubuntu', + 'Xubuntu', + 'Cygwin', + 'Symbian OS', + 'hpwOS', + 'webOS ', + 'webOS', + 'Tablet OS', + 'Tizen', + 'Linux', + 'Mac OS X', + 'Macintosh', + 'Mac', + 'Windows 98;', + 'Windows ' + ]); + + /*------------------------------------------------------------------------*/ + + /** + * Picks the layout engine from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected layout engine. + */ + function getLayout(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the manufacturer from an array of guesses. + * + * @private + * @param {Array} guesses An object of guesses. + * @returns {null|string} The detected manufacturer. + */ + function getManufacturer(guesses) { + return reduce(guesses, function(result, value, key) { + // Lookup the manufacturer by product or scan the UA for the manufacturer. + return result || ( + value[product] || + value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || + RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) + ) && key; + }); + } + + /** + * Picks the browser name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected browser name. + */ + function getName(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the OS name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected OS name. + */ + function getOS(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) + )) { + result = cleanupOS(result, pattern, guess.label || guess); + } + return result; + }); + } + + /** + * Picks the product name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {null|string} The detected product name. + */ + function getProduct(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || + RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) || + RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) + )) { + // Split by forward slash and append product version if needed. + if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { + result[0] += ' ' + result[1]; + } + // Correct character case and cleanup string. + guess = guess.label || guess; + result = format(result[0] + .replace(RegExp(pattern, 'i'), guess) + .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') + .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); + } + return result; + }); + } + + /** + * Resolves the version using an array of UA patterns. + * + * @private + * @param {Array} patterns An array of UA patterns. + * @returns {null|string} The detected version. + */ + function getVersion(patterns) { + return reduce(patterns, function(result, pattern) { + return result || (RegExp(pattern + + '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; + }); + } + + /** + * Returns `platform.description` when the platform object is coerced to a string. + * + * @name toString + * @memberOf platform + * @returns {string} Returns `platform.description` if available, else an empty string. + */ + function toStringPlatform() { + return this.description || ''; + } + + /*------------------------------------------------------------------------*/ + + // Convert layout to an array so we can add extra details. + layout && (layout = [layout]); + + // Detect product names that contain their manufacturer's name. + if (manufacturer && !product) { + product = getProduct([manufacturer]); + } + // Clean up Google TV. + if ((data = /\bGoogle TV\b/.exec(product))) { + product = data[0]; + } + // Detect simulators. + if (/\bSimulator\b/i.test(ua)) { + product = (product ? product + ' ' : '') + 'Simulator'; + } + // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. + if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { + description.push('running in Turbo/Uncompressed mode'); + } + // Detect IE Mobile 11. + if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) { + data = parse(ua.replace(/like iPhone OS/, '')); + manufacturer = data.manufacturer; + product = data.product; + } + // Detect iOS. + else if (/^iP/.test(product)) { + name || (name = 'Safari'); + os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) + ? ' ' + data[1].replace(/_/g, '.') + : ''); + } + // Detect Kubuntu. + else if (name == 'Konqueror' && !/buntu/i.test(os)) { + os = 'Kubuntu'; + } + // Detect Android browsers. + else if ((manufacturer && manufacturer != 'Google' && + ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) || + (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) { + name = 'Android Browser'; + os = /\bAndroid\b/.test(os) ? os : 'Android'; + } + // Detect Silk desktop/accelerated modes. + else if (name == 'Silk') { + if (!/\bMobi/i.test(ua)) { + os = 'Android'; + description.unshift('desktop mode'); + } + if (/Accelerated *= *true/i.test(ua)) { + description.unshift('accelerated'); + } + } + // Detect PaleMoon identifying as Firefox. + else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { + description.push('identifying as Firefox ' + data[1]); + } + // Detect Firefox OS and products running Firefox. + else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { + os || (os = 'Firefox OS'); + product || (product = data[1]); + } + // Detect false positives for Firefox/Safari. + else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { + // Escape the `/` for Firefox 1. + if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { + // Clear name of false positives. + name = null; + } + // Reassign a generic name. + if ((data = product || manufacturer || os) && + (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { + name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; + } + } + // Add Chrome version to description for Electron. + else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) { + description.push('Chromium ' + data); + } + // Detect non-Opera (Presto-based) versions (order is important). + if (!version) { + version = getVersion([ + '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))', + 'Version', + qualify(name), + '(?:Firefox|Minefield|NetFront)' + ]); + } + // Detect stubborn layout engines. + if ((data = + layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || + /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || + /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || + !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || + layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' + )) { + layout = [data]; + } + // Detect Windows Phone 7 desktop mode. + if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { + name += ' Mobile'; + os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); + description.unshift('desktop mode'); + } + // Detect Windows Phone 8.x desktop mode. + else if (/\bWPDesktop\b/i.test(ua)) { + name = 'IE Mobile'; + os = 'Windows Phone 8.x'; + description.unshift('desktop mode'); + version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); + } + // Detect IE 11 identifying as other browsers. + else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { + if (name) { + description.push('identifying as ' + name + (version ? ' ' + version : '')); + } + name = 'IE'; + version = data[1]; + } + // Leverage environment features. + if (useFeatures) { + // Detect server-side environments. + // Rhino has a global function while others have a global object. + if (isHostType(context, 'global')) { + if (java) { + data = java.lang.System; + arch = data.getProperty('os.arch'); + os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); + } + if (rhino) { + try { + version = context.require('ringo/engine').version.join('.'); + name = 'RingoJS'; + } catch(e) { + if ((data = context.system) && data.global.system == context.system) { + name = 'Narwhal'; + os || (os = data[0].os || null); + } + } + if (!name) { + name = 'Rhino'; + } + } + else if ( + typeof context.process == 'object' && !context.process.browser && + (data = context.process) + ) { + if (typeof data.versions == 'object') { + if (typeof data.versions.electron == 'string') { + description.push('Node ' + data.versions.node); + name = 'Electron'; + version = data.versions.electron; + } else if (typeof data.versions.nw == 'string') { + description.push('Chromium ' + version, 'Node ' + data.versions.node); + name = 'NW.js'; + version = data.versions.nw; + } + } + if (!name) { + name = 'Node.js'; + arch = data.arch; + os = data.platform; + version = /[\d.]+/.exec(data.version); + version = version ? version[0] : null; + } + } + } + // Detect Adobe AIR. + else if (getClassOf((data = context.runtime)) == airRuntimeClass) { + name = 'Adobe AIR'; + os = data.flash.system.Capabilities.os; + } + // Detect PhantomJS. + else if (getClassOf((data = context.phantom)) == phantomClass) { + name = 'PhantomJS'; + version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); + } + // Detect IE compatibility modes. + else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { + // We're in compatibility mode when the Trident version + 4 doesn't + // equal the document mode. + version = [version, doc.documentMode]; + if ((data = +data[1] + 4) != version[1]) { + description.push('IE ' + version[1] + ' mode'); + layout && (layout[1] = ''); + version[1] = data; + } + version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; + } + // Detect IE 11 masking as other browsers. + else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) { + description.push('masking as ' + name + ' ' + version); + name = 'IE'; + version = '11.0'; + layout = ['Trident']; + os = 'Windows'; + } + os = os && format(os); + } + // Detect prerelease phases. + if (version && (data = + /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || + /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || + /\bMinefield\b/i.test(ua) && 'a' + )) { + prerelease = /b/i.test(data) ? 'beta' : 'alpha'; + version = version.replace(RegExp(data + '\\+?$'), '') + + (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); + } + // Detect Firefox Mobile. + if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) { + name = 'Firefox Mobile'; + } + // Obscure Maxthon's unreliable version. + else if (name == 'Maxthon' && version) { + version = version.replace(/\.[\d.]+/, '.x'); + } + // Detect Xbox 360 and Xbox One. + else if (/\bXbox\b/i.test(product)) { + if (product == 'Xbox 360') { + os = null; + } + if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { + description.unshift('mobile mode'); + } + } + // Add mobile postfix. + else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && + (os == 'Windows CE' || /Mobi/i.test(ua))) { + name += ' Mobile'; + } + // Detect IE platform preview. + else if (name == 'IE' && useFeatures) { + try { + if (context.external === null) { + description.unshift('platform preview'); + } + } catch(e) { + description.unshift('embedded'); + } + } + // Detect BlackBerry OS version. + // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp + else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = + (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || + version + )) { + data = [data, /BB10/.test(ua)]; + os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; + version = null; + } + // Detect Opera identifying/masking itself as another browser. + // http://www.opera.com/support/kb/view/843/ + else if (this != forOwn && product != 'Wii' && ( + (useFeatures && opera) || + (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || + (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || + (name == 'IE' && ( + (os && !/^Win/.test(os) && version > 5.5) || + /\bWindows XP\b/.test(os) && version > 8 || + version == 8 && !/\bTrident\b/.test(ua) + )) + ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { + // When "identifying", the UA contains both Opera and the other browser's name. + data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); + if (reOpera.test(name)) { + if (/\bIE\b/.test(data) && os == 'Mac OS') { + os = null; + } + data = 'identify' + data; + } + // When "masking", the UA contains only the other browser's name. + else { + data = 'mask' + data; + if (operaClass) { + name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); + } else { + name = 'Opera'; + } + if (/\bIE\b/.test(data)) { + os = null; + } + if (!useFeatures) { + version = null; + } + } + layout = ['Presto']; + description.push(data); + } + // Detect WebKit Nightly and approximate Chrome/Safari versions. + if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { + // Correct build number for numeric comparison. + // (e.g. "532.5" becomes "532.05") + data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; + // Nightly builds are postfixed with a "+". + if (name == 'Safari' && data[1].slice(-1) == '+') { + name = 'WebKit Nightly'; + prerelease = 'alpha'; + version = data[1].slice(0, -1); + } + // Clear incorrect browser versions. + else if (version == data[1] || + version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { + version = null; + } + // Use the full Chrome version when available. + data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]; + // Detect Blink layout engine. + if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { + layout = ['Blink']; + } + // Detect JavaScriptCore. + // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi + if (!useFeatures || (!likeChrome && !data[1])) { + layout && (layout[1] = 'like Safari'); + data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8'); + } else { + layout && (layout[1] = 'like Chrome'); + data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); + } + // Add the postfix of ".x" or "+" for approximate versions. + layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); + // Obscure version for some Safari 1-2 releases. + if (name == 'Safari' && (!version || parseInt(version) > 45)) { + version = data; + } + } + // Detect Opera desktop modes. + if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { + name += ' '; + description.unshift('desktop mode'); + if (data == 'zvav') { + name += 'Mini'; + version = null; + } else { + name += 'Mobile'; + } + os = os.replace(RegExp(' *' + data + '$'), ''); + } + // Detect Chrome desktop mode. + else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { + description.unshift('desktop mode'); + name = 'Chrome Mobile'; + version = null; + + if (/\bOS X\b/.test(os)) { + manufacturer = 'Apple'; + os = 'iOS 4.3+'; + } else { + os = null; + } + } + // Strip incorrect OS versions. + if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && + ua.indexOf('/' + data + '-') > -1) { + os = trim(os.replace(data, '')); + } + // Add layout engine. + if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( + /Browser|Lunascape|Maxthon/.test(name) || + name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || + /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) { + // Don't add layout details to description if they are falsey. + (data = layout[layout.length - 1]) && description.push(data); + } + // Combine contextual information. + if (description.length) { + description = ['(' + description.join('; ') + ')']; + } + // Append manufacturer to description. + if (manufacturer && product && product.indexOf(manufacturer) < 0) { + description.push('on ' + manufacturer); + } + // Append product to description. + if (product) { + description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); + } + // Parse the OS into an object. + if (os) { + data = / ([\d.+]+)$/.exec(os); + isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; + os = { + 'architecture': 32, + 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, + 'version': data ? data[1] : null, + 'toString': function() { + var version = this.version; + return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); + } + }; + } + // Add browser/OS architecture. + if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { + if (os) { + os.architecture = 64; + os.family = os.family.replace(RegExp(' *' + data), ''); + } + if ( + name && (/\bWOW64\b/i.test(ua) || + (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) + ) { + description.unshift('32-bit'); + } + } + // Chrome 39 and above on OS X is always 64-bit. + else if ( + os && /^OS X/.test(os.family) && + name == 'Chrome' && parseFloat(version) >= 39 + ) { + os.architecture = 64; + } + + ua || (ua = null); + + /*------------------------------------------------------------------------*/ + + /** + * The platform object. + * + * @name platform + * @type Object + */ + var platform = {}; + + /** + * The platform description. + * + * @memberOf platform + * @type string|null + */ + platform.description = ua; + + /** + * The name of the browser's layout engine. + * + * The list of common layout engines include: + * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit" + * + * @memberOf platform + * @type string|null + */ + platform.layout = layout && layout[0]; + + /** + * The name of the product's manufacturer. + * + * The list of manufacturers include: + * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry", + * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo", + * "Nokia", "Samsung" and "Sony" + * + * @memberOf platform + * @type string|null + */ + platform.manufacturer = manufacturer; + + /** + * The name of the browser/environment. + * + * The list of common browser names include: + * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE", + * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk", + * "Opera Mini" and "Opera" + * + * Mobile versions of some browsers have "Mobile" appended to their name: + * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile" + * + * @memberOf platform + * @type string|null + */ + platform.name = name; + + /** + * The alpha/beta release indicator. + * + * @memberOf platform + * @type string|null + */ + platform.prerelease = prerelease; + + /** + * The name of the product hosting the browser. + * + * The list of common products include: + * + * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle", + * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer" + * + * @memberOf platform + * @type string|null + */ + platform.product = product; + + /** + * The browser's user agent string. + * + * @memberOf platform + * @type string|null + */ + platform.ua = ua; + + /** + * The browser/environment version. + * + * @memberOf platform + * @type string|null + */ + platform.version = name && version; + + /** + * The name of the operating system. + * + * @memberOf platform + * @type Object + */ + platform.os = os || { + + /** + * The CPU architecture the OS is built for. + * + * @memberOf platform.os + * @type number|null + */ + 'architecture': null, + + /** + * The family of the OS. + * + * Common values include: + * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", + * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", + * "Android", "iOS" and "Windows Phone" + * + * @memberOf platform.os + * @type string|null + */ + 'family': null, + + /** + * The version of the OS. + * + * @memberOf platform.os + * @type string|null + */ + 'version': null, + + /** + * Returns the OS string. + * + * @memberOf platform.os + * @returns {string} The OS string. + */ + 'toString': function() { return 'null'; } + }; + + platform.parse = parse; + platform.toString = toStringPlatform; + + if (platform.version) { + description.unshift(version); + } + if (platform.name) { + description.unshift(name); + } + if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { + description.push(product ? '(' + os + ')' : 'on ' + os); + } + if (description.length) { + platform.description = description.join(' '); + } + return platform; + } + + /*--------------------------------------------------------------------------*/ + + // Export platform. + var platform = parse(); + + // Some AMD build optimizers, like r.js, check for condition patterns like the following: + if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // Expose platform on the global object to prevent errors when platform is + // loaded by a script tag in the presence of an AMD loader. + // See http://requirejs.org/docs/errors.html#mismatch for more details. + root.platform = platform; + + // Define as an anonymous module so platform can be aliased through path mapping. + define(function() { + return platform; + }); + } + // Check for `exports` after `define` in case a build optimizer adds an `exports` object. + else if (freeExports && freeModule) { + // Export for CommonJS support. + forOwn(platform, function(value, key) { + freeExports[key] = value; + }); + } + else { + // Export to the global object. + root.platform = platform; + } +}.call(this)); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],9:[function(require,module,exports){ +var v1 = require('./v1'); +var v4 = require('./v4'); + +var uuid = v4; +uuid.v1 = v1; +uuid.v4 = v4; + +module.exports = uuid; + +},{"./v1":12,"./v4":13}],10:[function(require,module,exports){ +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +var byteToHex = []; +for (var i = 0; i < 256; ++i) { + byteToHex[i] = (i + 0x100).toString(16).substr(1); +} + +function bytesToUuid(buf, offset) { + var i = offset || 0; + var bth = byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; +} + +module.exports = bytesToUuid; + +},{}],11:[function(require,module,exports){ +// Unique ID creation requires a high quality random # generator. In the +// browser this is a little complicated due to unknown quality of Math.random() +// and inconsistent support for the `crypto` API. We do the best we can via +// feature-detection + +// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. +var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) || + (typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto)); +if (getRandomValues) { + // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto + var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef + + module.exports = function whatwgRNG() { + getRandomValues(rnds8); + return rnds8; + }; +} else { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var rnds = new Array(16); + + module.exports = function mathRNG() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return rnds; + }; +} + +},{}],12:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html + +var _nodeId; +var _clockseq; + +// Previous uuid creation time +var _lastMSecs = 0; +var _lastNSecs = 0; + +// See https://github.com/broofa/node-uuid for API details +function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + var node = options.node || _nodeId; + var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; + + // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + if (node == null || clockseq == null) { + var seedBytes = rng(); + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [ + seedBytes[0] | 0x01, + seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] + ]; + } + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + for (var n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf ? buf : bytesToUuid(b); +} + +module.exports = v1; + +},{"./lib/bytesToUuid":10,"./lib/rng":11}],13:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +function v4(options, buf, offset) { + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options === 'binary' ? new Array(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ++ii) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || bytesToUuid(rnds); +} + +module.exports = v4; + +},{"./lib/bytesToUuid":10,"./lib/rng":11}],14:[function(require,module,exports){ +/* +WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based +on @visionmedia's Emitter from UI Kit. + +Why? I wanted it standalone. + +I also wanted support for wildcard emitters like this: + +emitter.on('*', function (eventName, other, event, payloads) { + +}); + +emitter.on('somenamespace*', function (eventName, payloads) { + +}); + +Please note that callbacks triggered by wildcard registered events also get +the event name as the first argument. +*/ + +module.exports = WildEmitter; + +function WildEmitter() { } + +WildEmitter.mixin = function (constructor) { + var prototype = constructor.prototype || constructor; + + prototype.isWildEmitter= true; + + // Listen on the given `event` with `fn`. Store a group name if present. + prototype.on = function (event, groupName, fn) { + this.callbacks = this.callbacks || {}; + var hasGroup = (arguments.length === 3), + group = hasGroup ? arguments[1] : undefined, + func = hasGroup ? arguments[2] : arguments[1]; + func._groupName = group; + (this.callbacks[event] = this.callbacks[event] || []).push(func); + return this; + }; + + // Adds an `event` listener that will be invoked a single + // time then automatically removed. + prototype.once = function (event, groupName, fn) { + var self = this, + hasGroup = (arguments.length === 3), + group = hasGroup ? arguments[1] : undefined, + func = hasGroup ? arguments[2] : arguments[1]; + function on() { + self.off(event, on); + func.apply(this, arguments); + } + this.on(event, group, on); + return this; + }; + + // Unbinds an entire group + prototype.releaseGroup = function (groupName) { + this.callbacks = this.callbacks || {}; + var item, i, len, handlers; + for (item in this.callbacks) { + handlers = this.callbacks[item]; + for (i = 0, len = handlers.length; i < len; i++) { + if (handlers[i]._groupName === groupName) { + //console.log('removing'); + // remove it and shorten the array we're looping through + handlers.splice(i, 1); + i--; + len--; + } + } + } + return this; + }; + + // Remove the given callback for `event` or all + // registered callbacks. + prototype.off = function (event, fn) { + this.callbacks = this.callbacks || {}; + var callbacks = this.callbacks[event], + i; + + if (!callbacks) return this; + + // remove all handlers + if (arguments.length === 1) { + delete this.callbacks[event]; + return this; + } + + // remove specific handler + i = callbacks.indexOf(fn); + callbacks.splice(i, 1); + if (callbacks.length === 0) { + delete this.callbacks[event]; + } + return this; + }; + + /// Emit `event` with the given args. + // also calls any `*` handlers + prototype.emit = function (event) { + this.callbacks = this.callbacks || {}; + var args = [].slice.call(arguments, 1), + callbacks = this.callbacks[event], + specialCallbacks = this.getWildcardCallbacks(event), + i, + len, + item, + listeners; + + if (callbacks) { + listeners = callbacks.slice(); + for (i = 0, len = listeners.length; i < len; ++i) { + if (!listeners[i]) { + break; + } + listeners[i].apply(this, args); + } + } + + if (specialCallbacks) { + len = specialCallbacks.length; + listeners = specialCallbacks.slice(); + for (i = 0, len = listeners.length; i < len; ++i) { + if (!listeners[i]) { + break; + } + listeners[i].apply(this, [event].concat(args)); + } + } + + return this; + }; + + // Helper for for finding special wildcard event handlers that match the event + prototype.getWildcardCallbacks = function (eventName) { + this.callbacks = this.callbacks || {}; + var item, + split, + result = []; + + for (item in this.callbacks) { + split = item.split('*'); + if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { + result = result.concat(this.callbacks[item]); + } + } + return result; + }; + +}; + +WildEmitter.mixin(WildEmitter); + +},{}],15:[function(require,module,exports){ +/*! + * EventEmitter v5.2.4 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - http://oli.me.uk/ + * @preserve + */ + +;(function (exports) { + 'use strict'; + + /** + * Class for managing events. + * Can be extended to provide event functionality in other classes. + * + * @class EventEmitter Manages event registering and emitting. + */ + function EventEmitter() {} + + // Shortcuts to improve speed and size + var proto = EventEmitter.prototype; + var originalGlobalValue = exports.EventEmitter; + + /** + * Finds the index of the listener for the event in its storage array. + * + * @param {Function[]} listeners Array of listeners to search through. + * @param {Function} listener Method to look for. + * @return {Number} Index of the specified listener, -1 if not found + * @api private + */ + function indexOfListener(listeners, listener) { + var i = listeners.length; + while (i--) { + if (listeners[i].listener === listener) { + return i; + } + } + + return -1; + } + + /** + * Alias a method while keeping the context correct, to allow for overwriting of target method. + * + * @param {String} name The name of the target method. + * @return {Function} The aliased method + * @api private + */ + function alias(name) { + return function aliasClosure() { + return this[name].apply(this, arguments); + }; + } + + /** + * Returns the listener array for the specified event. + * Will initialise the event object and listener arrays if required. + * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. + * Each property in the object response is an array of listener functions. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Function[]|Object} All listener functions for the event. + */ + proto.getListeners = function getListeners(evt) { + var events = this._getEvents(); + var response; + var key; + + // Return a concatenated array of all matching events if + // the selector is a regular expression. + if (evt instanceof RegExp) { + response = {}; + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + response[key] = events[key]; + } + } + } + else { + response = events[evt] || (events[evt] = []); + } + + return response; + }; + + /** + * Takes a list of listener objects and flattens it into a list of listener functions. + * + * @param {Object[]} listeners Raw listener objects. + * @return {Function[]} Just the listener functions. + */ + proto.flattenListeners = function flattenListeners(listeners) { + var flatListeners = []; + var i; + + for (i = 0; i < listeners.length; i += 1) { + flatListeners.push(listeners[i].listener); + } + + return flatListeners; + }; + + /** + * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Object} All listener functions for an event in an object. + */ + proto.getListenersAsObject = function getListenersAsObject(evt) { + var listeners = this.getListeners(evt); + var response; + + if (listeners instanceof Array) { + response = {}; + response[evt] = listeners; + } + + return response || listeners; + }; + + function isValidListener (listener) { + if (typeof listener === 'function' || listener instanceof RegExp) { + return true + } else if (listener && typeof listener === 'object') { + return isValidListener(listener.listener) + } else { + return false + } + } + + /** + * Adds a listener function to the specified event. + * The listener will not be added if it is a duplicate. + * If the listener returns true then it will be removed after it is called. + * If you pass a regular expression as the event name then the listener will be added to all events that match it. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListener = function addListener(evt, listener) { + if (!isValidListener(listener)) { + throw new TypeError('listener must be a function'); + } + + var listeners = this.getListenersAsObject(evt); + var listenerIsWrapped = typeof listener === 'object'; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { + listeners[key].push(listenerIsWrapped ? listener : { + listener: listener, + once: false + }); + } + } + + return this; + }; + + /** + * Alias of addListener + */ + proto.on = alias('addListener'); + + /** + * Semi-alias of addListener. It will add a listener that will be + * automatically removed after its first execution. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addOnceListener = function addOnceListener(evt, listener) { + return this.addListener(evt, { + listener: listener, + once: true + }); + }; + + /** + * Alias of addOnceListener. + */ + proto.once = alias('addOnceListener'); + + /** + * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. + * You need to tell it what event names should be matched by a regex. + * + * @param {String} evt Name of the event to create. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvent = function defineEvent(evt) { + this.getListeners(evt); + return this; + }; + + /** + * Uses defineEvent to define multiple events. + * + * @param {String[]} evts An array of event names to define. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvents = function defineEvents(evts) { + for (var i = 0; i < evts.length; i += 1) { + this.defineEvent(evts[i]); + } + return this; + }; + + /** + * Removes a listener function from the specified event. + * When passed a regular expression as the event name, it will remove the listener from all events that match it. + * + * @param {String|RegExp} evt Name of the event to remove the listener from. + * @param {Function} listener Method to remove from the event. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListener = function removeListener(evt, listener) { + var listeners = this.getListenersAsObject(evt); + var index; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key)) { + index = indexOfListener(listeners[key], listener); + + if (index !== -1) { + listeners[key].splice(index, 1); + } + } + } + + return this; + }; + + /** + * Alias of removeListener + */ + proto.off = alias('removeListener'); + + /** + * Adds listeners in bulk using the manipulateListeners method. + * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. + * You can also pass it a regular expression to add the array of listeners to all events that match it. + * Yeah, this function does quite a bit. That's probably a bad thing. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListeners = function addListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(false, evt, listeners); + }; + + /** + * Removes listeners in bulk using the manipulateListeners method. + * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be removed. + * You can also pass it a regular expression to remove the listeners from all events that match it. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListeners = function removeListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(true, evt, listeners); + }; + + /** + * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. + * The first argument will determine if the listeners are removed (true) or added (false). + * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be added/removed. + * You can also pass it a regular expression to manipulate the listeners of all events that match it. + * + * @param {Boolean} remove True if you want to remove listeners, false if you want to add. + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add/remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { + var i; + var value; + var single = remove ? this.removeListener : this.addListener; + var multiple = remove ? this.removeListeners : this.addListeners; + + // If evt is an object then pass each of its properties to this method + if (typeof evt === 'object' && !(evt instanceof RegExp)) { + for (i in evt) { + if (evt.hasOwnProperty(i) && (value = evt[i])) { + // Pass the single listener straight through to the singular method + if (typeof value === 'function') { + single.call(this, i, value); + } + else { + // Otherwise pass back to the multiple function + multiple.call(this, i, value); + } + } + } + } + else { + // So evt must be a string + // And listeners must be an array of listeners + // Loop over it and pass each one to the multiple method + i = listeners.length; + while (i--) { + single.call(this, evt, listeners[i]); + } + } + + return this; + }; + + /** + * Removes all listeners from a specified event. + * If you do not specify an event then all listeners will be removed. + * That means every event will be emptied. + * You can also pass a regex to remove all events that match it. + * + * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeEvent = function removeEvent(evt) { + var type = typeof evt; + var events = this._getEvents(); + var key; + + // Remove different things depending on the state of evt + if (type === 'string') { + // Remove all listeners for the specified event + delete events[evt]; + } + else if (evt instanceof RegExp) { + // Remove all events matching the regex. + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + delete events[key]; + } + } + } + else { + // Remove all listeners in all events + delete this._events; + } + + return this; + }; + + /** + * Alias of removeEvent. + * + * Added to mirror the node API. + */ + proto.removeAllListeners = alias('removeEvent'); + + /** + * Emits an event of your choice. + * When emitted, every listener attached to that event will be executed. + * If you pass the optional argument array then those arguments will be passed to every listener upon execution. + * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. + * So they will not arrive within the array on the other side, they will be separate. + * You can also pass a regular expression to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {Array} [args] Optional array of arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emitEvent = function emitEvent(evt, args) { + var listenersMap = this.getListenersAsObject(evt); + var listeners; + var listener; + var i; + var key; + var response; + + for (key in listenersMap) { + if (listenersMap.hasOwnProperty(key)) { + listeners = listenersMap[key].slice(0); + + for (i = 0; i < listeners.length; i++) { + // If the listener returns true then it shall be removed from the event + // The function is executed either with a basic call or an apply if there is an args array + listener = listeners[i]; + + if (listener.once === true) { + this.removeListener(evt, listener.listener); + } + + response = listener.listener.apply(this, args || []); + + if (response === this._getOnceReturnValue()) { + this.removeListener(evt, listener.listener); + } + } + } + } + + return this; + }; + + /** + * Alias of emitEvent + */ + proto.trigger = alias('emitEvent'); + + /** + * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. + * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {...*} Optional additional arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emit = function emit(evt) { + var args = Array.prototype.slice.call(arguments, 1); + return this.emitEvent(evt, args); + }; + + /** + * Sets the current value to check against when executing listeners. If a + * listeners return value matches the one set here then it will be removed + * after execution. This value defaults to true. + * + * @param {*} value The new value to check for when executing listeners. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.setOnceReturnValue = function setOnceReturnValue(value) { + this._onceReturnValue = value; + return this; + }; + + /** + * Fetches the current value to check against when executing listeners. If + * the listeners return value matches this one then it should be removed + * automatically. It will return true by default. + * + * @return {*|Boolean} The current value to check for or the default, true. + * @api private + */ + proto._getOnceReturnValue = function _getOnceReturnValue() { + if (this.hasOwnProperty('_onceReturnValue')) { + return this._onceReturnValue; + } + else { + return true; + } + }; + + /** + * Fetches the events object and creates one if required. + * + * @return {Object} The events storage object. + * @api private + */ + proto._getEvents = function _getEvents() { + return this._events || (this._events = {}); + }; + + /** + * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. + * + * @return {Function} Non conflicting EventEmitter class. + */ + EventEmitter.noConflict = function noConflict() { + exports.EventEmitter = originalGlobalValue; + return EventEmitter; + }; + + // Expose the class either via AMD, CommonJS or the global object + if (typeof define === 'function' && define.amd) { + define(function () { + return EventEmitter; + }); + } + else if (typeof module === 'object' && module.exports){ + module.exports = EventEmitter; + } + else { + exports.EventEmitter = EventEmitter; + } +}(this || {})); + +},{}],16:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenVidu_1 = require("./OpenVidu/OpenVidu"); +if (window) { + window['OpenVidu'] = OpenVidu_1.OpenVidu; +} + +},{"./OpenVidu/OpenVidu":19}],17:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Stream_1 = require("./Stream"); +var Connection = (function () { + function Connection(session, opts) { + this.session = session; + this.disposed = false; + var msg = "'Connection' created "; + if (!!opts) { + msg += "(remote) with 'connectionId' [" + opts.id + ']'; + } + else { + msg += '(local)'; + } + console.info(msg); + this.options = opts; + if (!!opts) { + this.connectionId = opts.id; + if (opts.metadata) { + this.data = opts.metadata; + } + if (opts.streams) { + this.initRemoteStreams(opts.streams); + } + } + this.creationTime = new Date().getTime(); + } + Connection.prototype.sendIceCandidate = function (candidate) { + console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate)); + this.session.openvidu.sendRequest('onIceCandidate', { + endpointName: this.connectionId, + candidate: candidate.candidate, + sdpMid: candidate.sdpMid, + sdpMLineIndex: candidate.sdpMLineIndex + }, function (error, response) { + if (error) { + console.error('Error sending ICE candidate: ' + + JSON.stringify(error)); + } + }); + }; + Connection.prototype.initRemoteStreams = function (options) { + var _this = this; + options.forEach(function (opts) { + var streamOptions = { + id: opts.id, + connection: _this, + frameRate: opts.frameRate, + recvAudio: opts.audioActive, + recvVideo: opts.videoActive, + typeOfVideo: opts.typeOfVideo + }; + var stream = new Stream_1.Stream(_this.session, streamOptions); + _this.addStream(stream); + }); + console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); + }; + Connection.prototype.addStream = function (stream) { + stream.connection = this; + this.stream = stream; + }; + Connection.prototype.removeStream = function (streamId) { + delete this.stream; + }; + Connection.prototype.dispose = function () { + if (!!this.stream) { + delete this.stream; + } + this.disposed = true; + }; + return Connection; +}()); +exports.Connection = Connection; + +},{"./Stream":22}],18:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState"); +var LocalRecorder = (function () { + function LocalRecorder(stream) { + this.stream = stream; + this.chunks = []; + this.count = 0; + this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; + this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; + this.state = LocalRecorderState_1.LocalRecorderState.READY; + } + LocalRecorder.prototype.record = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (typeof MediaRecorder === 'undefined') { + console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'); + throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder')); + } + if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) { + throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); + } + console.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'"); + if (typeof MediaRecorder.isTypeSupported === 'function') { + var options = void 0; + if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) { + options = { mimeType: 'video/webm;codecs=vp9' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) { + options = { mimeType: 'video/webm;codecs=h264' }; + } + else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) { + options = { mimeType: 'video/webm;codecs=vp8' }; + } + console.log('Using mimeType ' + options.mimeType); + _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options); + } + else { + console.warn('isTypeSupported is not supported, using default codecs for browser'); + _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream()); + } + _this.mediaRecorder.start(10); + } + catch (err) { + reject(err); + } + _this.mediaRecorder.ondataavailable = function (e) { + _this.chunks.push(e.data); + }; + _this.mediaRecorder.onerror = function (e) { + console.error('MediaRecorder error: ', e); + }; + _this.mediaRecorder.onstart = function () { + console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + }; + _this.mediaRecorder.onpause = function () { + console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onresume = function () { + console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')'); + }; + _this.mediaRecorder.onwarning = function (e) { + console.log('MediaRecorder warning: ' + e); + }; + _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; + resolve(); + }); + }; + LocalRecorder.prototype.stop = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before')); + } + _this.mediaRecorder.onstop = function () { + _this.onStopDefault(); + resolve(); + }; + _this.mediaRecorder.stop(); + } + catch (e) { + reject(e); + } + }); + }; + LocalRecorder.prototype.pause = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) { + reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before')); + } + _this.mediaRecorder.pause(); + _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED; + } + catch (error) { + reject(error); + } + }); + }; + LocalRecorder.prototype.resume = function () { + var _this = this; + return new Promise(function (resolve, reject) { + try { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) { + throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before')); + } + _this.mediaRecorder.resume(); + _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; + } + catch (error) { + reject(error); + } + }); + }; + LocalRecorder.prototype.preview = function (parentElement) { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + this.videoPreview = document.createElement('video'); + this.videoPreview.id = this.id; + this.videoPreview.autoplay = true; + if (typeof parentElement === 'string') { + this.htmlParentElementId = parentElement; + var parentElementDom = document.getElementById(parentElement); + if (parentElementDom) { + this.videoPreview = parentElementDom.appendChild(this.videoPreview); + } + } + else { + this.htmlParentElementId = parentElement.id; + this.videoPreview = parentElement.appendChild(this.videoPreview); + } + this.videoPreview.src = this.videoPreviewSrc; + return this.videoPreview; + }; + LocalRecorder.prototype.clean = function () { + var _this = this; + var f = function () { + delete _this.blob; + _this.chunks = []; + _this.count = 0; + delete _this.mediaRecorder; + _this.state = LocalRecorderState_1.LocalRecorderState.READY; + }; + if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) { + this.stop().then(function () { return f(); }).catch(function () { return f(); }); + } + else { + f(); + } + }; + LocalRecorder.prototype.download = function () { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var a = document.createElement('a'); + a.style.display = 'none'; + document.body.appendChild(a); + var url = window.URL.createObjectURL(this.blob); + a.href = url; + a.download = this.id + '.webm'; + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + } + }; + LocalRecorder.prototype.getBlob = function () { + if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); + } + else { + return this.blob; + } + }; + LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var http_1 = new XMLHttpRequest(); + http_1.open('POST', endpoint, true); + if (typeof headers === 'object') { + for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { + var key = _a[_i]; + http_1.setRequestHeader(key, headers[key]); + } + } + http_1.onreadystatechange = function () { + if (http_1.readyState === 4) { + if (http_1.status.toString().charAt(0) === '2') { + resolve(http_1.responseText); + } + else { + reject(http_1.status); + } + } + }; + http_1.send(_this.blob); + } + }); + }; + LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { + reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); + } + else { + var http_2 = new XMLHttpRequest(); + http_2.open('POST', endpoint, true); + if (typeof headers === 'object') { + for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { + var key = _a[_i]; + http_2.setRequestHeader(key, headers[key]); + } + } + var sendable = new FormData(); + sendable.append('file', _this.blob, _this.id + '.webm'); + http_2.onreadystatechange = function () { + if (http_2.readyState === 4) { + if (http_2.status.toString().charAt(0) === '2') { + resolve(http_2.responseText); + } + else { + reject(http_2.status); + } + } + }; + http_2.send(sendable); + } + }); + }; + LocalRecorder.prototype.onStopDefault = function () { + console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')'); + this.blob = new Blob(this.chunks, { type: 'video/webm' }); + this.chunks = []; + this.videoPreviewSrc = window.URL.createObjectURL(this.blob); + this.state = LocalRecorderState_1.LocalRecorderState.FINISHED; + }; + return LocalRecorder; +}()); +exports.LocalRecorder = LocalRecorder; + +},{"../OpenViduInternal/Enums/LocalRecorderState":25}],19:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorder_1 = require("./LocalRecorder"); +var Publisher_1 = require("./Publisher"); +var Session_1 = require("./Session"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); +var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); +var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); +var platform = require("platform"); +var OpenVidu = (function () { + function OpenVidu() { + this.secret = ''; + this.recorder = false; + this.advancedConfiguration = {}; + console.info("'OpenVidu' initialized"); + } + OpenVidu.prototype.initSession = function () { + this.session = new Session_1.Session(this); + return this.session; + }; + OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) { + var properties; + if (!!param2 && (typeof param2 !== 'function')) { + properties = param2; + properties = { + audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, + frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), + insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, + mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, + publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, + publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, + resolution: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), + videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined + }; + } + else { + properties = { + insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, + mirror: true, + publishAudio: true, + publishVideo: true, + resolution: '640x480' + }; + } + var publisher = new Publisher_1.Publisher(targetElement, properties, this); + var completionHandler; + if (!!param2 && (typeof param2 === 'function')) { + completionHandler = param2; + } + else if (!!param3) { + completionHandler = param3; + } + publisher.initialize() + .then(function () { + if (completionHandler !== undefined) { + completionHandler(undefined); + } + publisher.emitEvent('accessAllowed', []); + }).catch(function (error) { + if (completionHandler !== undefined) { + completionHandler(error); + } + publisher.emitEvent('accessDenied', []); + }); + return publisher; + }; + OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { + var _this = this; + return new Promise(function (resolve, reject) { + var publisher; + var callback = function (error) { + if (!!error) { + reject(error); + } + else { + resolve(publisher); + } + }; + if (!!properties) { + publisher = _this.initPublisher(targetElement, properties, callback); + } + else { + publisher = _this.initPublisher(targetElement, callback); + } + }); + }; + OpenVidu.prototype.initLocalRecorder = function (stream) { + return new LocalRecorder_1.LocalRecorder(stream); + }; + OpenVidu.prototype.checkSystemRequirements = function () { + var browser = platform.name; + var version = platform.version; + if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') && + (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') && + (browser !== 'Opera') && (browser !== 'Opera Mobile') && + (browser !== 'Safari')) { + return 0; + } + else { + return 1; + } + }; + OpenVidu.prototype.getDevices = function () { + return new Promise(function (resolve, reject) { + navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { + var devices = []; + deviceInfos.forEach(function (deviceInfo) { + if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { + devices.push({ + kind: deviceInfo.kind, + deviceId: deviceInfo.deviceId, + label: deviceInfo.label + }); + } + }); + resolve(devices); + }).catch(function (error) { + console.error('Error getting devices', error); + reject(error); + }); + }); + }; + OpenVidu.prototype.getUserMedia = function (options) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.generateMediaConstraints(options) + .then(function (constraints) { + navigator.mediaDevices.getUserMedia(constraints) + .then(function (mediaStream) { + resolve(mediaStream); + }) + .catch(function (error) { + var errorName; + var errorMessage = error.toString(); + if (!(options.videoSource === 'screen')) { + errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; + } + reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + OpenVidu.prototype.enableProdMode = function () { + console.log = function () { }; + console.debug = function () { }; + console.info = function () { }; + console.warn = function () { }; + }; + OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { + this.advancedConfiguration = configuration; + }; + OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { + var _this = this; + return new Promise(function (resolve, reject) { + var audio, video; + if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) { + audio = false; + } + else if (publisherProperties.audioSource === undefined) { + audio = true; + } + else { + audio = publisherProperties.audioSource; + } + if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) { + video = false; + } + else { + video = { + height: { + ideal: 480 + }, + width: { + ideal: 640 + } + }; + } + var mediaConstraints = { + audio: audio, + video: video + }; + if (typeof mediaConstraints.audio === 'string') { + mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } }; + } + if (mediaConstraints.video) { + if (!!publisherProperties.resolution) { + var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); + var width = Number(widthAndHeight[0]); + var height = Number(widthAndHeight[1]); + mediaConstraints.video.width.ideal = width; + mediaConstraints.video.height.ideal = height; + } + if (!!publisherProperties.frameRate) { + mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate }; + } + if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') { + if (publisherProperties.videoSource === 'screen') { + if (platform.name !== 'Chrome' && platform.name.indexOf('Firefox') === -1) { + var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); + console.error(error); + reject(error); + } + else { + if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1)) { + screenSharing.getScreenConstraints(function (error, screenConstraints) { + if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') { + if (error === 'permission-denied' || error === 'PermissionDeniedError') { + var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); + console.error(error_1); + reject(error_1); + } + else { + var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); + screenSharing.getChromeExtensionStatus(extensionId, function (status) { + if (status === 'installed-disabled') { + var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); + console.error(error_2); + reject(error_2); + } + if (status === 'not-installed') { + var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); + console.error(error_3); + reject(error_3); + } + }); + } + } + else { + mediaConstraints.video = screenConstraints; + resolve(mediaConstraints); + } + }); + } + else { + screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { + if (!!error) { + if (error === 'not-installed') { + var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension : + 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold'; + var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl); + console.error(error_4); + reject(error_4); + } + else if (error === 'installed-disabled') { + var error_5 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); + console.error(error_5); + reject(error_5); + } + else if (error === 'permission-denied') { + var error_6 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); + console.error(error_6); + reject(error_6); + } + } + else { + mediaConstraints.video = screenConstraints.video; + resolve(mediaConstraints); + } + }); + } + publisherProperties.videoSource = 'screen'; + } + } + else { + mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource }; + resolve(mediaConstraints); + } + } + else { + resolve(mediaConstraints); + } + } + else { + resolve(mediaConstraints); + } + }); + }; + OpenVidu.prototype.startWs = function (onConnectSucces) { + var config = { + heartbeat: 5000, + sendCloseMessage: false, + ws: { + uri: this.wsUri, + useSockJS: false, + onconnected: onConnectSucces, + ondisconnect: this.disconnectCallback.bind(this), + onreconnecting: this.reconnectingCallback.bind(this), + onreconnected: this.reconnectedCallback.bind(this) + }, + rpc: { + requestTimeout: 10000, + participantJoined: this.session.onParticipantJoined.bind(this.session), + participantPublished: this.session.onParticipantPublished.bind(this.session), + participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), + participantLeft: this.session.onParticipantLeft.bind(this.session), + participantEvicted: this.session.onParticipantEvicted.bind(this.session), + recordingStarted: this.session.onRecordingStarted.bind(this.session), + recordingStopped: this.session.onRecordingStopped.bind(this.session), + sendMessage: this.session.onNewMessage.bind(this.session), + iceCandidate: this.session.recvIceCandidate.bind(this.session), + mediaError: this.session.onMediaError.bind(this.session) + } + }; + this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); + }; + OpenVidu.prototype.closeWs = function () { + this.jsonRpcClient.close(); + }; + OpenVidu.prototype.sendRequest = function (method, params, callback) { + if (params && params instanceof Function) { + callback = params; + params = {}; + } + console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); + this.jsonRpcClient.send(method, params, callback); + }; + OpenVidu.prototype.isMediaStreamTrack = function (mediaSource) { + var is = (!!mediaSource && + mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' && + mediaSource.id !== undefined && typeof mediaSource.id === 'string' && + mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' && + mediaSource.label !== undefined && typeof mediaSource.label === 'string' && + mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' && + mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string'); + return is; + }; + OpenVidu.prototype.getWsUri = function () { + return this.wsUri; + }; + OpenVidu.prototype.getSecret = function () { + return this.secret; + }; + OpenVidu.prototype.getRecorder = function () { + return this.recorder; + }; + OpenVidu.prototype.disconnectCallback = function () { + console.warn('Websocket connection lost'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenVidu.prototype.reconnectingCallback = function () { + console.warn('Websocket connection lost (reconnecting)'); + if (this.isRoomAvailable()) { + this.session.onLostConnection(); + } + else { + alert('Connection error. Please reload page.'); + } + }; + OpenVidu.prototype.reconnectedCallback = function () { + console.warn('Websocket reconnected'); + }; + OpenVidu.prototype.isRoomAvailable = function () { + if (this.session !== undefined && this.session instanceof Session_1.Session) { + return true; + } + else { + console.warn('Session instance not found'); + return false; + } + }; + return OpenVidu; +}()); +exports.OpenVidu = OpenVidu; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":42,"../OpenViduInternal/ScreenSharing/Screen-Capturing":47,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":46,"./LocalRecorder":18,"./Publisher":20,"./Session":21,"platform":8}],20:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Session_1 = require("./Session"); +var Stream_1 = require("./Stream"); +var StreamManager_1 = require("./StreamManager"); +var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); +var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var Publisher = (function (_super) { + __extends(Publisher, _super); + function Publisher(targEl, properties, openvidu) { + var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this; + _this.openvidu = openvidu; + _this.accessAllowed = false; + _this.isSubscribedToRemote = false; + _this.accessDenied = false; + _this.properties = properties; + _this.stream.ee.on('local-stream-destroyed-by-disconnect', function (reason) { + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + }); + return _this; + } + Publisher.prototype.publishAudio = function (value) { + this.stream.getMediaStream().getAudioTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream'); + }; + Publisher.prototype.publishVideo = function (value) { + this.stream.getMediaStream().getVideoTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream'); + }; + Publisher.prototype.subscribeToRemote = function (value) { + value = (value !== undefined) ? value : true; + this.isSubscribedToRemote = value; + this.stream.subscribeToMyRemote(value); + }; + Publisher.prototype.on = function (type, handler) { + var _this = this; + _super.prototype.on.call(this, type, handler); + if (type === 'streamCreated') { + if (!!this.stream && this.stream.isLocalStreamPublished) { + this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); + } + else { + this.stream.ee.on('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); + }); + } + } + if (type === 'remoteVideoPlaying') { + if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); + } + } + if (type === 'accessAllowed') { + if (this.accessAllowed) { + this.ee.emitEvent('accessAllowed'); + } + } + if (type === 'accessDenied') { + if (this.accessDenied) { + this.ee.emitEvent('accessDenied'); + } + } + return this; + }; + Publisher.prototype.once = function (type, handler) { + var _this = this; + _super.prototype.once.call(this, type, handler); + if (type === 'streamCreated') { + if (!!this.stream && this.stream.isLocalStreamPublished) { + this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); + } + else { + this.stream.ee.once('stream-created-by-publisher', function () { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); + }); + } + } + if (type === 'remoteVideoPlaying') { + if (this.stream.displayMyRemote() && this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'remoteVideoPlaying')]); + } + } + if (type === 'accessAllowed') { + if (this.accessAllowed) { + this.ee.emitEvent('accessAllowed'); + } + } + if (type === 'accessDenied') { + if (this.accessDenied) { + this.ee.emitEvent('accessDenied'); + } + } + return this; + }; + Publisher.prototype.initialize = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var errorCallback = function (openViduError) { + _this.accessDenied = true; + _this.accessAllowed = false; + reject(openViduError); + }; + var successCallback = function (mediaStream) { + _this.accessAllowed = true; + _this.accessDenied = false; + if (_this.openvidu.isMediaStreamTrack(_this.properties.audioSource)) { + mediaStream.removeTrack(mediaStream.getAudioTracks()[0]); + mediaStream.addTrack(_this.properties.audioSource); + } + if (_this.openvidu.isMediaStreamTrack(_this.properties.videoSource)) { + mediaStream.removeTrack(mediaStream.getVideoTracks()[0]); + mediaStream.addTrack(_this.properties.videoSource); + } + if (!!mediaStream.getAudioTracks()[0]) { + mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; + } + if (!!mediaStream.getVideoTracks()[0]) { + mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; + } + _this.stream.setMediaStream(mediaStream); + if (!_this.stream.displayMyRemote()) { + _this.stream.updateMediaStreamInVideos(); + } + _this.stream.isLocalStreamReadyToPublish = true; + _this.stream.ee.emitEvent('stream-ready-to-publish', []); + if (!!_this.firstVideoElement) { + _this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode); + } + delete _this.firstVideoElement; + resolve(); + }; + _this.openvidu.generateMediaConstraints(_this.properties) + .then(function (constraints) { + var outboundStreamOptions = { + mediaConstraints: constraints, + publisherProperties: _this.properties + }; + _this.stream.setOutboundStreamOptions(outboundStreamOptions); + var constraintsAux = {}; + var timeForDialogEvent = 1250; + if (_this.stream.isSendVideo() || _this.stream.isSendAudio()) { + var definedAudioConstraint_1 = ((constraints.audio === undefined) ? true : constraints.audio); + constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint_1; + constraintsAux.video = constraints.video; + var startTime_1 = Date.now(); + _this.setPermissionDialogTimer(timeForDialogEvent); + navigator.mediaDevices.getUserMedia(constraintsAux) + .then(function (mediaStream) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) { + constraintsAux.audio = definedAudioConstraint_1; + constraintsAux.video = false; + startTime_1 = Date.now(); + _this.setPermissionDialogTimer(timeForDialogEvent); + navigator.mediaDevices.getUserMedia(constraintsAux) + .then(function (audioOnlyStream) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); + successCallback(mediaStream); + }) + .catch(function (error) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + var errorName, errorMessage; + switch (error.name.toLowerCase()) { + case 'notfounderror': + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'notallowederror': + errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'overconstrainederror': + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = "Audio input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + } + }); + } + else { + successCallback(mediaStream); + } + }) + .catch(function (error) { + _this.clearPermissionDialogTimer(startTime_1, timeForDialogEvent); + var errorName, errorMessage; + switch (error.name.toLowerCase()) { + case 'notfounderror': + navigator.mediaDevices.getUserMedia({ + audio: false, + video: constraints.video + }) + .then(function (mediaStream) { + mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }).catch(function (e) { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + break; + case 'notallowederror': + errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; + errorMessage = error.toString(); + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + break; + case 'overconstrainederror': + navigator.mediaDevices.getUserMedia({ + audio: false, + video: constraints.video + }) + .then(function (mediaStream) { + mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; + errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }).catch(function (e) { + if (error.constraint.toLowerCase() === 'deviceid') { + errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; + errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; + } + else { + errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; + errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; + } + errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); + }); + break; + } + }); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'")); + } + }) + .catch(function (error) { + errorCallback(error); + }); + }); + }; + Publisher.prototype.updateSession = function (session) { + this.session = session; + this.stream.session = session; + }; + Publisher.prototype.emitEvent = function (type, eventArray) { + this.ee.emitEvent(type, eventArray); + }; + Publisher.prototype.reestablishStreamPlayingEvent = function () { + if (this.ee.getListeners('streamPlaying').length > 0) { + this.addPlayEventToFirstVideo(); + } + }; + Publisher.prototype.setPermissionDialogTimer = function (waitTime) { + var _this = this; + this.permissionDialogTimeout = setTimeout(function () { + _this.ee.emitEvent('accessDialogOpened', []); + }, waitTime); + }; + Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) { + clearTimeout(this.permissionDialogTimeout); + if ((Date.now() - startTime) > waitTime) { + this.ee.emitEvent('accessDialogClosed', []); + } + }; + return Publisher; +}(StreamManager_1.StreamManager)); +exports.Publisher = Publisher; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Events/StreamEvent":34,"../OpenViduInternal/Events/VideoElementEvent":36,"./Session":21,"./Stream":22,"./StreamManager":23}],21:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Connection_1 = require("./Connection"); +var Subscriber_1 = require("./Subscriber"); +var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent"); +var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent"); +var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); +var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent"); +var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); +var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var platform = require("platform"); +var EventEmitter = require("wolfy87-eventemitter"); +var Session = (function () { + function Session(openvidu) { + this.streamManagers = []; + this.remoteStreamsCreated = {}; + this.remoteConnections = {}; + this.speakingEventsEnabled = false; + this.ee = new EventEmitter(); + this.openvidu = openvidu; + } + Session.prototype.connect = function (token, metadata) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.processToken(token); + if (_this.openvidu.checkSystemRequirements()) { + _this.options = { + sessionId: _this.sessionId, + participantId: token, + metadata: !!metadata ? _this.stringClientMetadata(metadata) : '' + }; + _this.connectAux(token).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' ' + platform.version + ' is not supported in OpenVidu')); + } + }); + }; + Session.prototype.disconnect = function () { + this.leave(false, 'disconnect'); + }; + Session.prototype.subscribe = function (stream, targetElement, param3, param4) { + var properties = {}; + if (!!param3 && typeof param3 !== 'function') { + properties = { + insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, + subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, + subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true + }; + } + else { + properties = { + insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, + subscribeToAudio: true, + subscribeToVideo: true + }; + } + var completionHandler; + if (!!param3 && (typeof param3 === 'function')) { + completionHandler = param3; + } + else if (!!param4) { + completionHandler = param4; + } + console.info('Subscribing to ' + stream.connection.connectionId); + stream.subscribe() + .then(function () { + console.info('Subscribed correctly to ' + stream.connection.connectionId); + if (completionHandler !== undefined) { + completionHandler(undefined); + } + }) + .catch(function (error) { + if (completionHandler !== undefined) { + completionHandler(error); + } + }); + var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties); + if (!!subscriber.targetElement) { + stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode); + } + return subscriber; + }; + Session.prototype.subscribeAsync = function (stream, targetElement, properties) { + var _this = this; + return new Promise(function (resolve, reject) { + var subscriber; + var callback = function (error) { + if (!!error) { + reject(error); + } + else { + resolve(subscriber); + } + }; + if (!!properties) { + subscriber = _this.subscribe(stream, targetElement, properties, callback); + } + else { + subscriber = _this.subscribe(stream, targetElement, callback); + } + }); + }; + Session.prototype.unsubscribe = function (subscriber) { + var connectionId = subscriber.stream.connection.connectionId; + console.info('Unsubscribing from ' + connectionId); + this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { + if (error) { + console.error('Error unsubscribing from ' + connectionId, error); + } + else { + console.info('Unsubscribed correctly from ' + connectionId); + } + subscriber.stream.disposeWebRtcPeer(); + subscriber.stream.disposeMediaStream(); + }); + subscriber.stream.streamManager.removeAllVideos(); + }; + Session.prototype.publish = function (publisher) { + var _this = this; + return new Promise(function (resolve, reject) { + publisher.session = _this; + publisher.stream.session = _this; + if (!publisher.stream.isLocalStreamPublished) { + _this.connection.addStream(publisher.stream); + publisher.stream.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + } + else { + publisher.initialize() + .then(function () { + _this.connection.addStream(publisher.stream); + publisher.reestablishStreamPlayingEvent(); + publisher.stream.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }).catch(function (error) { + reject(error); + }); + } + }); + }; + Session.prototype.unpublish = function (publisher) { + var stream = publisher.stream; + if (!stream.connection) { + console.error('The associated Connection object of this Publisher is null', stream); + return; + } + else if (stream.connection !== this.connection) { + console.error('The associated Connection object of this Publisher is not your local Connection.' + + "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); + return; + } + else { + console.info('Unpublishing local media (' + stream.connection.connectionId + ')'); + this.openvidu.sendRequest('unpublishVideo', function (error, response) { + if (error) { + console.error(error); + } + else { + console.info('Media unpublished correctly'); + } + }); + stream.disposeWebRtcPeer(); + delete stream.connection.stream; + var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish'); + publisher.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + } + }; + Session.prototype.signal = function (signal) { + var _this = this; + return new Promise(function (resolve, reject) { + var signalMessage = {}; + if (signal.to && signal.to.length > 0) { + var connectionIds_1 = []; + signal.to.forEach(function (connection) { + connectionIds_1.push(connection.connectionId); + }); + signalMessage['to'] = connectionIds_1; + } + else { + signalMessage['to'] = []; + } + signalMessage['data'] = signal.data ? signal.data : ''; + signalMessage['type'] = signal.type ? signal.type : ''; + _this.openvidu.sendRequest('sendMessage', { + message: JSON.stringify(signalMessage) + }, function (error, response) { + if (!!error) { + reject(error); + } + else { + resolve(); + } + }); + }); + }; + Session.prototype.on = function (type, handler) { + this.ee.on(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + type + "' triggered by 'Session'"); + } + handler(event); + }); + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = true; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !str.speechEvent && str.hasAudio) { + str.enableSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.once = function (type, handler) { + this.ee.once(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered by 'Session'", event); + } + else { + console.info("Event '" + type + "' triggered by 'Session'"); + } + handler(event); + }); + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = true; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !str.speechEvent && str.hasAudio) { + str.enableOnceSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.off = function (type, handler) { + if (!handler) { + this.ee.removeAllListeners(type); + } + else { + this.ee.off(type, handler); + } + if (type === 'publisherStartSpeaking' || type === 'publisherStopSpeaking') { + this.speakingEventsEnabled = false; + for (var connectionId in this.remoteConnections) { + var str = this.remoteConnections[connectionId].stream; + if (!!str && !!str.speechEvent) { + str.disableSpeakingEvents(); + } + } + } + return this; + }; + Session.prototype.onParticipantJoined = function (response) { + var _this = this; + this.getConnection(response.id, '') + .then(function (connection) { + console.warn('Connection ' + response.id + ' already exists in connections list'); + }) + .catch(function (openViduError) { + var connection = new Connection_1.Connection(_this, response); + _this.remoteConnections[response.id] = connection; + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); + }); + }; + Session.prototype.onParticipantLeft = function (msg) { + var _this = this; + this.getRemoteConnection(msg.name, 'Remote connection ' + msg.name + " unknown when 'onParticipantLeft'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (connection) { + if (!!connection.stream) { + var stream = connection.stream; + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, msg.reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + delete _this.remoteStreamsCreated[stream.streamId]; + } + delete _this.remoteConnections[connection.connectionId]; + _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, msg.reason)]); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onParticipantPublished = function (response) { + var _this = this; + var afterConnectionFound = function (connection) { + _this.remoteConnections[connection.connectionId] = connection; + if (!_this.remoteStreamsCreated[connection.stream.streamId]) { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]); + } + _this.remoteStreamsCreated[connection.stream.streamId] = true; + }; + var connection; + this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (con) { + connection = con; + response.metadata = con.data; + connection.options = response; + connection.initRemoteStreams(response.streams); + afterConnectionFound(connection); + }) + .catch(function (openViduError) { + connection = new Connection_1.Connection(_this, response); + afterConnectionFound(connection); + }); + }; + Session.prototype.onParticipantUnpublished = function (msg) { + var _this = this; + this.getRemoteConnection(msg.name, "Remote connection '" + msg.name + "' unknown when 'onParticipantUnpublished'. " + + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) + .then(function (connection) { + var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, msg.reason); + _this.ee.emitEvent('streamDestroyed', [streamEvent]); + streamEvent.callDefaultBehaviour(); + var streamId = connection.stream.streamId; + delete _this.remoteStreamsCreated[streamId]; + connection.removeStream(streamId); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onParticipantEvicted = function (msg) { + }; + Session.prototype.onNewMessage = function (msg) { + var _this = this; + console.info('New signal: ' + JSON.stringify(msg)); + this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: " + + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId) + .then(function (connection) { + _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); + _this.ee.emitEvent('signal:' + msg.type, [new SignalEvent_1.SignalEvent(_this, msg.type, msg.data, connection)]); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.recvIceCandidate = function (msg) { + var candidate = { + candidate: msg.candidate, + sdpMid: msg.sdpMid, + sdpMLineIndex: msg.sdpMLineIndex, + toJSON: function () { + return { candidate: msg.candidate }; + } + }; + this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) + .then(function (connection) { + var stream = connection.stream; + stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) { + console.error('Error adding candidate for ' + stream.streamId + + ' stream of endpoint ' + msg.endpointName + ': ' + error); + }); + }) + .catch(function (openViduError) { + console.error(openViduError); + }); + }; + Session.prototype.onSessionClosed = function (msg) { + console.info('Session closed: ' + JSON.stringify(msg)); + var s = msg.room; + if (s !== undefined) { + this.ee.emitEvent('session-closed', [{ + session: s + }]); + } + else { + console.warn('Session undefined on session closed', msg); + } + }; + Session.prototype.onLostConnection = function () { + console.warn('Lost connection in Session ' + this.sessionId); + if (!!this.sessionId && !this.connection.disposed) { + this.leave(true, 'networkDisconnect'); + } + }; + Session.prototype.onMediaError = function (params) { + console.error('Media error: ' + JSON.stringify(params)); + var err = params.error; + if (err) { + this.ee.emitEvent('error-media', [{ + error: err + }]); + } + else { + console.warn('Received undefined media error. Params:', params); + } + }; + Session.prototype.onRecordingStarted = function (response) { + this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', response.id, response.name)]); + }; + Session.prototype.onRecordingStopped = function (response) { + this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', response.id, response.name)]); + }; + Session.prototype.emitEvent = function (type, eventArray) { + this.ee.emitEvent(type, eventArray); + }; + Session.prototype.leave = function (forced, reason) { + var _this = this; + forced = !!forced; + console.info('Leaving Session (forced=' + forced + ')'); + if (!!this.connection) { + if (!this.connection.disposed && !forced) { + this.openvidu.sendRequest('leaveRoom', function (error, response) { + if (error) { + console.error(error); + } + _this.openvidu.closeWs(); + }); + } + else { + this.openvidu.closeWs(); + } + if (!!this.connection.stream) { + this.connection.stream.disposeWebRtcPeer(); + if (this.connection.stream.isLocalStreamPublished) { + this.connection.stream.ee.emitEvent('local-stream-destroyed-by-disconnect', [reason]); + } + } + if (!this.connection.disposed) { + var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason); + this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); + sessionDisconnectEvent.callDefaultBehaviour(); + } + } + else { + console.warn('You were not connected to the session ' + this.sessionId); + } + }; + Session.prototype.connectAux = function (token) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.openvidu.startWs(function (error) { + if (!!error) { + reject(error); + } + else { + var joinParams = { + token: (!!token) ? token : '', + session: _this.sessionId, + metadata: !!_this.options.metadata ? _this.options.metadata : '', + secret: _this.openvidu.getSecret(), + recorder: _this.openvidu.getRecorder(), + }; + _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { + if (!!error) { + reject(error); + } + else { + _this.connection = new Connection_1.Connection(_this); + _this.connection.connectionId = response.id; + _this.connection.data = response.metadata; + var events_1 = { + connections: new Array(), + streams: new Array() + }; + var existingParticipants = response.value; + existingParticipants.forEach(function (participant) { + var connection = new Connection_1.Connection(_this, participant); + _this.remoteConnections[connection.connectionId] = connection; + events_1.connections.push(connection); + if (!!connection.stream) { + _this.remoteStreamsCreated[connection.stream.streamId] = true; + events_1.streams.push(connection.stream); + } + }); + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]); + events_1.connections.forEach(function (connection) { + _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); + }); + events_1.streams.forEach(function (stream) { + _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]); + }); + resolve(); + } + }); + } + }); + }); + }; + Session.prototype.stringClientMetadata = function (metadata) { + if (typeof metadata !== 'string') { + return JSON.stringify(metadata); + } + else { + return metadata; + } + }; + Session.prototype.getConnection = function (connectionId, errorMessage) { + var _this = this; + return new Promise(function (resolve, reject) { + var connection = _this.remoteConnections[connectionId]; + if (!!connection) { + resolve(connection); + } + else { + if (_this.connection.connectionId === connectionId) { + resolve(_this.connection); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); + } + } + }); + }; + Session.prototype.getRemoteConnection = function (connectionId, errorMessage) { + var _this = this; + return new Promise(function (resolve, reject) { + var connection = _this.remoteConnections[connectionId]; + if (!!connection) { + resolve(connection); + } + else { + reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); + } + }); + }; + Session.prototype.processToken = function (token) { + var url = new URL(token); + this.sessionId = url.searchParams.get('sessionId'); + var secret = url.searchParams.get('secret'); + var recorder = url.searchParams.get('recorder'); + var turnUsername = url.searchParams.get('turnUsername'); + var turnCredential = url.searchParams.get('turnCredential'); + var role = url.searchParams.get('role'); + if (!!secret) { + this.openvidu.secret = secret; + } + if (!!recorder) { + this.openvidu.recorder = true; + } + if (!!turnUsername && !!turnCredential) { + var stunUrl = 'stun:' + url.hostname + ':3478'; + var turnUrl1 = 'turn:' + url.hostname + ':3478'; + var turnUrl2 = turnUrl1 + '?transport=tcp'; + this.openvidu.iceServers = [ + { urls: [stunUrl] }, + { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential } + ]; + console.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']'); + } + if (!!role) { + this.openvidu.role = role; + } + this.openvidu.wsUri = 'wss://' + url.host + '/openvidu'; + }; + return Session; +}()); +exports.Session = Session; + +},{"../OpenViduInternal/Enums/OpenViduError":26,"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/ConnectionEvent":28,"../OpenViduInternal/Events/RecordingEvent":31,"../OpenViduInternal/Events/SessionDisconnectedEvent":32,"../OpenViduInternal/Events/SignalEvent":33,"../OpenViduInternal/Events/StreamEvent":34,"./Connection":17,"./Subscriber":24,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer"); +var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats"); +var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent"); +var EventEmitter = require("wolfy87-eventemitter"); +var hark = require("hark"); +var Stream = (function () { + function Stream(session, options) { + var _this = this; + this.ee = new EventEmitter(); + this.isSubscribeToRemote = false; + this.isLocalStreamReadyToPublish = false; + this.isLocalStreamPublished = false; + this.session = session; + if (options.hasOwnProperty('id')) { + this.inboundStreamOpts = options; + this.streamId = this.inboundStreamOpts.id; + this.hasAudio = this.inboundStreamOpts.recvAudio; + this.hasVideo = this.inboundStreamOpts.recvVideo; + this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo; + this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; + } + else { + this.outboundStreamOpts = options; + if (this.isSendVideo()) { + if (this.isSendScreen()) { + this.typeOfVideo = 'SCREEN'; + } + else { + this.typeOfVideo = 'CAMERA'; + } + this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; + } + else { + delete this.typeOfVideo; + } + this.hasAudio = this.isSendAudio(); + this.hasVideo = this.isSendVideo(); + } + this.ee.on('mediastream-updated', function () { + _this.streamManager.updateMediaStream(_this.mediaStream); + console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']'); + }); + } + Stream.prototype.getMediaStream = function () { + return this.mediaStream; + }; + Stream.prototype.setMediaStream = function (mediaStream) { + this.mediaStream = mediaStream; + }; + Stream.prototype.updateMediaStreamInVideos = function () { + this.ee.emitEvent('mediastream-updated'); + }; + Stream.prototype.getWebRtcPeer = function () { + return this.webRtcPeer; + }; + Stream.prototype.getRTCPeerConnection = function () { + return this.webRtcPeer.pc; + }; + Stream.prototype.subscribeToMyRemote = function (value) { + this.isSubscribeToRemote = value; + }; + Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { + this.outboundStreamOpts = outboundStreamOpts; + }; + Stream.prototype.subscribe = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.initWebRtcPeerReceive() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }); + }; + Stream.prototype.publish = function () { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.isLocalStreamReadyToPublish) { + _this.initWebRtcPeerSend() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + } + else { + _this.ee.once('stream-ready-to-publish', function () { + _this.publish() + .then(function () { + resolve(); + }) + .catch(function (error) { + reject(error); + }); + }); + } + }); + }; + Stream.prototype.disposeWebRtcPeer = function () { + if (this.webRtcPeer) { + this.webRtcPeer.dispose(); + } + if (this.speechEvent) { + this.speechEvent.stop(); + } + this.stopWebRtcStats(); + console.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "WebRTCPeer from 'Stream' with id [" + this.streamId + '] is now closed'); + }; + Stream.prototype.disposeMediaStream = function () { + if (this.mediaStream) { + this.mediaStream.getAudioTracks().forEach(function (track) { + track.stop(); + }); + this.mediaStream.getVideoTracks().forEach(function (track) { + track.stop(); + }); + delete this.mediaStream; + } + console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed'); + }; + Stream.prototype.displayMyRemote = function () { + return this.isSubscribeToRemote; + }; + Stream.prototype.isSendAudio = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.audioSource !== null && + this.outboundStreamOpts.publisherProperties.audioSource !== false); + }; + Stream.prototype.isSendVideo = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.videoSource !== null && + this.outboundStreamOpts.publisherProperties.videoSource !== false); + }; + Stream.prototype.isSendScreen = function () { + return (!!this.outboundStreamOpts && + this.outboundStreamOpts.publisherProperties.videoSource === 'screen'); + }; + Stream.prototype.setSpeechEventIfNotExists = function () { + if (!this.speechEvent) { + var harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}; + harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50; + harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50; + this.speechEvent = hark(this.mediaStream, harkOptions); + } + }; + Stream.prototype.enableSpeakingEvents = function () { + var _this = this; + this.setSpeechEventIfNotExists(); + this.speechEvent.on('speaking', function () { + _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); + }); + this.speechEvent.on('stopped_speaking', function () { + _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); + }); + }; + Stream.prototype.enableOnceSpeakingEvents = function () { + var _this = this; + this.setSpeechEventIfNotExists(); + this.speechEvent.on('speaking', function () { + _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); + _this.disableSpeakingEvents(); + }); + this.speechEvent.on('stopped_speaking', function () { + _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); + _this.disableSpeakingEvents(); + }); + }; + Stream.prototype.disableSpeakingEvents = function () { + this.speechEvent.stop(); + this.speechEvent = undefined; + }; + Stream.prototype.isLocal = function () { + return (!this.inboundStreamOpts && !!this.outboundStreamOpts); + }; + Stream.prototype.getSelectedIceCandidate = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.webRtcStats.getSelectedIceCandidateInfo() + .then(function (report) { return resolve(report); }) + .catch(function (error) { return reject(error); }); + }); + }; + Stream.prototype.getRemoteIceCandidateList = function () { + return this.webRtcPeer.remoteCandidatesQueue; + }; + Stream.prototype.getLocalIceCandidateList = function () { + return this.webRtcPeer.localCandidatesQueue; + }; + Stream.prototype.initWebRtcPeerSend = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var userMediaConstraints = { + audio: _this.isSendAudio(), + video: _this.isSendVideo() + }; + var options = { + mediaStream: _this.mediaStream, + mediaConstraints: userMediaConstraints, + onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), + iceServers: _this.getIceServersConf(), + simulcast: false + }; + var successCallback = function (sdpOfferParam) { + console.debug('Sending SDP offer to publish as ' + + _this.streamId, sdpOfferParam); + _this.session.openvidu.sendRequest('publishVideo', { + sdpOffer: sdpOfferParam, + doLoopback: _this.displayMyRemote() || false, + audioActive: _this.isSendAudio(), + videoActive: _this.isSendVideo(), + typeOfVideo: ((_this.isSendVideo()) ? (_this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''), + frameRate: !!_this.frameRate ? _this.frameRate : -1 + }, function (error, response) { + if (error) { + reject('Error on publishVideo: ' + JSON.stringify(error)); + } + else { + _this.webRtcPeer.processAnswer(response.sdpAnswer) + .then(function () { + _this.streamId = response.id; + _this.isLocalStreamPublished = true; + if (_this.displayMyRemote()) { + _this.remotePeerSuccesfullyEstablished(); + } + _this.ee.emitEvent('stream-created-by-publisher'); + _this.initWebRtcStats(); + resolve(); + }) + .catch(function (error) { + reject(error); + }); + console.info("'Publisher' successfully published to session"); + } + }); + }; + if (_this.displayMyRemote()) { + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(options); + } + else { + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(options); + } + _this.webRtcPeer.generateOffer().then(function (offer) { + successCallback(offer); + }).catch(function (error) { + reject(new Error('(publish) SDP offer error: ' + JSON.stringify(error))); + }); + }); + }; + Stream.prototype.initWebRtcPeerReceive = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var offerConstraints = { + audio: _this.inboundStreamOpts.recvAudio, + video: _this.inboundStreamOpts.recvVideo + }; + console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); + var options = { + onicecandidate: _this.connection.sendIceCandidate.bind(_this.connection), + mediaConstraints: offerConstraints, + iceServers: _this.getIceServersConf(), + simulcast: false + }; + var successCallback = function (sdpOfferParam) { + console.debug('Sending SDP offer to subscribe to ' + + _this.streamId, sdpOfferParam); + _this.session.openvidu.sendRequest('receiveVideoFrom', { + sender: _this.streamId, + sdpOffer: sdpOfferParam + }, function (error, response) { + if (error) { + reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error))); + } + else { + _this.webRtcPeer.processAnswer(response.sdpAnswer).then(function () { + _this.remotePeerSuccesfullyEstablished(); + _this.initWebRtcStats(); + resolve(); + }).catch(function (error) { + reject(error); + }); + } + }); + }; + _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(options); + _this.webRtcPeer.generateOffer() + .then(function (offer) { + successCallback(offer); + }) + .catch(function (error) { + reject(new Error('(subscribe) SDP offer error: ' + JSON.stringify(error))); + }); + }); + }; + Stream.prototype.remotePeerSuccesfullyEstablished = function () { + this.mediaStream = this.webRtcPeer.pc.getRemoteStreams()[0]; + console.debug('Peer remote stream', this.mediaStream); + if (!!this.mediaStream) { + this.ee.emitEvent('mediastream-updated'); + if (!this.displayMyRemote() && !!this.mediaStream.getAudioTracks()[0] && this.session.speakingEventsEnabled) { + this.enableSpeakingEvents(); + } + } + }; + Stream.prototype.initWebRtcStats = function () { + this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); + this.webRtcStats.initWebRtcStats(); + }; + Stream.prototype.stopWebRtcStats = function () { + if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { + this.webRtcStats.stopWebRtcStats(); + } + }; + Stream.prototype.getIceServersConf = function () { + var returnValue; + if (!!this.session.openvidu.advancedConfiguration.iceServers) { + returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ? + undefined : + this.session.openvidu.advancedConfiguration.iceServers; + } + else if (this.session.openvidu.iceServers) { + returnValue = this.session.openvidu.iceServers; + } + else { + returnValue = undefined; + } + return returnValue; + }; + return Stream; +}()); +exports.Stream = Stream; + +},{"../OpenViduInternal/Events/PublisherSpeakingEvent":30,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":48,"../OpenViduInternal/WebRtcStats/WebRtcStats":49,"hark":5,"wolfy87-eventemitter":15}],23:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); +var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); +var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); +var EventEmitter = require("wolfy87-eventemitter"); +var StreamManager = (function () { + function StreamManager(stream, targetElement) { + var _this = this; + this.videos = []; + this.lazyLaunchVideoElementCreatedEvent = false; + this.ee = new EventEmitter(); + this.stream = stream; + this.stream.streamManager = this; + this.remote = !this.stream.isLocal(); + if (!!targetElement) { + var targEl = void 0; + if (typeof targetElement === 'string') { + targEl = document.getElementById(targetElement); + } + else if (targetElement instanceof HTMLElement) { + targEl = targetElement; + } + if (!!targEl) { + this.firstVideoElement = { + targetElement: targEl, + video: document.createElement('video'), + id: '' + }; + this.targetElement = targEl; + this.element = targEl; + } + } + this.canPlayListener = function () { + if (_this.stream.isLocal()) { + if (!_this.stream.displayMyRemote()) { + console.info("Your local 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); + } + else { + console.info("Your own remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('remoteVideoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'remoteVideoPlaying')]); + } + } + else { + console.info("Remote 'Stream' with id [" + _this.stream.streamId + '] video is now playing'); + _this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(_this.videos[0].video, _this, 'videoPlaying')]); + } + _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this)]); + }; + } + StreamManager.prototype.on = function (type, handler) { + this.ee.on(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered", event); + } + else { + console.info("Event '" + type + "' triggered"); + } + handler(event); + }); + if (type === 'videoElementCreated') { + if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); + this.lazyLaunchVideoElementCreatedEvent = false; + } + } + if (type === 'streamPlaying' || type === 'videoPlaying') { + if (this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); + this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); + } + } + return this; + }; + StreamManager.prototype.once = function (type, handler) { + this.ee.once(type, function (event) { + if (event) { + console.info("Event '" + type + "' triggered once", event); + } + else { + console.info("Event '" + type + "' triggered once"); + } + handler(event); + }); + if (type === 'videoElementCreated') { + if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); + } + } + if (type === 'streamPlaying' || type === 'videoPlaying') { + if (this.videos[0] && this.videos[0].video && + this.videos[0].video.currentTime > 0 && + this.videos[0].video.paused === false && + this.videos[0].video.ended === false && + this.videos[0].video.readyState === 4) { + this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this)]); + this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]); + } + } + return this; + }; + StreamManager.prototype.off = function (type, handler) { + if (!handler) { + this.ee.removeAllListeners(type); + } + else { + this.ee.off(type, handler); + } + return this; + }; + StreamManager.prototype.addVideoElement = function (video) { + this.initializeVideoProperties(video); + for (var _i = 0, _a = this.videos; _i < _a.length; _i++) { + var v = _a[_i]; + if (v.video === video) { + return 0; + } + } + var returnNumber = 1; + this.initializeVideoProperties(video); + for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) { + var streamManager = _c[_b]; + if (streamManager.disassociateVideo(video)) { + returnNumber = -1; + break; + } + } + this.stream.session.streamManagers.forEach(function (streamManager) { + streamManager.disassociateVideo(video); + }); + this.pushNewStreamManagerVideo({ + video: video, + id: video.id + }); + console.info('New video element associated to ', this); + return returnNumber; + }; + StreamManager.prototype.createVideoElement = function (targetElement, insertMode) { + var targEl; + if (typeof targetElement === 'string') { + targEl = document.getElementById(targEl); + if (!targEl) { + throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); + } + } + else if (targetElement instanceof HTMLElement) { + targEl = targetElement; + } + else { + throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); + } + var video = document.createElement('video'); + this.initializeVideoProperties(video); + var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; + switch (insMode) { + case VideoInsertMode_1.VideoInsertMode.AFTER: + targEl.parentNode.insertBefore(video, targEl.nextSibling); + break; + case VideoInsertMode_1.VideoInsertMode.APPEND: + targEl.appendChild(video); + break; + case VideoInsertMode_1.VideoInsertMode.BEFORE: + targEl.parentNode.insertBefore(video, targEl); + break; + case VideoInsertMode_1.VideoInsertMode.PREPEND: + targEl.insertBefore(video, targEl.childNodes[0]); + break; + case VideoInsertMode_1.VideoInsertMode.REPLACE: + targEl.parentNode.replaceChild(video, targEl); + break; + default: + insMode = VideoInsertMode_1.VideoInsertMode.APPEND; + targEl.appendChild(video); + break; + } + var v = { + targetElement: targEl, + video: video, + insertMode: insMode, + id: video.id + }; + this.pushNewStreamManagerVideo(v); + this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]); + this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement; + return video; + }; + StreamManager.prototype.initializeVideoProperties = function (video) { + video.srcObject = this.stream.getMediaStream(); + video.autoplay = true; + video.controls = false; + if (!video.id) { + video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId; + if (!this.id && !!this.targetElement) { + this.id = video.id; + } + } + if (!this.remote && !this.stream.displayMyRemote()) { + video.muted = true; + if (this.stream.outboundStreamOpts.publisherProperties.mirror) { + this.mirrorVideo(video); + } + } + }; + StreamManager.prototype.removeAllVideos = function () { + var _this = this; + for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) { + if (this.stream.session.streamManagers[i] === this) { + this.stream.session.streamManagers.splice(i, 1); + } + } + this.videos.slice().reverse().forEach(function (streamManagerVideo, index, videos) { + streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener); + if (!!streamManagerVideo.targetElement) { + streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video); + _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]); + _this.videos.splice(videos.length - 1 - index, 1); + } + else { + streamManagerVideo.video.srcObject = null; + } + }); + }; + StreamManager.prototype.disassociateVideo = function (video) { + var disassociated = false; + for (var i = 0; i < this.videos.length; i++) { + if (this.videos[i].video === video) { + this.videos.splice(i, 1); + disassociated = true; + console.info('Video element disassociated from ', this); + break; + } + } + return disassociated; + }; + StreamManager.prototype.addPlayEventToFirstVideo = function () { + if ((!!this.videos[0]) && (!!this.videos[0].video) && (this.videos[0].video.oncanplay === null)) { + this.videos[0].video.addEventListener('canplay', this.canPlayListener); + } + }; + StreamManager.prototype.updateMediaStream = function (mediaStream) { + this.videos.forEach(function (streamManagerVideo) { + streamManagerVideo.video.srcObject = mediaStream; + }); + }; + StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) { + this.videos.push(streamManagerVideo); + this.addPlayEventToFirstVideo(); + if (this.stream.session.streamManagers.indexOf(this) === -1) { + this.stream.session.streamManagers.push(this); + } + }; + StreamManager.prototype.mirrorVideo = function (video) { + video.style.transform = 'rotateY(180deg)'; + video.style.webkitTransform = 'rotateY(180deg)'; + }; + return StreamManager; +}()); +exports.StreamManager = StreamManager; + +},{"../OpenViduInternal/Enums/VideoInsertMode":27,"../OpenViduInternal/Events/StreamManagerEvent":35,"../OpenViduInternal/Events/VideoElementEvent":36,"wolfy87-eventemitter":15}],24:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var StreamManager_1 = require("./StreamManager"); +var Subscriber = (function (_super) { + __extends(Subscriber, _super); + function Subscriber(stream, targEl, properties) { + var _this = _super.call(this, stream, targEl) || this; + _this.element = _this.targetElement; + _this.stream = stream; + _this.properties = properties; + return _this; + } + Subscriber.prototype.subscribeToAudio = function (value) { + this.stream.getMediaStream().getAudioTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream'); + return this; + }; + Subscriber.prototype.subscribeToVideo = function (value) { + this.stream.getMediaStream().getVideoTracks().forEach(function (track) { + track.enabled = value; + }); + console.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream'); + return this; + }; + return Subscriber; +}(StreamManager_1.StreamManager)); +exports.Subscriber = Subscriber; + +},{"./StreamManager":23}],25:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LocalRecorderState; +(function (LocalRecorderState) { + LocalRecorderState["READY"] = "READY"; + LocalRecorderState["RECORDING"] = "RECORDING"; + LocalRecorderState["PAUSED"] = "PAUSED"; + LocalRecorderState["FINISHED"] = "FINISHED"; +})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {})); + +},{}],26:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OpenViduErrorName; +(function (OpenViduErrorName) { + OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; + OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED"; + OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; + OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; + OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; + OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED"; + OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; + OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; + OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; + OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; + OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; + OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED"; + OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; +})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); +var OpenViduError = (function () { + function OpenViduError(name, message) { + this.name = name; + this.message = message; + } + return OpenViduError; +}()); +exports.OpenViduError = OpenViduError; + +},{}],27:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var VideoInsertMode; +(function (VideoInsertMode) { + VideoInsertMode["AFTER"] = "AFTER"; + VideoInsertMode["APPEND"] = "APPEND"; + VideoInsertMode["BEFORE"] = "BEFORE"; + VideoInsertMode["PREPEND"] = "PREPEND"; + VideoInsertMode["REPLACE"] = "REPLACE"; +})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); + +},{}],28:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var ConnectionEvent = (function (_super) { + __extends(ConnectionEvent, _super); + function ConnectionEvent(cancelable, target, type, connection, reason) { + var _this = _super.call(this, cancelable, target, type) || this; + _this.connection = connection; + _this.reason = reason; + return _this; + } + ConnectionEvent.prototype.callDefaultBehaviour = function () { }; + return ConnectionEvent; +}(Event_1.Event)); +exports.ConnectionEvent = ConnectionEvent; + +},{"./Event":29}],29:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Event = (function () { + function Event(cancelable, target, type) { + this.hasBeenPrevented = false; + this.cancelable = cancelable; + this.target = target; + this.type = type; + } + Event.prototype.isDefaultPrevented = function () { + return this.hasBeenPrevented; + }; + Event.prototype.preventDefault = function () { + this.callDefaultBehaviour = function () { }; + this.hasBeenPrevented = true; + }; + return Event; +}()); +exports.Event = Event; + +},{}],30:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var PublisherSpeakingEvent = (function (_super) { + __extends(PublisherSpeakingEvent, _super); + function PublisherSpeakingEvent(target, type, connection, streamId) { + var _this = _super.call(this, false, target, type) || this; + _this.type = type; + _this.connection = connection; + _this.streamId = streamId; + return _this; + } + PublisherSpeakingEvent.prototype.callDefaultBehaviour = function () { }; + return PublisherSpeakingEvent; +}(Event_1.Event)); +exports.PublisherSpeakingEvent = PublisherSpeakingEvent; + +},{"./Event":29}],31:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var RecordingEvent = (function (_super) { + __extends(RecordingEvent, _super); + function RecordingEvent(target, type, id, name) { + var _this = _super.call(this, false, target, type) || this; + _this.id = id; + if (name !== id) { + _this.name = name; + } + return _this; + } + RecordingEvent.prototype.callDefaultBehaviour = function () { }; + return RecordingEvent; +}(Event_1.Event)); +exports.RecordingEvent = RecordingEvent; + +},{"./Event":29}],32:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var SessionDisconnectedEvent = (function (_super) { + __extends(SessionDisconnectedEvent, _super); + function SessionDisconnectedEvent(target, reason) { + var _this = _super.call(this, true, target, 'sessionDisconnected') || this; + _this.reason = reason; + return _this; + } + SessionDisconnectedEvent.prototype.callDefaultBehaviour = function () { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); + var session = this.target; + for (var connectionId in session.remoteConnections) { + if (!!session.remoteConnections[connectionId].stream) { + session.remoteConnections[connectionId].stream.disposeWebRtcPeer(); + session.remoteConnections[connectionId].stream.disposeMediaStream(); + if (session.remoteConnections[connectionId].stream.streamManager) { + session.remoteConnections[connectionId].stream.streamManager.removeAllVideos(); + } + delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId]; + session.remoteConnections[connectionId].dispose(); + } + delete session.remoteConnections[connectionId]; + } + }; + return SessionDisconnectedEvent; +}(Event_1.Event)); +exports.SessionDisconnectedEvent = SessionDisconnectedEvent; + +},{"./Event":29}],33:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var SignalEvent = (function (_super) { + __extends(SignalEvent, _super); + function SignalEvent(target, type, data, from) { + var _this = _super.call(this, false, target, type) || this; + _this.type = type; + _this.data = data; + _this.from = from; + return _this; + } + SignalEvent.prototype.callDefaultBehaviour = function () { }; + return SignalEvent; +}(Event_1.Event)); +exports.SignalEvent = SignalEvent; + +},{"./Event":29}],34:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var Publisher_1 = require("../../OpenVidu/Publisher"); +var Session_1 = require("../../OpenVidu/Session"); +var StreamEvent = (function (_super) { + __extends(StreamEvent, _super); + function StreamEvent(cancelable, target, type, stream, reason) { + var _this = _super.call(this, cancelable, target, type) || this; + _this.stream = stream; + _this.reason = reason; + return _this; + } + StreamEvent.prototype.callDefaultBehaviour = function () { + if (this.type === 'streamDestroyed') { + if (this.target instanceof Session_1.Session) { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Session'"); + this.stream.disposeWebRtcPeer(); + } + else if (this.target instanceof Publisher_1.Publisher) { + console.info("Calling default behaviour upon '" + this.type + "' event dispatched by 'Publisher'"); + this.stream.isLocalStreamReadyToPublish = false; + } + this.stream.disposeMediaStream(); + if (this.stream.streamManager) + this.stream.streamManager.removeAllVideos(); + delete this.stream.session.remoteStreamsCreated[this.stream.streamId]; + var remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId]; + if (!!remoteConnection && !!remoteConnection.options) { + var streamOptionsServer = remoteConnection.options.streams; + for (var i = streamOptionsServer.length - 1; i >= 0; --i) { + if (streamOptionsServer[i].id === this.stream.streamId) { + streamOptionsServer.splice(i, 1); + } + } + } + } + }; + return StreamEvent; +}(Event_1.Event)); +exports.StreamEvent = StreamEvent; + +},{"../../OpenVidu/Publisher":20,"../../OpenVidu/Session":21,"./Event":29}],35:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var StreamManagerEvent = (function (_super) { + __extends(StreamManagerEvent, _super); + function StreamManagerEvent(target) { + return _super.call(this, false, target, 'streamPlaying') || this; + } + StreamManagerEvent.prototype.callDefaultBehaviour = function () { }; + return StreamManagerEvent; +}(Event_1.Event)); +exports.StreamManagerEvent = StreamManagerEvent; + +},{"./Event":29}],36:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Event_1 = require("./Event"); +var VideoElementEvent = (function (_super) { + __extends(VideoElementEvent, _super); + function VideoElementEvent(element, target, type) { + var _this = _super.call(this, false, target, type) || this; + _this.element = element; + return _this; + } + VideoElementEvent.prototype.callDefaultBehaviour = function () { }; + return VideoElementEvent; +}(Event_1.Event)); +exports.VideoElementEvent = VideoElementEvent; + +},{"./Event":29}],37:[function(require,module,exports){ +function Mapper() { + var sources = {}; + this.forEach = function (callback) { + for (var key in sources) { + var source = sources[key]; + for (var key2 in source) + callback(source[key2]); + } + ; + }; + this.get = function (id, source) { + var ids = sources[source]; + if (ids == undefined) + return undefined; + return ids[id]; + }; + this.remove = function (id, source) { + var ids = sources[source]; + if (ids == undefined) + return; + delete ids[id]; + for (var i in ids) { + return false; + } + delete sources[source]; + }; + this.set = function (value, id, source) { + if (value == undefined) + return this.remove(id, source); + var ids = sources[source]; + if (ids == undefined) + sources[source] = ids = {}; + ids[id] = value; + }; +} +; +Mapper.prototype.pop = function (id, source) { + var value = this.get(id, source); + if (value == undefined) + return undefined; + this.remove(id, source); + return value; +}; +module.exports = Mapper; + +},{}],38:[function(require,module,exports){ +var JsonRpcClient = require('./jsonrpcclient'); +exports.JsonRpcClient = JsonRpcClient; + +},{"./jsonrpcclient":39}],39:[function(require,module,exports){ +var RpcBuilder = require('../'); +var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); +Date.now = Date.now || function () { + return +new Date; +}; +var PING_INTERVAL = 5000; +var RECONNECTING = 'RECONNECTING'; +var CONNECTED = 'CONNECTED'; +var DISCONNECTED = 'DISCONNECTED'; +var Logger = console; +function JsonRpcClient(configuration) { + var self = this; + var wsConfig = configuration.ws; + var notReconnectIfNumLessThan = -1; + var pingNextNum = 0; + var enabledPings = true; + var pingPongStarted = false; + var pingInterval; + var status = DISCONNECTED; + var onreconnecting = wsConfig.onreconnecting; + var onreconnected = wsConfig.onreconnected; + var onconnected = wsConfig.onconnected; + var onerror = wsConfig.onerror; + configuration.rpc.pull = function (params, request) { + request.reply(null, "push"); + }; + wsConfig.onreconnecting = function () { + Logger.debug("--------- ONRECONNECTING -----------"); + if (status === RECONNECTING) { + Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it"); + return; + } + status = RECONNECTING; + if (onreconnecting) { + onreconnecting(); + } + }; + wsConfig.onreconnected = function () { + Logger.debug("--------- ONRECONNECTED -----------"); + if (status === CONNECTED) { + Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it"); + return; + } + status = CONNECTED; + enabledPings = true; + updateNotReconnectIfLessThan(); + usePing(); + if (onreconnected) { + onreconnected(); + } + }; + wsConfig.onconnected = function () { + Logger.debug("--------- ONCONNECTED -----------"); + if (status === CONNECTED) { + Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it"); + return; + } + status = CONNECTED; + enabledPings = true; + usePing(); + if (onconnected) { + onconnected(); + } + }; + wsConfig.onerror = function (error) { + Logger.debug("--------- ONERROR -----------"); + status = DISCONNECTED; + if (onerror) { + onerror(error); + } + }; + var ws = new WebSocketWithReconnection(wsConfig); + Logger.debug('Connecting websocket to URI: ' + wsConfig.uri); + var rpcBuilderOptions = { + request_timeout: configuration.rpc.requestTimeout, + ping_request_timeout: configuration.rpc.heartbeatRequestTimeout + }; + var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) { + Logger.debug('Received request: ' + JSON.stringify(request)); + try { + var func = configuration.rpc[request.method]; + if (func === undefined) { + Logger.error("Method " + request.method + " not registered in client"); + } + else { + func(request.params, request); + } + } + catch (err) { + Logger.error('Exception processing request: ' + JSON.stringify(request)); + Logger.error(err); + } + }); + this.send = function (method, params, callback) { + if (method !== 'ping') { + Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params)); + } + var requestTime = Date.now(); + rpc.encode(method, params, function (error, result) { + if (error) { + try { + Logger.error("ERROR:" + error.message + " in Request: method:" + + method + " params:" + JSON.stringify(params) + " request:" + + error.request); + if (error.data) { + Logger.error("ERROR DATA:" + JSON.stringify(error.data)); + } + } + catch (e) { } + error.requestTime = requestTime; + } + if (callback) { + if (result != undefined && result.value !== 'pong') { + Logger.debug('Response: ' + JSON.stringify(result)); + } + callback(error, result); + } + }); + }; + function updateNotReconnectIfLessThan() { + Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' + + notReconnectIfNumLessThan + ')'); + notReconnectIfNumLessThan = pingNextNum; + } + function sendPing() { + if (enabledPings) { + var params = null; + if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) { + params = { + interval: configuration.heartbeat || PING_INTERVAL + }; + } + pingNextNum++; + self.send('ping', params, (function (pingNum) { + return function (error, result) { + if (error) { + Logger.debug("Error in ping request #" + pingNum + " (" + + error.message + ")"); + if (pingNum > notReconnectIfNumLessThan) { + enabledPings = false; + updateNotReconnectIfLessThan(); + Logger.debug("Server did not respond to ping message #" + + pingNum + ". Reconnecting... "); + ws.reconnectWs(); + } + } + }; + })(pingNextNum)); + } + else { + Logger.debug("Trying to send ping, but ping is not enabled"); + } + } + function usePing() { + if (!pingPongStarted) { + Logger.debug("Starting ping (if configured)"); + pingPongStarted = true; + if (configuration.heartbeat != undefined) { + pingInterval = setInterval(sendPing, configuration.heartbeat); + sendPing(); + } + } + } + this.close = function () { + Logger.debug("Closing jsonRpcClient explicitly by client"); + if (pingInterval != undefined) { + Logger.debug("Clearing ping interval"); + clearInterval(pingInterval); + } + pingPongStarted = false; + enabledPings = false; + if (configuration.sendCloseMessage) { + Logger.debug("Sending close message"); + this.send('closeSession', null, function (error, result) { + if (error) { + Logger.error("Error sending close message: " + JSON.stringify(error)); + } + ws.close(); + }); + } + else { + ws.close(); + } + }; + this.forceClose = function (millis) { + ws.forceClose(millis); + }; + this.reconnect = function () { + ws.reconnectWs(); + }; +} +module.exports = JsonRpcClient; + +},{"../":42,"./transports/webSocketWithReconnection":41}],40:[function(require,module,exports){ +var WebSocketWithReconnection = require('./webSocketWithReconnection'); +exports.WebSocketWithReconnection = WebSocketWithReconnection; + +},{"./webSocketWithReconnection":41}],41:[function(require,module,exports){ +(function (global){ +"use strict"; +var BrowserWebSocket = global.WebSocket || global.MozWebSocket; +var Logger = console; +var MAX_RETRIES = 2000; +var RETRY_TIME_MS = 3000; +var CONNECTING = 0; +var OPEN = 1; +var CLOSING = 2; +var CLOSED = 3; +function WebSocketWithReconnection(config) { + var closing = false; + var registerMessageHandler; + var wsUri = config.uri; + var useSockJS = config.useSockJS; + var reconnecting = false; + var forcingDisconnection = false; + var ws; + if (useSockJS) { + ws = new SockJS(wsUri); + } + else { + ws = new WebSocket(wsUri); + } + ws.onopen = function () { + logConnected(ws, wsUri); + if (config.onconnected) { + config.onconnected(); + } + }; + ws.onerror = function (error) { + Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error); + if (config.onerror) { + config.onerror(error); + } + }; + function logConnected(ws, wsUri) { + try { + Logger.debug("WebSocket connected to " + wsUri); + } + catch (e) { + Logger.error(e); + } + } + var reconnectionOnClose = function () { + if (ws.readyState === CLOSED) { + if (closing) { + Logger.debug("Connection closed by user"); + } + else { + Logger.debug("Connection closed unexpectecly. Reconnecting..."); + reconnectToSameUri(MAX_RETRIES, 1); + } + } + else { + Logger.debug("Close callback from previous websocket. Ignoring it"); + } + }; + ws.onclose = reconnectionOnClose; + function reconnectToSameUri(maxRetries, numRetries) { + Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")"); + if (numRetries === 1) { + if (reconnecting) { + Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection."); + return; + } + else { + reconnecting = true; + } + if (config.onreconnecting) { + config.onreconnecting(); + } + } + if (forcingDisconnection) { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + else { + if (config.newWsUriOnReconnection) { + config.newWsUriOnReconnection(function (error, newWsUri) { + if (error) { + Logger.debug(error); + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + else { + reconnectToNewUri(maxRetries, numRetries, newWsUri); + } + }); + } + else { + reconnectToNewUri(maxRetries, numRetries, wsUri); + } + } + } + function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) { + Logger.debug("Reconnection attempt #" + numRetries); + ws.close(); + wsUri = reconnectWsUri || wsUri; + var newWs; + if (useSockJS) { + newWs = new SockJS(wsUri); + } + else { + newWs = new WebSocket(wsUri); + } + newWs.onopen = function () { + Logger.debug("Reconnected after " + numRetries + " attempts..."); + logConnected(newWs, wsUri); + reconnecting = false; + registerMessageHandler(); + if (config.onreconnected()) { + config.onreconnected(); + } + newWs.onclose = reconnectionOnClose; + }; + var onErrorOrClose = function (error) { + Logger.warn("Reconnection error: ", error); + if (numRetries === maxRetries) { + if (config.ondisconnect) { + config.ondisconnect(); + } + } + else { + setTimeout(function () { + reconnectToSameUri(maxRetries, numRetries + 1); + }, RETRY_TIME_MS); + } + }; + newWs.onerror = onErrorOrClose; + ws = newWs; + } + this.close = function () { + closing = true; + ws.close(); + }; + this.forceClose = function (millis) { + Logger.debug("Testing: Force WebSocket close"); + if (millis) { + Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure"); + var goodWsUri = wsUri; + wsUri = "wss://21.234.12.34.4:443/"; + forcingDisconnection = true; + setTimeout(function () { + Logger.debug("Testing: Recover good wsUri " + goodWsUri); + wsUri = goodWsUri; + forcingDisconnection = false; + }, millis); + } + ws.close(); + }; + this.reconnectWs = function () { + Logger.debug("reconnectWs"); + reconnectToSameUri(MAX_RETRIES, 1, wsUri); + }; + this.send = function (message) { + ws.send(message); + }; + this.addEventListener = function (type, callback) { + registerMessageHandler = function () { + ws.addEventListener(type, callback); + }; + registerMessageHandler(); + }; +} +module.exports = WebSocketWithReconnection; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],42:[function(require,module,exports){ +var defineProperty_IE8 = false; +if (Object.defineProperty) { + try { + Object.defineProperty({}, "x", {}); + } + catch (e) { + defineProperty_IE8 = true; + } +} +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== 'function') { + throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { + return fToBind.apply(this instanceof fNOP && oThis + ? this + : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); + }; + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + return fBound; + }; +} +var EventEmitter = require('events').EventEmitter; +var inherits = require('inherits'); +var packers = require('./packers'); +var Mapper = require('./Mapper'); +var BASE_TIMEOUT = 5000; +function unifyResponseMethods(responseMethods) { + if (!responseMethods) + return {}; + for (var key in responseMethods) { + var value = responseMethods[key]; + if (typeof value == 'string') + responseMethods[key] = + { + response: value + }; + } + ; + return responseMethods; +} +; +function unifyTransport(transport) { + if (!transport) + return; + if (transport instanceof Function) + return { send: transport }; + if (transport.send instanceof Function) + return transport; + if (transport.postMessage instanceof Function) { + transport.send = transport.postMessage; + return transport; + } + if (transport.write instanceof Function) { + transport.send = transport.write; + return transport; + } + if (transport.onmessage !== undefined) + return; + if (transport.pause instanceof Function) + return; + throw new SyntaxError("Transport is not a function nor a valid object"); +} +; +function RpcNotification(method, params) { + if (defineProperty_IE8) { + this.method = method; + this.params = params; + } + else { + Object.defineProperty(this, 'method', { value: method, enumerable: true }); + Object.defineProperty(this, 'params', { value: params, enumerable: true }); + } +} +; +function RpcBuilder(packer, options, transport, onRequest) { + var self = this; + if (!packer) + throw new SyntaxError('Packer is not defined'); + if (!packer.pack || !packer.unpack) + throw new SyntaxError('Packer is invalid'); + var responseMethods = unifyResponseMethods(packer.responseMethods); + if (options instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after onRequest"); + onRequest = options; + transport = undefined; + options = undefined; + } + ; + if (options && options.send instanceof Function) { + if (transport && !(transport instanceof Function)) + throw new SyntaxError("Only a function can be after transport"); + onRequest = transport; + transport = options; + options = undefined; + } + ; + if (transport instanceof Function) { + if (onRequest != undefined) + throw new SyntaxError("There can't be parameters after onRequest"); + onRequest = transport; + transport = undefined; + } + ; + if (transport && transport.send instanceof Function) + if (onRequest && !(onRequest instanceof Function)) + throw new SyntaxError("Only a function can be after transport"); + options = options || {}; + EventEmitter.call(this); + if (onRequest) + this.on('request', onRequest); + if (defineProperty_IE8) + this.peerID = options.peerID; + else + Object.defineProperty(this, 'peerID', { value: options.peerID }); + var max_retries = options.max_retries || 0; + function transportMessage(event) { + self.decode(event.data || event); + } + ; + this.getTransport = function () { + return transport; + }; + this.setTransport = function (value) { + if (transport) { + if (transport.removeEventListener) + transport.removeEventListener('message', transportMessage); + else if (transport.removeListener) + transport.removeListener('data', transportMessage); + } + ; + if (value) { + if (value.addEventListener) + value.addEventListener('message', transportMessage); + else if (value.addListener) + value.addListener('data', transportMessage); + } + ; + transport = unifyTransport(value); + }; + if (!defineProperty_IE8) + Object.defineProperty(this, 'transport', { + get: this.getTransport.bind(this), + set: this.setTransport.bind(this) + }); + this.setTransport(transport); + var request_timeout = options.request_timeout || BASE_TIMEOUT; + var ping_request_timeout = options.ping_request_timeout || request_timeout; + var response_timeout = options.response_timeout || BASE_TIMEOUT; + var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT; + var requestID = 0; + var requests = new Mapper(); + var responses = new Mapper(); + var processedResponses = new Mapper(); + var message2Key = {}; + function storeResponse(message, id, dest) { + var response = { + message: message, + timeout: setTimeout(function () { + responses.remove(id, dest); + }, response_timeout) + }; + responses.set(response, id, dest); + } + ; + function storeProcessedResponse(ack, from) { + var timeout = setTimeout(function () { + processedResponses.remove(ack, from); + }, duplicates_timeout); + processedResponses.set(timeout, ack, from); + } + ; + function RpcRequest(method, params, id, from, transport) { + RpcNotification.call(this, method, params); + this.getTransport = function () { + return transport; + }; + this.setTransport = function (value) { + transport = unifyTransport(value); + }; + if (!defineProperty_IE8) + Object.defineProperty(this, 'transport', { + get: this.getTransport.bind(this), + set: this.setTransport.bind(this) + }); + var response = responses.get(id, from); + if (!(transport || self.getTransport())) { + if (defineProperty_IE8) + this.duplicated = Boolean(response); + else + Object.defineProperty(this, 'duplicated', { + value: Boolean(response) + }); + } + var responseMethod = responseMethods[method]; + this.pack = packer.pack.bind(packer, this, id); + this.reply = function (error, result, transport) { + if (error instanceof Function || error && error.send instanceof Function) { + if (result != undefined) + throw new SyntaxError("There can't be parameters after callback"); + transport = error; + result = null; + error = undefined; + } + else if (result instanceof Function + || result && result.send instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after callback"); + transport = result; + result = null; + } + ; + transport = unifyTransport(transport); + if (response) + clearTimeout(response.timeout); + if (from != undefined) { + if (error) + error.dest = from; + if (result) + result.dest = from; + } + ; + var message; + if (error || result != undefined) { + if (self.peerID != undefined) { + if (error) + error.from = self.peerID; + else + result.from = self.peerID; + } + if (responseMethod) { + if (responseMethod.error == undefined && error) + message = + { + error: error + }; + else { + var method = error + ? responseMethod.error + : responseMethod.response; + message = + { + method: method, + params: error || result + }; + } + } + else + message = + { + error: error, + result: result + }; + message = packer.pack(message, id); + } + else if (response) + message = response.message; + else + message = packer.pack({ result: null }, id); + storeResponse(message, id, from); + transport = transport || this.getTransport() || self.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + } + ; + inherits(RpcRequest, RpcNotification); + function cancel(message) { + var key = message2Key[message]; + if (!key) + return; + delete message2Key[message]; + var request = requests.pop(key.id, key.dest); + if (!request) + return; + clearTimeout(request.timeout); + storeProcessedResponse(key.id, key.dest); + } + ; + this.cancel = function (message) { + if (message) + return cancel(message); + for (var message in message2Key) + cancel(message); + }; + this.close = function () { + var transport = this.getTransport(); + if (transport && transport.close) + transport.close(); + this.cancel(); + processedResponses.forEach(clearTimeout); + responses.forEach(function (response) { + clearTimeout(response.timeout); + }); + }; + this.encode = function (method, params, dest, transport, callback) { + if (params instanceof Function) { + if (dest != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = params; + transport = undefined; + dest = undefined; + params = undefined; + } + else if (dest instanceof Function) { + if (transport != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = dest; + transport = undefined; + dest = undefined; + } + else if (transport instanceof Function) { + if (callback != undefined) + throw new SyntaxError("There can't be parameters after callback"); + callback = transport; + transport = undefined; + } + ; + if (self.peerID != undefined) { + params = params || {}; + params.from = self.peerID; + } + ; + if (dest != undefined) { + params = params || {}; + params.dest = dest; + } + ; + var message = { + method: method, + params: params + }; + if (callback) { + var id = requestID++; + var retried = 0; + message = packer.pack(message, id); + function dispatchCallback(error, result) { + self.cancel(message); + callback(error, result); + } + ; + var request = { + message: message, + callback: dispatchCallback, + responseMethods: responseMethods[method] || {} + }; + var encode_transport = unifyTransport(transport); + function sendRequest(transport) { + var rt = (method === 'ping' ? ping_request_timeout : request_timeout); + request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++)); + message2Key[message] = { id: id, dest: dest }; + requests.set(request, id, dest); + transport = transport || encode_transport || self.getTransport(); + if (transport) + return transport.send(message); + return message; + } + ; + function retry(transport) { + transport = unifyTransport(transport); + console.warn(retried + ' retry for request message:', message); + var timeout = processedResponses.pop(id, dest); + clearTimeout(timeout); + return sendRequest(transport); + } + ; + function timeout() { + if (retried < max_retries) + return retry(transport); + var error = new Error('Request has timed out'); + error.request = message; + error.retry = retry; + dispatchCallback(error); + } + ; + return sendRequest(transport); + } + ; + message = packer.pack(message); + transport = transport || this.getTransport(); + if (transport) + return transport.send(message); + return message; + }; + this.decode = function (message, transport) { + if (!message) + throw new TypeError("Message is not defined"); + try { + message = packer.unpack(message); + } + catch (e) { + return console.debug(e, message); + } + ; + var id = message.id; + var ack = message.ack; + var method = message.method; + var params = message.params || {}; + var from = params.from; + var dest = params.dest; + if (self.peerID != undefined && from == self.peerID) + return; + if (id == undefined && ack == undefined) { + var notification = new RpcNotification(method, params); + if (self.emit('request', notification)) + return; + return notification; + } + ; + function processRequest() { + transport = unifyTransport(transport) || self.getTransport(); + if (transport) { + var response = responses.get(id, from); + if (response) + return transport.send(response.message); + } + ; + var idAck = (id != undefined) ? id : ack; + var request = new RpcRequest(method, params, idAck, from, transport); + if (self.emit('request', request)) + return; + return request; + } + ; + function processResponse(request, error, result) { + request.callback(error, result); + } + ; + function duplicatedResponse(timeout) { + console.warn("Response already processed", message); + clearTimeout(timeout); + storeProcessedResponse(ack, from); + } + ; + if (method) { + if (dest == undefined || dest == self.peerID) { + var request = requests.get(ack, from); + if (request) { + var responseMethods = request.responseMethods; + if (method == responseMethods.error) + return processResponse(request, params); + if (method == responseMethods.response) + return processResponse(request, null, params); + return processRequest(); + } + var processed = processedResponses.get(ack, from); + if (processed) + return duplicatedResponse(processed); + } + return processRequest(); + } + ; + var error = message.error; + var result = message.result; + if (error && error.dest && error.dest != self.peerID) + return; + if (result && result.dest && result.dest != self.peerID) + return; + var request = requests.get(ack, from); + if (!request) { + var processed = processedResponses.get(ack, from); + if (processed) + return duplicatedResponse(processed); + return console.warn("No callback was defined for this message", message); + } + ; + processResponse(request, error, result); + }; +} +; +inherits(RpcBuilder, EventEmitter); +RpcBuilder.RpcNotification = RpcNotification; +module.exports = RpcBuilder; +var clients = require('./clients'); +var transports = require('./clients/transports'); +RpcBuilder.clients = clients; +RpcBuilder.clients.transports = transports; +RpcBuilder.packers = packers; + +},{"./Mapper":37,"./clients":38,"./clients/transports":40,"./packers":45,"events":1,"inherits":6}],43:[function(require,module,exports){ +function pack(message, id) { + var result = { + jsonrpc: "2.0" + }; + if (message.method) { + result.method = message.method; + if (message.params) + result.params = message.params; + if (id != undefined) + result.id = id; + } + else if (id != undefined) { + if (message.error) { + if (message.result !== undefined) + throw new TypeError("Both result and error are defined"); + result.error = message.error; + } + else if (message.result !== undefined) + result.result = message.result; + else + throw new TypeError("No result or error is defined"); + result.id = id; + } + ; + return JSON.stringify(result); +} +; +function unpack(message) { + var result = message; + if (typeof message === 'string' || message instanceof String) { + result = JSON.parse(message); + } + var version = result.jsonrpc; + if (version !== '2.0') + throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); + if (result.method == undefined) { + if (result.id == undefined) + throw new TypeError("Invalid message: " + message); + var result_defined = result.result !== undefined; + var error_defined = result.error !== undefined; + if (result_defined && error_defined) + throw new TypeError("Both result and error are defined: " + message); + if (!result_defined && !error_defined) + throw new TypeError("No result or error is defined: " + message); + result.ack = result.id; + delete result.id; + } + return result; +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],44:[function(require,module,exports){ +function pack(message) { + throw new TypeError("Not yet implemented"); +} +; +function unpack(message) { + throw new TypeError("Not yet implemented"); +} +; +exports.pack = pack; +exports.unpack = unpack; + +},{}],45:[function(require,module,exports){ +var JsonRPC = require('./JsonRPC'); +var XmlRPC = require('./XmlRPC'); +exports.JsonRPC = JsonRPC; +exports.XmlRPC = XmlRPC; + +},{"./JsonRPC":43,"./XmlRPC":44}],46:[function(require,module,exports){ +window.getScreenId = function (callback, custom_parameter) { + if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) { + callback({ + video: true + }); + return; + } + if (!!navigator.mozGetUserMedia) { + callback(null, 'firefox', { + video: { + mozMediaSource: 'window', + mediaSource: 'window' + } + }); + return; + } + window.addEventListener('message', onIFrameCallback); + function onIFrameCallback(event) { + if (!event.data) + return; + if (event.data.chromeMediaSourceId) { + if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { + callback('permission-denied'); + } + else { + callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack)); + } + window.removeEventListener('message', onIFrameCallback); + } + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); + window.removeEventListener('message', onIFrameCallback); + } + } + if (!custom_parameter) { + setTimeout(postGetSourceIdMessage, 100); + } + else { + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); + } +}; +function getScreenConstraints(error, sourceId, canRequestAudioTrack) { + var screen_constraints = { + audio: false, + video: { + mandatory: { + chromeMediaSource: error ? 'screen' : 'desktop', + maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, + maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 + }, + optional: [] + } + }; + if (!!canRequestAudioTrack) { + screen_constraints.audio = { + mandatory: { + chromeMediaSource: error ? 'screen' : 'desktop', + }, + optional: [] + }; + } + if (sourceId) { + screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; + if (screen_constraints.audio && screen_constraints.audio.mandatory) { + screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId; + } + } + return screen_constraints; +} +function postGetSourceIdMessage(custom_parameter) { + if (!iframe) { + loadIFrame(function () { + postGetSourceIdMessage(custom_parameter); + }); + return; + } + if (!iframe.isLoaded) { + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); + return; + } + if (!custom_parameter) { + iframe.contentWindow.postMessage({ + captureSourceId: true + }, '*'); + } + else if (!!custom_parameter.forEach) { + iframe.contentWindow.postMessage({ + captureCustomSourceId: custom_parameter + }, '*'); + } + else { + iframe.contentWindow.postMessage({ + captureSourceIdWithAudio: true + }, '*'); + } +} +var iframe; +window.getScreenConstraints = function (callback) { + loadIFrame(function () { + getScreenId(function (error, sourceId, screen_constraints) { + if (!screen_constraints) { + screen_constraints = { + video: true + }; + } + callback(error, screen_constraints.video); + }); + }); +}; +function loadIFrame(loadCallback) { + if (iframe) { + loadCallback(); + return; + } + iframe = document.createElement('iframe'); + iframe.onload = function () { + iframe.isLoaded = true; + loadCallback(); + }; + iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/'; + iframe.style.display = 'none'; + (document.body || document.documentElement).appendChild(iframe); +} +window.getChromeExtensionStatus = function (callback) { + if (!!navigator.mozGetUserMedia) { + callback('installed-enabled'); + return; + } + window.addEventListener('message', onIFrameCallback); + function onIFrameCallback(event) { + if (!event.data) + return; + if (event.data.chromeExtensionStatus) { + callback(event.data.chromeExtensionStatus); + window.removeEventListener('message', onIFrameCallback); + } + } + setTimeout(postGetChromeExtensionStatusMessage, 100); +}; +function postGetChromeExtensionStatusMessage() { + if (!iframe) { + loadIFrame(postGetChromeExtensionStatusMessage); + return; + } + if (!iframe.isLoaded) { + setTimeout(postGetChromeExtensionStatusMessage, 100); + return; + } + iframe.contentWindow.postMessage({ + getChromeExtensionStatus: true + }, '*'); +} +exports.getScreenId = getScreenId; + +},{}],47:[function(require,module,exports){ +var chromeMediaSource = 'screen'; +var sourceId; +var screenCallback; +var isFirefox = typeof window.InstallTrigger !== 'undefined'; +var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; +var isChrome = !!window.chrome && !isOpera; +window.addEventListener('message', function (event) { + if (event.origin != window.location.origin) { + return; + } + onMessageCallback(event.data); +}); +function onMessageCallback(data) { + if (data == 'PermissionDeniedError') { + if (screenCallback) + return screenCallback('PermissionDeniedError'); + else + throw new Error('PermissionDeniedError'); + } + if (data == 'rtcmulticonnection-extension-loaded') { + chromeMediaSource = 'desktop'; + } + if (data.sourceId && screenCallback) { + screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true); + } +} +function isChromeExtensionAvailable(callback) { + if (!callback) + return; + if (chromeMediaSource == 'desktop') + return callback(true); + window.postMessage('are-you-there', '*'); + setTimeout(function () { + if (chromeMediaSource == 'screen') { + callback(false); + } + else + callback(true); + }, 2000); +} +function getSourceId(callback) { + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage('get-sourceId', '*'); +} +function getCustomSourceId(arr, callback) { + if (!arr || !arr.forEach) + throw '"arr" parameter is mandatory and it must be an array.'; + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage({ + 'get-custom-sourceId': arr + }, '*'); +} +function getSourceIdWithAudio(callback) { + if (!callback) + throw '"callback" parameter is mandatory.'; + if (sourceId) + return callback(sourceId); + screenCallback = callback; + window.postMessage('audio-plus-tab', '*'); +} +function getChromeExtensionStatus(extensionid, callback) { + if (isFirefox) + return callback('not-chrome'); + if (arguments.length != 2) { + callback = extensionid; + extensionid = 'lfcgfepafnobdloecchnfaclibenjold'; + } + var image = document.createElement('img'); + image.src = 'chrome-extension://' + extensionid + '/icon.png'; + image.onload = function () { + chromeMediaSource = 'screen'; + window.postMessage('are-you-there', '*'); + setTimeout(function () { + if (chromeMediaSource == 'screen') { + callback('installed-disabled'); + } + else + callback('installed-enabled'); + }, 2000); + }; + image.onerror = function () { + callback('not-installed'); + }; +} +function getScreenConstraintsWithAudio(callback) { + getScreenConstraints(callback, true); +} +function getScreenConstraints(callback, captureSourceIdWithAudio) { + sourceId = ''; + var firefoxScreenConstraints = { + mozMediaSource: 'window', + mediaSource: 'window' + }; + if (isFirefox) + return callback(null, firefoxScreenConstraints); + var screen_constraints = { + mandatory: { + chromeMediaSource: chromeMediaSource, + maxWidth: screen.width > 1920 ? screen.width : 1920, + maxHeight: screen.height > 1080 ? screen.height : 1080 + }, + optional: [] + }; + if (chromeMediaSource == 'desktop' && !sourceId) { + if (captureSourceIdWithAudio) { + getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + if (canRequestAudioTrack) { + screen_constraints.canRequestAudioTrack = true; + } + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } + else { + getSourceId(function (sourceId) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } + return; + } + if (chromeMediaSource == 'desktop') { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + } + callback(null, screen_constraints); +} +exports.getScreenConstraints = getScreenConstraints; +exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio; +exports.isChromeExtensionAvailable = isChromeExtensionAvailable; +exports.getChromeExtensionStatus = getChromeExtensionStatus; +exports.getSourceId = getSourceId; + +},{}],48:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var freeice = require("freeice"); +var uuid = require("uuid"); +var platform = require("platform"); +var WebRtcPeer = (function () { + function WebRtcPeer(configuration) { + var _this = this; + this.configuration = configuration; + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.iceCandidateList = []; + this.candidategatheringdone = false; + this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice(); + this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers }); + this.id = !!configuration.id ? configuration.id : uuid.v4(); + this.pc.onicecandidate = function (event) { + var candidate = event.candidate; + if (candidate) { + _this.localCandidatesQueue.push({ candidate: candidate.candidate }); + _this.candidategatheringdone = false; + _this.configuration.onicecandidate(event.candidate); + } + else if (!_this.candidategatheringdone) { + _this.candidategatheringdone = true; + } + }; + this.pc.onsignalingstatechange = function () { + if (_this.pc.signalingState === 'stable') { + while (_this.iceCandidateList.length > 0) { + _this.pc.addIceCandidate(_this.iceCandidateList.shift()); + } + } + }; + this.start(); + } + WebRtcPeer.prototype.start = function () { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.pc.signalingState === 'closed') { + reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); + } + if (!!_this.configuration.mediaStream) { + _this.pc.addStream(_this.configuration.mediaStream); + } + if (_this.configuration.mode === 'sendonly' && + (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) { + _this.configuration.mode = 'sendrecv'; + } + resolve(); + }); + }; + WebRtcPeer.prototype.dispose = function () { + var _this = this; + console.debug('Disposing WebRtcPeer'); + try { + if (this.pc) { + if (this.pc.signalingState === 'closed') { + return; + } + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.pc.getLocalStreams().forEach(function (str) { + _this.streamStop(str); + }); + this.pc.close(); + } + } + catch (err) { + console.warn('Exception disposing webrtc peer ' + err); + } + }; + WebRtcPeer.prototype.generateOffer = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var offerAudio, offerVideo = true; + if (!!_this.configuration.mediaConstraints) { + offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ? + _this.configuration.mediaConstraints.audio : true; + offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ? + _this.configuration.mediaConstraints.video : true; + } + var constraints = { + offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio), + offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo) + }; + console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints)); + _this.pc.createOffer(constraints).then(function (offer) { + console.debug('Created SDP offer'); + return _this.pc.setLocalDescription(offer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.processOffer = function (sdpOffer) { + var _this = this; + return new Promise(function (resolve, reject) { + var offer = { + type: 'offer', + sdp: sdpOffer + }; + console.debug('SDP offer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('PeerConnection is closed'); + } + _this.pc.setRemoteDescription(offer) + .then(function () { + return _this.pc.createAnswer(); + }).then(function (answer) { + console.debug('Created SDP answer'); + return _this.pc.setLocalDescription(answer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.processAnswer = function (sdpAnswer) { + var _this = this; + return new Promise(function (resolve, reject) { + var answer = { + type: 'answer', + sdp: sdpAnswer + }; + console.debug('SDP answer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('RTCPeerConnection is closed'); + } + _this.pc.setRemoteDescription(answer).then(function () { return resolve(); }).catch(function (error) { return reject(error); }); + }); + }; + WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) { + var _this = this; + return new Promise(function (resolve, reject) { + console.debug('Remote ICE candidate received', iceCandidate); + _this.remoteCandidatesQueue.push(iceCandidate); + switch (_this.pc.signalingState) { + case 'closed': + reject(new Error('PeerConnection object is closed')); + break; + case 'stable': + if (!!_this.pc.remoteDescription) { + _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); }); + } + break; + default: + _this.iceCandidateList.push(iceCandidate); + resolve(); + } + }); + }; + WebRtcPeer.prototype.streamStop = function (stream) { + stream.getTracks().forEach(function (track) { + track.stop(); + stream.removeTrack(track); + }); + }; + return WebRtcPeer; +}()); +exports.WebRtcPeer = WebRtcPeer; +var WebRtcPeerRecvonly = (function (_super) { + __extends(WebRtcPeerRecvonly, _super); + function WebRtcPeerRecvonly(configuration) { + var _this = this; + configuration.mode = 'recvonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerRecvonly; +}(WebRtcPeer)); +exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; +var WebRtcPeerSendonly = (function (_super) { + __extends(WebRtcPeerSendonly, _super); + function WebRtcPeerSendonly(configuration) { + var _this = this; + configuration.mode = 'sendonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendonly; +}(WebRtcPeer)); +exports.WebRtcPeerSendonly = WebRtcPeerSendonly; +var WebRtcPeerSendrecv = (function (_super) { + __extends(WebRtcPeerSendrecv, _super); + function WebRtcPeerSendrecv(configuration) { + var _this = this; + configuration.mode = 'sendrecv'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendrecv; +}(WebRtcPeer)); +exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; + +},{"freeice":2,"platform":8,"uuid":9}],49:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var platform = require("platform"); +var WebRtcStats = (function () { + function WebRtcStats(stream) { + this.stream = stream; + this.webRtcStatsEnabled = false; + this.statsInterval = 1; + this.stats = { + inbound: { + audio: { + bytesReceived: 0, + packetsReceived: 0, + packetsLost: 0 + }, + video: { + bytesReceived: 0, + packetsReceived: 0, + packetsLost: 0, + framesDecoded: 0, + nackCount: 0 + } + }, + outbound: { + audio: { + bytesSent: 0, + packetsSent: 0, + }, + video: { + bytesSent: 0, + packetsSent: 0, + framesEncoded: 0, + nackCount: 0 + } + } + }; + } + WebRtcStats.prototype.isEnabled = function () { + return this.webRtcStatsEnabled; + }; + WebRtcStats.prototype.initWebRtcStats = function () { + var _this = this; + var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); + if (elastestInstrumentation) { + console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); + this.webRtcStatsEnabled = true; + var instrumentation_1 = JSON.parse(elastestInstrumentation); + this.statsInterval = instrumentation_1.webrtc.interval; + console.warn('localStorage item: ' + JSON.stringify(instrumentation_1)); + this.webRtcStatsIntervalId = setInterval(function () { + _this.sendStatsToHttpEndpoint(instrumentation_1); + }, this.statsInterval * 1000); + return; + } + console.debug('WebRtc stats not enabled'); + }; + WebRtcStats.prototype.stopWebRtcStats = function () { + if (this.webRtcStatsEnabled) { + clearInterval(this.webRtcStatsIntervalId); + console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); + } + }; + WebRtcStats.prototype.getSelectedIceCandidateInfo = function () { + var _this = this; + return new Promise(function (resolve, reject) { + _this.getStatsAgnostic(_this.stream.getRTCPeerConnection(), function (stats) { + if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + var localCandidateId = void 0, remoteCandidateId = void 0, googCandidatePair = void 0; + var localCandidates = {}; + var remoteCandidates = {}; + for (var key in stats) { + var stat = stats[key]; + if (stat.type === 'localcandidate') { + localCandidates[stat.id] = stat; + } + else if (stat.type === 'remotecandidate') { + remoteCandidates[stat.id] = stat; + } + else if (stat.type === 'googCandidatePair' && (stat.googActiveConnection === 'true')) { + googCandidatePair = stat; + localCandidateId = stat.localCandidateId; + remoteCandidateId = stat.remoteCandidateId; + } + } + var finalLocalCandidate_1 = localCandidates[localCandidateId]; + if (!!finalLocalCandidate_1) { + var candList = _this.stream.getLocalIceCandidateList(); + var cand = candList.filter(function (c) { + return (!!c.candidate && + c.candidate.indexOf(finalLocalCandidate_1.ipAddress) >= 0 && + c.candidate.indexOf(finalLocalCandidate_1.portNumber) >= 0 && + c.candidate.indexOf(finalLocalCandidate_1.priority) >= 0); + }); + finalLocalCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find local candidate in list of sent ICE candidates'; + } + else { + finalLocalCandidate_1 = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used'; + } + var finalRemoteCandidate_1 = remoteCandidates[remoteCandidateId]; + if (!!finalRemoteCandidate_1) { + var candList = _this.stream.getRemoteIceCandidateList(); + var cand = candList.filter(function (c) { + return (!!c.candidate && + c.candidate.indexOf(finalRemoteCandidate_1.ipAddress) >= 0 && + c.candidate.indexOf(finalRemoteCandidate_1.portNumber) >= 0 && + c.candidate.indexOf(finalRemoteCandidate_1.priority) >= 0); + }); + finalRemoteCandidate_1.raw = !!cand[0] ? cand[0].candidate : 'ERROR: Cannot find remote candidate in list of received ICE candidates'; + } + else { + finalRemoteCandidate_1 = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used'; + } + resolve({ + googCandidatePair: googCandidatePair, + localCandidate: finalLocalCandidate_1, + remoteCandidate: finalRemoteCandidate_1 + }); + } + else { + reject('Selected ICE candidate info only available for Chrome'); + } + }, function (error) { + reject(error); + }); + }); + }; + WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { + var _this = this; + var sendPost = function (json) { + var http = new XMLHttpRequest(); + var url = instrumentation.webrtc.httpEndpoint; + http.open('POST', url, true); + http.setRequestHeader('Content-type', 'application/json'); + http.onreadystatechange = function () { + if (http.readyState === 4 && http.status === 200) { + console.log('WebRtc stats successfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId); + } + }; + http.send(json); + }; + var f = function (stats) { + if (platform.name.indexOf('Firefox') !== -1) { + stats.forEach(function (stat) { + var json = {}; + if ((stat.type === 'inbound-rtp') && + (stat.nackCount !== null && + stat.isRemote === false && + stat.id.startsWith('inbound') && + stat.remoteId.startsWith('inbound'))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var jit = stat.jitter * 1000; + var metrics = { + bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + jitter: jit, + packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + bytesReceived: 'bytes', + jitter: 'ms', + packetsReceived: 'packets', + packetsLost: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = 'frames'; + units['nackCount'] = 'packets'; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.nackCount; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ((stat.type === 'outbound-rtp') && + (stat.isRemote === false && + stat.id.toLowerCase().includes('outbound'))) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + bytesSent: 'bytes', + packetsSent: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = 'frames'; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + }); + } + else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { + var key = _a[_i]; + var stat = stats[key]; + if (stat.type === 'ssrc') { + var json = {}; + if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || + (stat.mediaType === 'video' && 'qpSum' in stat))) { + var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, + jitter: stat.googJitterBufferMs, + packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, + packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval + }; + var units = { + bytesReceived: 'bytes', + jitter: 'ms', + packetsReceived: 'packets', + packetsLost: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; + metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; + units['framesDecoded'] = 'frames'; + units['nackCount'] = 'packets'; + _this.stats.inbound.video.framesDecoded = stat.framesDecoded; + _this.stats.inbound.video.nackCount = stat.googNacksSent; + } + _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; + _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; + _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + else if ('bytesSent' in stat) { + var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; + var metrics = { + bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, + packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval + }; + var units = { + bytesSent: 'bytes', + packetsSent: 'packets' + }; + if (stat.mediaType === 'video') { + metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; + units['framesEncoded'] = 'frames'; + _this.stats.outbound.video.framesEncoded = stat.framesEncoded; + } + _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; + _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; + json = { + '@timestamp': new Date(stat.timestamp).toISOString(), + 'exec': instrumentation.exec, + 'component': instrumentation.component, + 'stream': 'webRtc', + 'type': metricId, + 'stream_type': 'composed_metrics', + 'units': units + }; + json[metricId] = metrics; + sendPost(JSON.stringify(json)); + } + } + } + } + }; + this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); }); + }; + WebRtcStats.prototype.standardizeReport = function (response) { + console.log(response); + var standardReport = {}; + if (platform.name.indexOf('Firefox') !== -1) { + Object.keys(response).forEach(function (key) { + console.log(response[key]); + }); + return response; + } + response.result().forEach(function (report) { + var standardStats = { + id: report.id, + timestamp: report.timestamp, + type: report.type + }; + report.names().forEach(function (name) { + standardStats[name] = report.stat(name); + }); + standardReport[standardStats.id] = standardStats; + }); + return standardReport; + }; + WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) { + var _this = this; + if (platform.name.indexOf('Firefox') !== -1) { + return pc.getStats(null).then(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }).catch(failureCb); + } + else if ((platform.name.indexOf('Chrome') !== -1) || (platform.name.indexOf('Opera') !== -1)) { + return pc.getStats(function (response) { + var report = _this.standardizeReport(response); + successCb(report); + }, null, failureCb); + } + }; + return WebRtcStats; +}()); +exports.WebRtcStats = WebRtcStats; + +},{"platform":8}]},{},[16]) +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1NYW5hZ2VyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9NYXBwZXIuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvSnNvblJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL1htbFJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmctQXV0by5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNQZWVyL1dlYlJ0Y1BlZXIudHMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1N0YXRzL1dlYlJ0Y1N0YXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzZ0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3RlQSxnREFBK0M7QUFFL0MsSUFBSSxNQUFNLEVBQUU7SUFFUixNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsbUJBQVEsQ0FBQztDQUNqQzs7Ozs7QUNhRCxtQ0FBa0M7QUFV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LEdBQUcsS0FBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEIsQ0FBQyxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztTQUN2QjtJQUNMLENBQUM7SUFFTCxrQkFBQztBQUFELENBcllBLEFBcVlDLElBQUE7QUFyWVksa0NBQVciLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIixcbiAgXCJzdHVuLnNlcnZpY2VzLm1vemlsbGEuY29tXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvL1NldHVwIEF1ZGlvIENvbnRleHRcbiAgaWYgKCFhdWRpb0NvbnRleHQpIHtcbiAgICBhdWRpb0NvbnRleHQgPSBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuICB9XG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLyohXG4gKiBQbGF0Zm9ybS5qcyA8aHR0cHM6Ly9tdGhzLmJlL3BsYXRmb3JtPlxuICogQ29weXJpZ2h0IDIwMTQtMjAxOCBCZW5qYW1pbiBUYW4gPGh0dHBzOi8vYm5qbW50NG4ubm93LnNoLz5cbiAqIENvcHlyaWdodCAyMDExLTIwMTMgSm9obi1EYXZpZCBEYWx0b24gPGh0dHA6Ly9hbGx5b3VjYW5sZWV0LmNvbS8+XG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbXRocy5iZS9taXQ+XG4gKi9cbjsoZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBCYWNrdXAgcG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIG9sZFJvb3QgPSByb290O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcyBvciBCcm93c2VyaWZpZWQgY29kZSBhbmQgdXNlIGl0IGFzIGByb290YC4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSBmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlICYmIHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSkge1xuICAgIHJvb3QgPSBmcmVlR2xvYmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgdGhlIG1heGltdW0gbGVuZ3RoIG9mIGFuIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgKiBTZWUgdGhlIFtFUzYgc3BlY10oaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGgpXG4gICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAqL1xuICB2YXIgbWF4U2FmZUludGVnZXIgPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuXG4gIC8qKiBSZWd1bGFyIGV4cHJlc3Npb24gdG8gZGV0ZWN0IE9wZXJhLiAqL1xuICB2YXIgcmVPcGVyYSA9IC9cXGJPcGVyYS87XG5cbiAgLyoqIFBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciB0aGlzQmluZGluZyA9IHRoaXM7XG5cbiAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAvKiogVXNlZCB0byBjaGVjayBmb3Igb3duIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LiAqL1xuICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiB2YWx1ZXMuICovXG4gIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDYXBpdGFsaXplcyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgIHN0cmluZyA9IFN0cmluZyhzdHJpbmcpO1xuICAgIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG4gIH1cblxuICAvKipcbiAgICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGNsZWFuIHVwIHRoZSBPUyBuYW1lLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3MgVGhlIE9TIG5hbWUgdG8gY2xlYW4gdXAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVybl0gQSBgUmVnRXhwYCBwYXR0ZXJuIG1hdGNoaW5nIHRoZSBPUyBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhYmVsXSBBIGxhYmVsIGZvciB0aGUgT1MuXG4gICAqL1xuICBmdW5jdGlvbiBjbGVhbnVwT1Mob3MsIHBhdHRlcm4sIGxhYmVsKSB7XG4gICAgLy8gUGxhdGZvcm0gdG9rZW5zIGFyZSBkZWZpbmVkIGF0OlxuICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIC8vIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDgxMTIyMDUzOTUwL2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIHZhciBkYXRhID0ge1xuICAgICAgJzEwLjAnOiAnMTAnLFxuICAgICAgJzYuNCc6ICAnMTAgVGVjaG5pY2FsIFByZXZpZXcnLFxuICAgICAgJzYuMyc6ICAnOC4xJyxcbiAgICAgICc2LjInOiAgJzgnLFxuICAgICAgJzYuMSc6ICAnU2VydmVyIDIwMDggUjIgLyA3JyxcbiAgICAgICc2LjAnOiAgJ1NlcnZlciAyMDA4IC8gVmlzdGEnLFxuICAgICAgJzUuMic6ICAnU2VydmVyIDIwMDMgLyBYUCA2NC1iaXQnLFxuICAgICAgJzUuMSc6ICAnWFAnLFxuICAgICAgJzUuMDEnOiAnMjAwMCBTUDEnLFxuICAgICAgJzUuMCc6ICAnMjAwMCcsXG4gICAgICAnNC4wJzogICdOVCcsXG4gICAgICAnNC45MCc6ICdNRSdcbiAgICB9O1xuICAgIC8vIERldGVjdCBXaW5kb3dzIHZlcnNpb24gZnJvbSBwbGF0Zm9ybSB0b2tlbnMuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwgJiYgL15XaW4vaS50ZXN0KG9zKSAmJiAhL15XaW5kb3dzIFBob25lIC9pLnRlc3Qob3MpICYmXG4gICAgICAgIChkYXRhID0gZGF0YVsvW1xcZC5dKyQvLmV4ZWMob3MpXSkpIHtcbiAgICAgIG9zID0gJ1dpbmRvd3MgJyArIGRhdGE7XG4gICAgfVxuICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgIG9zID0gU3RyaW5nKG9zKTtcblxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGxhYmVsKTtcbiAgICB9XG5cbiAgICBvcyA9IGZvcm1hdChcbiAgICAgIG9zLnJlcGxhY2UoLyBjZSQvaSwgJyBDRScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJocHcvaSwgJ3dlYicpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWNpbnRvc2hcXGIvLCAnTWFjIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL19Qb3dlclBDXFxiL2ksICcgT1MnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKE9TIFgpIFteIFxcZF0rL2ksICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWMgKE9TIFgpXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyhcXGQpLywgJyAkMScpXG4gICAgICAgIC5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgLnJlcGxhY2UoLyg/OiBCZVBDfFsgLl0qZmNbIFxcZC5dKykkL2ksICcnKVxuICAgICAgICAucmVwbGFjZSgvXFxieDg2XFwuNjRcXGIvZ2ksICd4ODZfNjQnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKFdpbmRvd3MgUGhvbmUpIE9TXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihDaHJvbWUgT1MgXFx3KykgW1xcZC5dK1xcYi8sICckMScpXG4gICAgICAgIC5zcGxpdCgnIG9uICcpWzBdXG4gICAgKTtcblxuICAgIHJldHVybiBvcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpdGVyYXRpb24gdXRpbGl0eSBmb3IgYXJyYXlzIGFuZCBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBlYWNoKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gb2JqZWN0ID8gb2JqZWN0Lmxlbmd0aCA6IDA7XG5cbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPiAtMSAmJiBsZW5ndGggPD0gbWF4U2FmZUludGVnZXIpIHtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtpbmRleF0sIGluZGV4LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3JPd24ob2JqZWN0LCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaW0gYW5kIGNvbmRpdGlvbmFsbHkgY2FwaXRhbGl6ZSBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGZvcm1hdChzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSB0cmltKHN0cmluZyk7XG4gICAgcmV0dXJuIC9eKD86d2ViT1N8aSg/Ok9TfFApKS8udGVzdChzdHJpbmcpXG4gICAgICA/IHN0cmluZ1xuICAgICAgOiBjYXBpdGFsaXplKHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZXMgb3ZlciBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgZXhlY3V0aW5nIHRoZSBgY2FsbGJhY2tgIGZvciBlYWNoLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gZXhlY3V0ZWQgcGVyIG93biBwcm9wZXJ0eS5cbiAgICovXG4gIGZ1bmN0aW9uIGZvck93bihvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtrZXldLCBrZXksIG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIGEgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYFtbQ2xhc3NdXWAuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRDbGFzc09mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGxcbiAgICAgID8gY2FwaXRhbGl6ZSh2YWx1ZSlcbiAgICAgIDogdG9TdHJpbmcuY2FsbCh2YWx1ZSkuc2xpY2UoOCwgLTEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvc3Qgb2JqZWN0cyBjYW4gcmV0dXJuIHR5cGUgdmFsdWVzIHRoYXQgYXJlIGRpZmZlcmVudCBmcm9tIHRoZWlyIGFjdHVhbFxuICAgKiBkYXRhIHR5cGUuIFRoZSBvYmplY3RzIHdlIGFyZSBjb25jZXJuZWQgd2l0aCB1c3VhbGx5IHJldHVybiBub24tcHJpbWl0aXZlXG4gICAqIHR5cGVzIG9mIFwib2JqZWN0XCIsIFwiZnVuY3Rpb25cIiwgb3IgXCJ1bmtub3duXCIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBvd25lciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgYSBub24tcHJpbWl0aXZlLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RUeXBlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICB2YXIgdHlwZSA9IG9iamVjdCAhPSBudWxsID8gdHlwZW9mIG9iamVjdFtwcm9wZXJ0eV0gOiAnbnVtYmVyJztcbiAgICByZXR1cm4gIS9eKD86Ym9vbGVhbnxudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZCkkLy50ZXN0KHR5cGUpICYmXG4gICAgICAodHlwZSA9PSAnb2JqZWN0JyA/ICEhb2JqZWN0W3Byb3BlcnR5XSA6IHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmVzIGEgc3RyaW5nIGZvciB1c2UgaW4gYSBgUmVnRXhwYCBieSBtYWtpbmcgaHlwaGVucyBhbmQgc3BhY2VzIG9wdGlvbmFsLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcXVhbGlmeS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBxdWFsaWZ5KHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC8oWyAtXSkoPyEkKS9nLCAnJDE/Jyk7XG4gIH1cblxuICAvKipcbiAgICogQSBiYXJlLWJvbmVzIGBBcnJheSNyZWR1Y2VgIGxpa2UgdXRpbGl0eSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Kn0gVGhlIGFjY3VtdWxhdGVkIHJlc3VsdC5cbiAgICovXG4gIGZ1bmN0aW9uIHJlZHVjZShhcnJheSwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWNjdW11bGF0b3IgPSBudWxsO1xuICAgIGVhY2goYXJyYXksIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBhcnJheSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvXiArfCArJC9nLCAnJyk7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbGF0Zm9ybSBvYmplY3QuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgKiBAcGFyYW0ge09iamVjdHxzdHJpbmd9IFt1YT1uYXZpZ2F0b3IudXNlckFnZW50XSBUaGUgdXNlciBhZ2VudCBzdHJpbmcgb3JcbiAgICogIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBIHBsYXRmb3JtIG9iamVjdC5cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlKHVhKSB7XG5cbiAgICAvKiogVGhlIGVudmlyb25tZW50IGNvbnRleHQgb2JqZWN0LiAqL1xuICAgIHZhciBjb250ZXh0ID0gcm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBhIGN1c3RvbSBjb250ZXh0IGlzIHByb3ZpZGVkLiAqL1xuICAgIHZhciBpc0N1c3RvbUNvbnRleHQgPSB1YSAmJiB0eXBlb2YgdWEgPT0gJ29iamVjdCcgJiYgZ2V0Q2xhc3NPZih1YSkgIT0gJ1N0cmluZyc7XG5cbiAgICAvLyBKdWdnbGUgYXJndW1lbnRzLlxuICAgIGlmIChpc0N1c3RvbUNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB1YTtcbiAgICAgIHVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKiogQnJvd3NlciBuYXZpZ2F0b3Igb2JqZWN0LiAqL1xuICAgIHZhciBuYXYgPSBjb250ZXh0Lm5hdmlnYXRvciB8fCB7fTtcblxuICAgIC8qKiBCcm93c2VyIHVzZXIgYWdlbnQgc3RyaW5nLiAqL1xuICAgIHZhciB1c2VyQWdlbnQgPSBuYXYudXNlckFnZW50IHx8ICcnO1xuXG4gICAgdWEgfHwgKHVhID0gdXNlckFnZW50KTtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBgdGhpc0JpbmRpbmdgIGlzIHRoZSBbTW9kdWxlU2NvcGVdLiAqL1xuICAgIHZhciBpc01vZHVsZVNjb3BlID0gaXNDdXN0b21Db250ZXh0IHx8IHRoaXNCaW5kaW5nID09IG9sZFJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYnJvd3NlciBpcyBsaWtlIENocm9tZS4gKi9cbiAgICB2YXIgbGlrZUNocm9tZSA9IGlzQ3VzdG9tQ29udGV4dFxuICAgICAgPyAhIW5hdi5saWtlQ2hyb21lXG4gICAgICA6IC9cXGJDaHJvbWVcXGIvLnRlc3QodWEpICYmICEvaW50ZXJuYWx8XFxuL2kudGVzdCh0b1N0cmluZy50b1N0cmluZygpKTtcblxuICAgIC8qKiBJbnRlcm5hbCBgW1tDbGFzc11dYCB2YWx1ZSBzaG9ydGN1dHMuICovXG4gICAgdmFyIG9iamVjdENsYXNzID0gJ09iamVjdCcsXG4gICAgICAgIGFpclJ1bnRpbWVDbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1NjcmlwdEJyaWRnaW5nUHJveHlPYmplY3QnLFxuICAgICAgICBlbnZpcm9DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ0Vudmlyb25tZW50JyxcbiAgICAgICAgamF2YUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBjb250ZXh0LmphdmEpID8gJ0phdmFQYWNrYWdlJyA6IGdldENsYXNzT2YoY29udGV4dC5qYXZhKSxcbiAgICAgICAgcGhhbnRvbUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnUnVudGltZU9iamVjdCc7XG5cbiAgICAvKiogRGV0ZWN0IEphdmEgZW52aXJvbm1lbnRzLiAqL1xuICAgIHZhciBqYXZhID0gL1xcYkphdmEvLnRlc3QoamF2YUNsYXNzKSAmJiBjb250ZXh0LmphdmE7XG5cbiAgICAvKiogRGV0ZWN0IFJoaW5vLiAqL1xuICAgIHZhciByaGlubyA9IGphdmEgJiYgZ2V0Q2xhc3NPZihjb250ZXh0LmVudmlyb25tZW50KSA9PSBlbnZpcm9DbGFzcztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYWxwaGEuICovXG4gICAgdmFyIGFscGhhID0gamF2YSA/ICdhJyA6ICdcXHUwM2IxJztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYmV0YS4gKi9cbiAgICB2YXIgYmV0YSA9IGphdmEgPyAnYicgOiAnXFx1MDNiMic7XG5cbiAgICAvKiogQnJvd3NlciBkb2N1bWVudCBvYmplY3QuICovXG4gICAgdmFyIGRvYyA9IGNvbnRleHQuZG9jdW1lbnQgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgT3BlcmEgYnJvd3NlciAoUHJlc3RvLWJhc2VkKS5cbiAgICAgKiBodHRwOi8vd3d3Lmhvd3RvY3JlYXRlLmNvLnVrL29wZXJhU3R1ZmYvb3BlcmFPYmplY3QuaHRtbFxuICAgICAqIGh0dHA6Ly9kZXYub3BlcmEuY29tL2FydGljbGVzL3ZpZXcvb3BlcmEtbWluaS13ZWItY29udGVudC1hdXRob3JpbmctZ3VpZGVsaW5lcy8jb3BlcmFtaW5pXG4gICAgICovXG4gICAgdmFyIG9wZXJhID0gY29udGV4dC5vcGVyYW1pbmkgfHwgY29udGV4dC5vcGVyYTtcblxuICAgIC8qKiBPcGVyYSBgW1tDbGFzc11dYC4gKi9cbiAgICB2YXIgb3BlcmFDbGFzcyA9IHJlT3BlcmEudGVzdChvcGVyYUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBvcGVyYSkgPyBvcGVyYVsnW1tDbGFzc11dJ10gOiBnZXRDbGFzc09mKG9wZXJhKSlcbiAgICAgID8gb3BlcmFDbGFzc1xuICAgICAgOiAob3BlcmEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKiBUZW1wb3JhcnkgdmFyaWFibGUgdXNlZCBvdmVyIHRoZSBzY3JpcHQncyBsaWZldGltZS4gKi9cbiAgICB2YXIgZGF0YTtcblxuICAgIC8qKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZS4gKi9cbiAgICB2YXIgYXJjaCA9IHVhO1xuXG4gICAgLyoqIFBsYXRmb3JtIGRlc2NyaXB0aW9uIGFycmF5LiAqL1xuICAgIHZhciBkZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgLyoqIFBsYXRmb3JtIGFscGhhL2JldGEgaW5kaWNhdG9yLiAqL1xuICAgIHZhciBwcmVyZWxlYXNlID0gbnVsbDtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgdGhhdCBlbnZpcm9ubWVudCBmZWF0dXJlcyBzaG91bGQgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwbGF0Zm9ybS4gKi9cbiAgICB2YXIgdXNlRmVhdHVyZXMgPSB1YSA9PSB1c2VyQWdlbnQ7XG5cbiAgICAvKiogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi4gKi9cbiAgICB2YXIgdmVyc2lvbiA9IHVzZUZlYXR1cmVzICYmIG9wZXJhICYmIHR5cGVvZiBvcGVyYS52ZXJzaW9uID09ICdmdW5jdGlvbicgJiYgb3BlcmEudmVyc2lvbigpO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgT1MgZW5kcyB3aXRoIFwiLyBWZXJzaW9uXCIgKi9cbiAgICB2YXIgaXNTcGVjaWFsQ2FzZWRPUztcblxuICAgIC8qIERldGVjdGFibGUgbGF5b3V0IGVuZ2luZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIGxheW91dCA9IGdldExheW91dChbXG4gICAgICB7ICdsYWJlbCc6ICdFZGdlSFRNTCcsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnVHJpZGVudCcsXG4gICAgICB7ICdsYWJlbCc6ICdXZWJLaXQnLCAncGF0dGVybic6ICdBcHBsZVdlYktpdCcgfSxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdQcmVzdG8nLFxuICAgICAgJ05ldEZyb250JyxcbiAgICAgICdUYXNtYW4nLFxuICAgICAgJ0tIVE1MJyxcbiAgICAgICdHZWNrbydcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgYnJvd3NlciBuYW1lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbmFtZSA9IGdldE5hbWUoW1xuICAgICAgJ0Fkb2JlIEFJUicsXG4gICAgICAnQXJvcmEnLFxuICAgICAgJ0F2YW50IEJyb3dzZXInLFxuICAgICAgJ0JyZWFjaCcsXG4gICAgICAnQ2FtaW5vJyxcbiAgICAgICdFbGVjdHJvbicsXG4gICAgICAnRXBpcGhhbnknLFxuICAgICAgJ0Zlbm5lYycsXG4gICAgICAnRmxvY2snLFxuICAgICAgJ0dhbGVvbicsXG4gICAgICAnR3JlZW5Ccm93c2VyJyxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdJY2V3ZWFzZWwnLFxuICAgICAgJ0stTWVsZW9uJyxcbiAgICAgICdLb25xdWVyb3InLFxuICAgICAgJ0x1bmFzY2FwZScsXG4gICAgICAnTWF4dGhvbicsXG4gICAgICB7ICdsYWJlbCc6ICdNaWNyb3NvZnQgRWRnZScsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnTWlkb3JpJyxcbiAgICAgICdOb29rIEJyb3dzZXInLFxuICAgICAgJ1BhbGVNb29uJyxcbiAgICAgICdQaGFudG9tSlMnLFxuICAgICAgJ1JhdmVuJyxcbiAgICAgICdSZWtvbnEnLFxuICAgICAgJ1JvY2tNZWx0JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NhbXN1bmcgSW50ZXJuZXQnLCAncGF0dGVybic6ICdTYW1zdW5nQnJvd3NlcicgfSxcbiAgICAgICdTZWFNb25rZXknLFxuICAgICAgeyAnbGFiZWwnOiAnU2lsaycsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdTbGVpcG5pcicsXG4gICAgICAnU2xpbUJyb3dzZXInLFxuICAgICAgeyAnbGFiZWwnOiAnU1JXYXJlIElyb24nLCAncGF0dGVybic6ICdJcm9uJyB9LFxuICAgICAgJ1N1bnJpc2UnLFxuICAgICAgJ1N3aWZ0Zm94JyxcbiAgICAgICdXYXRlcmZveCcsXG4gICAgICAnV2ViUG9zaXRpdmUnLFxuICAgICAgJ09wZXJhIE1pbmknLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEgTWluaScsICdwYXR0ZXJuJzogJ09QaU9TJyB9LFxuICAgICAgJ09wZXJhJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhJywgJ3BhdHRlcm4nOiAnT1BSJyB9LFxuICAgICAgJ0Nocm9tZScsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgTW9iaWxlJywgJ3BhdHRlcm4nOiAnKD86Q3JpT1N8Q3JNbyknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94JywgJ3BhdHRlcm4nOiAnKD86RmlyZWZveHxNaW5lZmllbGQpJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCBmb3IgaU9TJywgJ3BhdHRlcm4nOiAnRnhpT1MnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ0lFTW9iaWxlJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdNU0lFJyB9LFxuICAgICAgJ1NhZmFyaSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgcHJvZHVjdHMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0JsYWNrQmVycnknLCAncGF0dGVybic6ICdCQjEwJyB9LFxuICAgICAgJ0JsYWNrQmVycnknLFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMnLCAncGF0dGVybic6ICdHVC1JOTAwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMicsICdwYXR0ZXJuJzogJ0dULUk5MTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMzJywgJ3BhdHRlcm4nOiAnR1QtSTkzMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzQnLCAncGF0dGVybic6ICdHVC1JOTUwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNScsICdwYXR0ZXJuJzogJ1NNLUc5MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYnLCAncGF0dGVybic6ICdTTS1HOTIwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTI1JyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3JywgJ3BhdHRlcm4nOiAnU00tRzkzMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNyBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkzNScgfSxcbiAgICAgICdHb29nbGUgVFYnLFxuICAgICAgJ0x1bWlhJyxcbiAgICAgICdpUGFkJyxcbiAgICAgICdpUG9kJyxcbiAgICAgICdpUGhvbmUnLFxuICAgICAgJ0tpbmRsZScsXG4gICAgICB7ICdsYWJlbCc6ICdLaW5kbGUgRmlyZScsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdOZXh1cycsXG4gICAgICAnTm9vaycsXG4gICAgICAnUGxheUJvb2snLFxuICAgICAgJ1BsYXlTdGF0aW9uIFZpdGEnLFxuICAgICAgJ1BsYXlTdGF0aW9uJyxcbiAgICAgICdUb3VjaFBhZCcsXG4gICAgICAnVHJhbnNmb3JtZXInLFxuICAgICAgeyAnbGFiZWwnOiAnV2lpIFUnLCAncGF0dGVybic6ICdXaWlVJyB9LFxuICAgICAgJ1dpaScsXG4gICAgICAnWGJveCBPbmUnLFxuICAgICAgeyAnbGFiZWwnOiAnWGJveCAzNjAnLCAncGF0dGVybic6ICdYYm94JyB9LFxuICAgICAgJ1hvb20nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG1hbnVmYWN0dXJlcnMuICovXG4gICAgdmFyIG1hbnVmYWN0dXJlciA9IGdldE1hbnVmYWN0dXJlcih7XG4gICAgICAnQXBwbGUnOiB7ICdpUGFkJzogMSwgJ2lQaG9uZSc6IDEsICdpUG9kJzogMSB9LFxuICAgICAgJ0FyY2hvcyc6IHt9LFxuICAgICAgJ0FtYXpvbic6IHsgJ0tpbmRsZSc6IDEsICdLaW5kbGUgRmlyZSc6IDEgfSxcbiAgICAgICdBc3VzJzogeyAnVHJhbnNmb3JtZXInOiAxIH0sXG4gICAgICAnQmFybmVzICYgTm9ibGUnOiB7ICdOb29rJzogMSB9LFxuICAgICAgJ0JsYWNrQmVycnknOiB7ICdQbGF5Qm9vayc6IDEgfSxcbiAgICAgICdHb29nbGUnOiB7ICdHb29nbGUgVFYnOiAxLCAnTmV4dXMnOiAxIH0sXG4gICAgICAnSFAnOiB7ICdUb3VjaFBhZCc6IDEgfSxcbiAgICAgICdIVEMnOiB7fSxcbiAgICAgICdMRyc6IHt9LFxuICAgICAgJ01pY3Jvc29mdCc6IHsgJ1hib3gnOiAxLCAnWGJveCBPbmUnOiAxIH0sXG4gICAgICAnTW90b3JvbGEnOiB7ICdYb29tJzogMSB9LFxuICAgICAgJ05pbnRlbmRvJzogeyAnV2lpIFUnOiAxLCAgJ1dpaSc6IDEgfSxcbiAgICAgICdOb2tpYSc6IHsgJ0x1bWlhJzogMSB9LFxuICAgICAgJ1NhbXN1bmcnOiB7ICdHYWxheHkgUyc6IDEsICdHYWxheHkgUzInOiAxLCAnR2FsYXh5IFMzJzogMSwgJ0dhbGF4eSBTNCc6IDEgfSxcbiAgICAgICdTb255JzogeyAnUGxheVN0YXRpb24nOiAxLCAnUGxheVN0YXRpb24gVml0YSc6IDEgfVxuICAgIH0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBvcGVyYXRpbmcgc3lzdGVtcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgb3MgPSBnZXRPUyhbXG4gICAgICAnV2luZG93cyBQaG9uZScsXG4gICAgICAnQW5kcm9pZCcsXG4gICAgICAnQ2VudE9TJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBPUycsICdwYXR0ZXJuJzogJ0NyT1MnIH0sXG4gICAgICAnRGViaWFuJyxcbiAgICAgICdGZWRvcmEnLFxuICAgICAgJ0ZyZWVCU0QnLFxuICAgICAgJ0dlbnRvbycsXG4gICAgICAnSGFpa3UnLFxuICAgICAgJ0t1YnVudHUnLFxuICAgICAgJ0xpbnV4IE1pbnQnLFxuICAgICAgJ09wZW5CU0QnLFxuICAgICAgJ1JlZCBIYXQnLFxuICAgICAgJ1N1U0UnLFxuICAgICAgJ1VidW50dScsXG4gICAgICAnWHVidW50dScsXG4gICAgICAnQ3lnd2luJyxcbiAgICAgICdTeW1iaWFuIE9TJyxcbiAgICAgICdocHdPUycsXG4gICAgICAnd2ViT1MgJyxcbiAgICAgICd3ZWJPUycsXG4gICAgICAnVGFibGV0IE9TJyxcbiAgICAgICdUaXplbicsXG4gICAgICAnTGludXgnLFxuICAgICAgJ01hYyBPUyBYJyxcbiAgICAgICdNYWNpbnRvc2gnLFxuICAgICAgJ01hYycsXG4gICAgICAnV2luZG93cyA5ODsnLFxuICAgICAgJ1dpbmRvd3MgJ1xuICAgIF0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGxheW91dCBlbmdpbmUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbGF5b3V0IGVuZ2luZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMYXlvdXQoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIG1hbnVmYWN0dXJlciBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gb2JqZWN0IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbWFudWZhY3R1cmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlcihndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgICAvLyBMb29rdXAgdGhlIG1hbnVmYWN0dXJlciBieSBwcm9kdWN0IG9yIHNjYW4gdGhlIFVBIGZvciB0aGUgbWFudWZhY3R1cmVyLlxuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChcbiAgICAgICAgICB2YWx1ZVtwcm9kdWN0XSB8fFxuICAgICAgICAgIHZhbHVlWy9eW2Etel0rKD86ICtbYS16XStcXGIpKi9pLmV4ZWMocHJvZHVjdCldIHx8XG4gICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBxdWFsaWZ5KGtleSkgKyAnKD86XFxcXGJ8XFxcXHcqXFxcXGQpJywgJ2knKS5leGVjKHVhKVxuICAgICAgICApICYmIGtleTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBicm93c2VyIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgYnJvd3NlciBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hbWUoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIE9TIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgT1MgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRPUyhndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/Oi9bXFxcXGQuXSt8WyBcXFxcdy5dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xlYW51cE9TKHJlc3VsdCwgcGF0dGVybiwgZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgcHJvZHVjdCBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHByb2R1Y3QgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRQcm9kdWN0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcZCtbLlxcXFx3X10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcdystW1xcXFx3XSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzo7ICooPzpbYS16XStbXy1dKT9bYS16XStcXFxcZCt8W14gKCk7LV0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAvLyBTcGxpdCBieSBmb3J3YXJkIHNsYXNoIGFuZCBhcHBlbmQgcHJvZHVjdCB2ZXJzaW9uIGlmIG5lZWRlZC5cbiAgICAgICAgICBpZiAoKHJlc3VsdCA9IFN0cmluZygoZ3Vlc3MubGFiZWwgJiYgIVJlZ0V4cChwYXR0ZXJuLCAnaScpLnRlc3QoZ3Vlc3MubGFiZWwpKSA/IGd1ZXNzLmxhYmVsIDogcmVzdWx0KS5zcGxpdCgnLycpKVsxXSAmJiAhL1tcXGQuXSsvLnRlc3QocmVzdWx0WzBdKSkge1xuICAgICAgICAgICAgcmVzdWx0WzBdICs9ICcgJyArIHJlc3VsdFsxXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgICAgICAgZ3Vlc3MgPSBndWVzcy5sYWJlbCB8fCBndWVzcztcbiAgICAgICAgICByZXN1bHQgPSBmb3JtYXQocmVzdWx0WzBdXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgZ3Vlc3MpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJzsgKig/OicgKyBndWVzcyArICdbXy1dKT8nLCAnaScpLCAnICcpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJygnICsgZ3Vlc3MgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCAnJDEgJDInKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2ZXJzaW9uIHVzaW5nIGFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXR0ZXJucyBBbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCB2ZXJzaW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZlcnNpb24ocGF0dGVybnMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UocGF0dGVybnMsIGZ1bmN0aW9uKHJlc3VsdCwgcGF0dGVybikge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChSZWdFeHAocGF0dGVybiArXG4gICAgICAgICAgJyg/Oi1bXFxcXGQuXSsvfCg/OiBmb3IgW1xcXFx3LV0rKT9bIC8tXSkoW1xcXFxkLl0rW14gKCk7L18tXSopJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fCBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIHdoZW4gdGhlIHBsYXRmb3JtIG9iamVjdCBpcyBjb2VyY2VkIHRvIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG5hbWUgdG9TdHJpbmdcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgaWYgYXZhaWxhYmxlLCBlbHNlIGFuIGVtcHR5IHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZ1BsYXRmb3JtKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRpb24gfHwgJyc7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQ29udmVydCBsYXlvdXQgdG8gYW4gYXJyYXkgc28gd2UgY2FuIGFkZCBleHRyYSBkZXRhaWxzLlxuICAgIGxheW91dCAmJiAobGF5b3V0ID0gW2xheW91dF0pO1xuXG4gICAgLy8gRGV0ZWN0IHByb2R1Y3QgbmFtZXMgdGhhdCBjb250YWluIHRoZWlyIG1hbnVmYWN0dXJlcidzIG5hbWUuXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiAhcHJvZHVjdCkge1xuICAgICAgcHJvZHVjdCA9IGdldFByb2R1Y3QoW21hbnVmYWN0dXJlcl0pO1xuICAgIH1cbiAgICAvLyBDbGVhbiB1cCBHb29nbGUgVFYuXG4gICAgaWYgKChkYXRhID0gL1xcYkdvb2dsZSBUVlxcYi8uZXhlYyhwcm9kdWN0KSkpIHtcbiAgICAgIHByb2R1Y3QgPSBkYXRhWzBdO1xuICAgIH1cbiAgICAvLyBEZXRlY3Qgc2ltdWxhdG9ycy5cbiAgICBpZiAoL1xcYlNpbXVsYXRvclxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBwcm9kdWN0ID0gKHByb2R1Y3QgPyBwcm9kdWN0ICsgJyAnIDogJycpICsgJ1NpbXVsYXRvcic7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBNaW5pIDgrIHJ1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUgb24gaU9TLlxuICAgIGlmIChuYW1lID09ICdPcGVyYSBNaW5pJyAmJiAvXFxiT1BpT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBNb2JpbGUgMTEuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAvXFxibGlrZSBpUGhvbmUgT1NcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkYXRhID0gcGFyc2UodWEucmVwbGFjZSgvbGlrZSBpUGhvbmUgT1MvLCAnJykpO1xuICAgICAgbWFudWZhY3R1cmVyID0gZGF0YS5tYW51ZmFjdHVyZXI7XG4gICAgICBwcm9kdWN0ID0gZGF0YS5wcm9kdWN0O1xuICAgIH1cbiAgICAvLyBEZXRlY3QgaU9TLlxuICAgIGVsc2UgaWYgKC9eaVAvLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIG5hbWUgfHwgKG5hbWUgPSAnU2FmYXJpJyk7XG4gICAgICBvcyA9ICdpT1MnICsgKChkYXRhID0gLyBPUyAoW1xcZF9dKykvaS5leGVjKHVhKSlcbiAgICAgICAgPyAnICcgKyBkYXRhWzFdLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICA6ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEt1YnVudHUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnS29ucXVlcm9yJyAmJiAhL2J1bnR1L2kudGVzdChvcykpIHtcbiAgICAgIG9zID0gJ0t1YnVudHUnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQW5kcm9pZCBicm93c2Vycy5cbiAgICBlbHNlIGlmICgobWFudWZhY3R1cmVyICYmIG1hbnVmYWN0dXJlciAhPSAnR29vZ2xlJyAmJlxuICAgICAgICAoKC9DaHJvbWUvLnRlc3QobmFtZSkgJiYgIS9cXGJNb2JpbGUgU2FmYXJpXFxiL2kudGVzdCh1YSkpIHx8IC9cXGJWaXRhXFxiLy50ZXN0KHByb2R1Y3QpKSkgfHxcbiAgICAgICAgKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSAmJiAvXkNocm9tZS8udGVzdChuYW1lKSAmJiAvXFxiVmVyc2lvblxcLy9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSA9ICdBbmRyb2lkIEJyb3dzZXInO1xuICAgICAgb3MgPSAvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6ICdBbmRyb2lkJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFNpbGsgZGVza3RvcC9hY2NlbGVyYXRlZCBtb2Rlcy5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTaWxrJykge1xuICAgICAgaWYgKCEvXFxiTW9iaS9pLnRlc3QodWEpKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQnO1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIH1cbiAgICAgIGlmICgvQWNjZWxlcmF0ZWQgKj0gKnRydWUvaS50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdhY2NlbGVyYXRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgUGFsZU1vb24gaWRlbnRpZnlpbmcgYXMgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdQYWxlTW9vbicgJiYgKGRhdGEgPSAvXFxiRmlyZWZveFxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyBGaXJlZm94ICcgKyBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggT1MgYW5kIHByb2R1Y3RzIHJ1bm5pbmcgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdGaXJlZm94JyAmJiAoZGF0YSA9IC9cXGIoTW9iaWxlfFRhYmxldHxUVilcXGIvaS5leGVjKHVhKSkpIHtcbiAgICAgIG9zIHx8IChvcyA9ICdGaXJlZm94IE9TJyk7XG4gICAgICBwcm9kdWN0IHx8IChwcm9kdWN0ID0gZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBmYWxzZSBwb3NpdGl2ZXMgZm9yIEZpcmVmb3gvU2FmYXJpLlxuICAgIGVsc2UgaWYgKCFuYW1lIHx8IChkYXRhID0gIS9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAvXFxiKD86RmlyZWZveHxTYWZhcmkpXFxiLy5leGVjKG5hbWUpKSkge1xuICAgICAgLy8gRXNjYXBlIHRoZSBgL2AgZm9yIEZpcmVmb3ggMS5cbiAgICAgIGlmIChuYW1lICYmICFwcm9kdWN0ICYmIC9bXFwvLF18XlteKF0rP1xcKS8udGVzdCh1YS5zbGljZSh1YS5pbmRleE9mKGRhdGEgKyAnLycpICsgOCkpKSB7XG4gICAgICAgIC8vIENsZWFyIG5hbWUgb2YgZmFsc2UgcG9zaXRpdmVzLlxuICAgICAgICBuYW1lID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFJlYXNzaWduIGEgZ2VuZXJpYyBuYW1lLlxuICAgICAgaWYgKChkYXRhID0gcHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgb3MpICYmXG4gICAgICAgICAgKHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IC9cXGIoPzpBbmRyb2lkfFN5bWJpYW4gT1N8VGFibGV0IE9TfHdlYk9TKVxcYi8udGVzdChvcykpKSB7XG4gICAgICAgIG5hbWUgPSAvW2Etel0rKD86IEhhdCk/L2kuZXhlYygvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6IGRhdGEpICsgJyBCcm93c2VyJztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIENocm9tZSB2ZXJzaW9uIHRvIGRlc2NyaXB0aW9uIGZvciBFbGVjdHJvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdFbGVjdHJvbicgJiYgKGRhdGEgPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBub24tT3BlcmEgKFByZXN0by1iYXNlZCkgdmVyc2lvbnMgKG9yZGVyIGlzIGltcG9ydGFudCkuXG4gICAgaWYgKCF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbihbXG4gICAgICAgICcoPzpDbG91ZDl8Q3JpT1N8Q3JNb3xFZGdlfEZ4aU9TfElFTW9iaWxlfElyb258T3BlcmEgP01pbml8T1BpT1N8T1BSfFJhdmVufFNhbXN1bmdCcm93c2VyfFNpbGsoPyEvW1xcXFxkLl0rJCkpJyxcbiAgICAgICAgJ1ZlcnNpb24nLFxuICAgICAgICBxdWFsaWZ5KG5hbWUpLFxuICAgICAgICAnKD86RmlyZWZveHxNaW5lZmllbGR8TmV0RnJvbnQpJ1xuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBzdHViYm9ybiBsYXlvdXQgZW5naW5lcy5cbiAgICBpZiAoKGRhdGEgPVxuICAgICAgICAgIGxheW91dCA9PSAnaUNhYicgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+IDMgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAvXFxiT3BlcmFcXGIvLnRlc3QobmFtZSkgJiYgKC9cXGJPUFJcXGIvLnRlc3QodWEpID8gJ0JsaW5rJyA6ICdQcmVzdG8nKSB8fFxuICAgICAgICAgIC9cXGIoPzpNaWRvcml8Tm9va3xTYWZhcmkpXFxiL2kudGVzdCh1YSkgJiYgIS9eKD86VHJpZGVudHxFZGdlSFRNTCkkLy50ZXN0KGxheW91dCkgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAhbGF5b3V0ICYmIC9cXGJNU0lFXFxiL2kudGVzdCh1YSkgJiYgKG9zID09ICdNYWMgT1MnID8gJ1Rhc21hbicgOiAnVHJpZGVudCcpIHx8XG4gICAgICAgICAgbGF5b3V0ID09ICdXZWJLaXQnICYmIC9cXGJQbGF5U3RhdGlvblxcYig/ISBWaXRhXFxiKS9pLnRlc3QobmFtZSkgJiYgJ05ldEZyb250J1xuICAgICAgICApKSB7XG4gICAgICBsYXlvdXQgPSBbZGF0YV07XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDcgZGVza3RvcCBtb2RlLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgKGRhdGEgPSAoLzsgKig/OlhCTFdQfFp1bmVXUCkoXFxkKykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSAnICsgKC9cXCskLy50ZXN0KGRhdGEpID8gZGF0YSA6IGRhdGEgKyAnLngnKTtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA4LnggZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKC9cXGJXUERlc2t0b3BcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgbmFtZSA9ICdJRSBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSA4LngnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB2ZXJzaW9uIHx8ICh2ZXJzaW9uID0gKC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpIHx8IDApWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIDExIGlkZW50aWZ5aW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKG5hbWUgIT0gJ0lFJyAmJiBsYXlvdXQgPT0gJ1RyaWRlbnQnICYmIChkYXRhID0gL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkpKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyAnICsgbmFtZSArICh2ZXJzaW9uID8gJyAnICsgdmVyc2lvbiA6ICcnKSk7XG4gICAgICB9XG4gICAgICBuYW1lID0gJ0lFJztcbiAgICAgIHZlcnNpb24gPSBkYXRhWzFdO1xuICAgIH1cbiAgICAvLyBMZXZlcmFnZSBlbnZpcm9ubWVudCBmZWF0dXJlcy5cbiAgICBpZiAodXNlRmVhdHVyZXMpIHtcbiAgICAgIC8vIERldGVjdCBzZXJ2ZXItc2lkZSBlbnZpcm9ubWVudHMuXG4gICAgICAvLyBSaGlubyBoYXMgYSBnbG9iYWwgZnVuY3Rpb24gd2hpbGUgb3RoZXJzIGhhdmUgYSBnbG9iYWwgb2JqZWN0LlxuICAgICAgaWYgKGlzSG9zdFR5cGUoY29udGV4dCwgJ2dsb2JhbCcpKSB7XG4gICAgICAgIGlmIChqYXZhKSB7XG4gICAgICAgICAgZGF0YSA9IGphdmEubGFuZy5TeXN0ZW07XG4gICAgICAgICAgYXJjaCA9IGRhdGEuZ2V0UHJvcGVydHkoJ29zLmFyY2gnKTtcbiAgICAgICAgICBvcyA9IG9zIHx8IGRhdGEuZ2V0UHJvcGVydHkoJ29zLm5hbWUnKSArICcgJyArIGRhdGEuZ2V0UHJvcGVydHkoJ29zLnZlcnNpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmhpbm8pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmVyc2lvbiA9IGNvbnRleHQucmVxdWlyZSgncmluZ28vZW5naW5lJykudmVyc2lvbi5qb2luKCcuJyk7XG4gICAgICAgICAgICBuYW1lID0gJ1JpbmdvSlMnO1xuICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgaWYgKChkYXRhID0gY29udGV4dC5zeXN0ZW0pICYmIGRhdGEuZ2xvYmFsLnN5c3RlbSA9PSBjb250ZXh0LnN5c3RlbSkge1xuICAgICAgICAgICAgICBuYW1lID0gJ05hcndoYWwnO1xuICAgICAgICAgICAgICBvcyB8fCAob3MgPSBkYXRhWzBdLm9zIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnUmhpbm8nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgY29udGV4dC5wcm9jZXNzID09ICdvYmplY3QnICYmICFjb250ZXh0LnByb2Nlc3MuYnJvd3NlciAmJlxuICAgICAgICAgIChkYXRhID0gY29udGV4dC5wcm9jZXNzKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5lbGVjdHJvbiA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ0VsZWN0cm9uJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMuZWxlY3Ryb247XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLm53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyB2ZXJzaW9uLCAnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOVy5qcyc7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLm53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnTm9kZS5qcyc7XG4gICAgICAgICAgICBhcmNoID0gZGF0YS5hcmNoO1xuICAgICAgICAgICAgb3MgPSBkYXRhLnBsYXRmb3JtO1xuICAgICAgICAgICAgdmVyc2lvbiA9IC9bXFxkLl0rLy5leGVjKGRhdGEudmVyc2lvbik7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbiA/IHZlcnNpb25bMF0gOiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEFkb2JlIEFJUi5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnJ1bnRpbWUpKSA9PSBhaXJSdW50aW1lQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdBZG9iZSBBSVInO1xuICAgICAgICBvcyA9IGRhdGEuZmxhc2guc3lzdGVtLkNhcGFiaWxpdGllcy5vcztcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBQaGFudG9tSlMuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5waGFudG9tKSkgPT0gcGhhbnRvbUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnUGhhbnRvbUpTJztcbiAgICAgICAgdmVyc2lvbiA9IChkYXRhID0gZGF0YS52ZXJzaW9uIHx8IG51bGwpICYmIChkYXRhLm1ham9yICsgJy4nICsgZGF0YS5taW5vciArICcuJyArIGRhdGEucGF0Y2gpO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIGNvbXBhdGliaWxpdHkgbW9kZXMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAoZGF0YSA9IC9cXGJUcmlkZW50XFwvKFxcZCspL2kuZXhlYyh1YSkpKSB7XG4gICAgICAgIC8vIFdlJ3JlIGluIGNvbXBhdGliaWxpdHkgbW9kZSB3aGVuIHRoZSBUcmlkZW50IHZlcnNpb24gKyA0IGRvZXNuJ3RcbiAgICAgICAgLy8gZXF1YWwgdGhlIGRvY3VtZW50IG1vZGUuXG4gICAgICAgIHZlcnNpb24gPSBbdmVyc2lvbiwgZG9jLmRvY3VtZW50TW9kZV07XG4gICAgICAgIGlmICgoZGF0YSA9ICtkYXRhWzFdICsgNCkgIT0gdmVyc2lvblsxXSkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0lFICcgKyB2ZXJzaW9uWzFdICsgJyBtb2RlJyk7XG4gICAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnJyk7XG4gICAgICAgICAgdmVyc2lvblsxXSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgdmVyc2lvbiA9IG5hbWUgPT0gJ0lFJyA/IFN0cmluZyh2ZXJzaW9uWzFdLnRvRml4ZWQoMSkpIDogdmVyc2lvblswXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSAxMSBtYXNraW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgL14oPzpDaHJvbWV8RmlyZWZveClcXGIvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnbWFza2luZyBhcyAnICsgbmFtZSArICcgJyArIHZlcnNpb24pO1xuICAgICAgICBuYW1lID0gJ0lFJztcbiAgICAgICAgdmVyc2lvbiA9ICcxMS4wJztcbiAgICAgICAgbGF5b3V0ID0gWydUcmlkZW50J107XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcyAmJiBmb3JtYXQob3MpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgcHJlcmVsZWFzZSBwaGFzZXMuXG4gICAgaWYgKHZlcnNpb24gJiYgKGRhdGEgPVxuICAgICAgICAgIC8oPzpbYWJdfGRwfHByZXxbYWJdXFxkK3ByZSkoPzpcXGQrXFwrPyk/JC9pLmV4ZWModmVyc2lvbikgfHxcbiAgICAgICAgICAvKD86YWxwaGF8YmV0YSkoPzogP1xcZCk/L2kuZXhlYyh1YSArICc7JyArICh1c2VGZWF0dXJlcyAmJiBuYXYuYXBwTWlub3JWZXJzaW9uKSkgfHxcbiAgICAgICAgICAvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgJ2EnXG4gICAgICAgICkpIHtcbiAgICAgIHByZXJlbGVhc2UgPSAvYi9pLnRlc3QoZGF0YSkgPyAnYmV0YScgOiAnYWxwaGEnO1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZShSZWdFeHAoZGF0YSArICdcXFxcKz8kJyksICcnKSArXG4gICAgICAgIChwcmVyZWxlYXNlID09ICdiZXRhJyA/IGJldGEgOiBhbHBoYSkgKyAoL1xcZCtcXCs/Ly5leGVjKGRhdGEpIHx8ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggTW9iaWxlLlxuICAgIGlmIChuYW1lID09ICdGZW5uZWMnIHx8IG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGIoPzpBbmRyb2lkfEZpcmVmb3ggT1MpXFxiLy50ZXN0KG9zKSkge1xuICAgICAgbmFtZSA9ICdGaXJlZm94IE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIE9ic2N1cmUgTWF4dGhvbidzIHVucmVsaWFibGUgdmVyc2lvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdNYXh0aG9uJyAmJiB2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKC9cXC5bXFxkLl0rLywgJy54Jyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBYYm94IDM2MCBhbmQgWGJveCBPbmUuXG4gICAgZWxzZSBpZiAoL1xcYlhib3hcXGIvaS50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnKSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcgJiYgL1xcYklFTW9iaWxlXFxiLy50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdtb2JpbGUgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgbW9iaWxlIHBvc3RmaXguXG4gICAgZWxzZSBpZiAoKC9eKD86Q2hyb21lfElFfE9wZXJhKSQvLnRlc3QobmFtZSkgfHwgbmFtZSAmJiAhcHJvZHVjdCAmJiAhL0Jyb3dzZXJ8TW9iaS8udGVzdChuYW1lKSkgJiZcbiAgICAgICAgKG9zID09ICdXaW5kb3dzIENFJyB8fCAvTW9iaS9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBwbGF0Zm9ybSBwcmV2aWV3LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0lFJyAmJiB1c2VGZWF0dXJlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGNvbnRleHQuZXh0ZXJuYWwgPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdwbGF0Zm9ybSBwcmV2aWV3Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdlbWJlZGRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgQmxhY2tCZXJyeSBPUyB2ZXJzaW9uLlxuICAgIC8vIGh0dHA6Ly9kb2NzLmJsYWNrYmVycnkuY29tL2VuL2RldmVsb3BlcnMvZGVsaXZlcmFibGVzLzE4MTY5L0hUVFBfaGVhZGVyc19zZW50X2J5X0JCX0Jyb3dzZXJfMTIzNDkxMV8xMS5qc3BcbiAgICBlbHNlIGlmICgoL1xcYkJsYWNrQmVycnlcXGIvLnRlc3QocHJvZHVjdCkgfHwgL1xcYkJCMTBcXGIvLnRlc3QodWEpKSAmJiAoZGF0YSA9XG4gICAgICAgICAgKFJlZ0V4cChwcm9kdWN0LnJlcGxhY2UoLyArL2csICcgKicpICsgJy8oWy5cXFxcZF0rKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICkpIHtcbiAgICAgIGRhdGEgPSBbZGF0YSwgL0JCMTAvLnRlc3QodWEpXTtcbiAgICAgIG9zID0gKGRhdGFbMV0gPyAocHJvZHVjdCA9IG51bGwsIG1hbnVmYWN0dXJlciA9ICdCbGFja0JlcnJ5JykgOiAnRGV2aWNlIFNvZnR3YXJlJykgKyAnICcgKyBkYXRhWzBdO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBpZGVudGlmeWluZy9tYXNraW5nIGl0c2VsZiBhcyBhbm90aGVyIGJyb3dzZXIuXG4gICAgLy8gaHR0cDovL3d3dy5vcGVyYS5jb20vc3VwcG9ydC9rYi92aWV3Lzg0My9cbiAgICBlbHNlIGlmICh0aGlzICE9IGZvck93biAmJiBwcm9kdWN0ICE9ICdXaWknICYmIChcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgb3BlcmEpIHx8XG4gICAgICAgICAgKC9PcGVyYS8udGVzdChuYW1lKSAmJiAvXFxiKD86TVNJRXxGaXJlZm94KVxcYi9pLnRlc3QodWEpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiT1MgWCAoPzpcXGQrXFwuKXsyLH0vLnRlc3Qob3MpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdJRScgJiYgKFxuICAgICAgICAgICAgKG9zICYmICEvXldpbi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDUuNSkgfHxcbiAgICAgICAgICAgIC9cXGJXaW5kb3dzIFhQXFxiLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gOCB8fFxuICAgICAgICAgICAgdmVyc2lvbiA9PSA4ICYmICEvXFxiVHJpZGVudFxcYi8udGVzdCh1YSlcbiAgICAgICAgICApKVxuICAgICAgICApICYmICFyZU9wZXJhLnRlc3QoKGRhdGEgPSBwYXJzZS5jYWxsKGZvck93biwgdWEucmVwbGFjZShyZU9wZXJhLCAnJykgKyAnOycpKSkgJiYgZGF0YS5uYW1lKSB7XG4gICAgICAvLyBXaGVuIFwiaWRlbnRpZnlpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIGJvdGggT3BlcmEgYW5kIHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGRhdGEgPSAnaW5nIGFzICcgKyBkYXRhLm5hbWUgKyAoKGRhdGEgPSBkYXRhLnZlcnNpb24pID8gJyAnICsgZGF0YSA6ICcnKTtcbiAgICAgIGlmIChyZU9wZXJhLnRlc3QobmFtZSkpIHtcbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSAmJiBvcyA9PSAnTWFjIE9TJykge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gJ2lkZW50aWZ5JyArIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBXaGVuIFwibWFza2luZ1wiLCB0aGUgVUEgY29udGFpbnMgb25seSB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBlbHNlIHtcbiAgICAgICAgZGF0YSA9ICdtYXNrJyArIGRhdGE7XG4gICAgICAgIGlmIChvcGVyYUNsYXNzKSB7XG4gICAgICAgICAgbmFtZSA9IGZvcm1hdChvcGVyYUNsYXNzLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMSAkMicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lID0gJ09wZXJhJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdXNlRmVhdHVyZXMpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGF5b3V0ID0gWydQcmVzdG8nXTtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXZWJLaXQgTmlnaHRseSBhbmQgYXBwcm94aW1hdGUgQ2hyb21lL1NhZmFyaSB2ZXJzaW9ucy5cbiAgICBpZiAoKGRhdGEgPSAoL1xcYkFwcGxlV2ViS2l0XFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgLy8gQ29ycmVjdCBidWlsZCBudW1iZXIgZm9yIG51bWVyaWMgY29tcGFyaXNvbi5cbiAgICAgIC8vIChlLmcuIFwiNTMyLjVcIiBiZWNvbWVzIFwiNTMyLjA1XCIpXG4gICAgICBkYXRhID0gW3BhcnNlRmxvYXQoZGF0YS5yZXBsYWNlKC9cXC4oXFxkKSQvLCAnLjAkMScpKSwgZGF0YV07XG4gICAgICAvLyBOaWdodGx5IGJ1aWxkcyBhcmUgcG9zdGZpeGVkIHdpdGggYSBcIitcIi5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmIGRhdGFbMV0uc2xpY2UoLTEpID09ICcrJykge1xuICAgICAgICBuYW1lID0gJ1dlYktpdCBOaWdodGx5JztcbiAgICAgICAgcHJlcmVsZWFzZSA9ICdhbHBoYSc7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhWzFdLnNsaWNlKDAsIC0xKTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFyIGluY29ycmVjdCBicm93c2VyIHZlcnNpb25zLlxuICAgICAgZWxzZSBpZiAodmVyc2lvbiA9PSBkYXRhWzFdIHx8XG4gICAgICAgICAgdmVyc2lvbiA9PSAoZGF0YVsyXSA9ICgvXFxiU2FmYXJpXFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgZnVsbCBDaHJvbWUgdmVyc2lvbiB3aGVuIGF2YWlsYWJsZS5cbiAgICAgIGRhdGFbMV0gPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKS9pLmV4ZWModWEpIHx8IDApWzFdO1xuICAgICAgLy8gRGV0ZWN0IEJsaW5rIGxheW91dCBlbmdpbmUuXG4gICAgICBpZiAoZGF0YVswXSA9PSA1MzcuMzYgJiYgZGF0YVsyXSA9PSA1MzcuMzYgJiYgcGFyc2VGbG9hdChkYXRhWzFdKSA+PSAyOCAmJiBsYXlvdXQgPT0gJ1dlYktpdCcpIHtcbiAgICAgICAgbGF5b3V0ID0gWydCbGluayddO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEphdmFTY3JpcHRDb3JlLlxuICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzY4NDc0L2hvdy1jYW4taS1kZXRlY3Qtd2hpY2gtamF2YXNjcmlwdC1lbmdpbmUtdjgtb3ItanNjLWlzLXVzZWQtYXQtcnVudGltZS1pbi1hbmRyb2lcbiAgICAgIGlmICghdXNlRmVhdHVyZXMgfHwgKCFsaWtlQ2hyb21lICYmICFkYXRhWzFdKSkge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIFNhZmFyaScpO1xuICAgICAgICBkYXRhID0gKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNDAwID8gMSA6IGRhdGEgPCA1MDAgPyAyIDogZGF0YSA8IDUyNiA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQgPyAnNCsnIDogZGF0YSA8IDUzNSA/IDUgOiBkYXRhIDwgNTM3ID8gNiA6IGRhdGEgPCA1MzggPyA3IDogZGF0YSA8IDYwMSA/IDggOiAnOCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBDaHJvbWUnKTtcbiAgICAgICAgZGF0YSA9IGRhdGFbMV0gfHwgKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNTMwID8gMSA6IGRhdGEgPCA1MzIgPyAyIDogZGF0YSA8IDUzMi4wNSA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQuMDMgPyA1IDogZGF0YSA8IDUzNC4wNyA/IDYgOiBkYXRhIDwgNTM0LjEwID8gNyA6IGRhdGEgPCA1MzQuMTMgPyA4IDogZGF0YSA8IDUzNC4xNiA/IDkgOiBkYXRhIDwgNTM0LjI0ID8gMTAgOiBkYXRhIDwgNTM0LjMwID8gMTEgOiBkYXRhIDwgNTM1LjAxID8gMTIgOiBkYXRhIDwgNTM1LjAyID8gJzEzKycgOiBkYXRhIDwgNTM1LjA3ID8gMTUgOiBkYXRhIDwgNTM1LjExID8gMTYgOiBkYXRhIDwgNTM1LjE5ID8gMTcgOiBkYXRhIDwgNTM2LjA1ID8gMTggOiBkYXRhIDwgNTM2LjEwID8gMTkgOiBkYXRhIDwgNTM3LjAxID8gMjAgOiBkYXRhIDwgNTM3LjExID8gJzIxKycgOiBkYXRhIDwgNTM3LjEzID8gMjMgOiBkYXRhIDwgNTM3LjE4ID8gMjQgOiBkYXRhIDwgNTM3LjI0ID8gMjUgOiBkYXRhIDwgNTM3LjM2ID8gMjYgOiBsYXlvdXQgIT0gJ0JsaW5rJyA/ICcyNycgOiAnMjgnKTtcbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgcG9zdGZpeCBvZiBcIi54XCIgb3IgXCIrXCIgZm9yIGFwcHJveGltYXRlIHZlcnNpb25zLlxuICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gKz0gJyAnICsgKGRhdGEgKz0gdHlwZW9mIGRhdGEgPT0gJ251bWJlcicgPyAnLngnIDogL1suK10vLnRlc3QoZGF0YSkgPyAnJyA6ICcrJykpO1xuICAgICAgLy8gT2JzY3VyZSB2ZXJzaW9uIGZvciBzb21lIFNhZmFyaSAxLTIgcmVsZWFzZXMuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAoIXZlcnNpb24gfHwgcGFyc2VJbnQodmVyc2lvbikgPiA0NSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IGRhdGE7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBkZXNrdG9wIG1vZGVzLlxuICAgIGlmIChuYW1lID09ICdPcGVyYScgJiYgIChkYXRhID0gL1xcYnpib3Z8enZhdiQvLmV4ZWMob3MpKSkge1xuICAgICAgbmFtZSArPSAnICc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIGlmIChkYXRhID09ICd6dmF2Jykge1xuICAgICAgICBuYW1lICs9ICdNaW5pJztcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuYW1lICs9ICdNb2JpbGUnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSArICckJyksICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IENocm9tZSBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAvXFxiQ2hyb21lXFxiLy5leGVjKGxheW91dCAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIG5hbWUgPSAnQ2hyb21lIE1vYmlsZSc7XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcblxuICAgICAgaWYgKC9cXGJPUyBYXFxiLy50ZXN0KG9zKSkge1xuICAgICAgICBtYW51ZmFjdHVyZXIgPSAnQXBwbGUnO1xuICAgICAgICBvcyA9ICdpT1MgNC4zKyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFN0cmlwIGluY29ycmVjdCBPUyB2ZXJzaW9ucy5cbiAgICBpZiAodmVyc2lvbiAmJiB2ZXJzaW9uLmluZGV4T2YoKGRhdGEgPSAvW1xcZC5dKyQvLmV4ZWMob3MpKSkgPT0gMCAmJlxuICAgICAgICB1YS5pbmRleE9mKCcvJyArIGRhdGEgKyAnLScpID4gLTEpIHtcbiAgICAgIG9zID0gdHJpbShvcy5yZXBsYWNlKGRhdGEsICcnKSk7XG4gICAgfVxuICAgIC8vIEFkZCBsYXlvdXQgZW5naW5lLlxuICAgIGlmIChsYXlvdXQgJiYgIS9cXGIoPzpBdmFudHxOb29rKVxcYi8udGVzdChuYW1lKSAmJiAoXG4gICAgICAgIC9Ccm93c2VyfEx1bmFzY2FwZXxNYXh0aG9uLy50ZXN0KG5hbWUpIHx8XG4gICAgICAgIG5hbWUgIT0gJ1NhZmFyaScgJiYgL15pT1MvLnRlc3Qob3MpICYmIC9cXGJTYWZhcmlcXGIvLnRlc3QobGF5b3V0WzFdKSB8fFxuICAgICAgICAvXig/OkFkb2JlfEFyb3JhfEJyZWFjaHxNaWRvcml8T3BlcmF8UGhhbnRvbXxSZWtvbnF8Um9ja3xTYW1zdW5nIEludGVybmV0fFNsZWlwbmlyfFdlYikvLnRlc3QobmFtZSkgJiYgbGF5b3V0WzFdKSkge1xuICAgICAgLy8gRG9uJ3QgYWRkIGxheW91dCBkZXRhaWxzIHRvIGRlc2NyaXB0aW9uIGlmIHRoZXkgYXJlIGZhbHNleS5cbiAgICAgIChkYXRhID0gbGF5b3V0W2xheW91dC5sZW5ndGggLSAxXSkgJiYgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gQ29tYmluZSBjb250ZXh0dWFsIGluZm9ybWF0aW9uLlxuICAgIGlmIChkZXNjcmlwdGlvbi5sZW5ndGgpIHtcbiAgICAgIGRlc2NyaXB0aW9uID0gWycoJyArIGRlc2NyaXB0aW9uLmpvaW4oJzsgJykgKyAnKSddO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgbWFudWZhY3R1cmVyIHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgcHJvZHVjdCAmJiBwcm9kdWN0LmluZGV4T2YobWFudWZhY3R1cmVyKSA8IDApIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ29uICcgKyBtYW51ZmFjdHVyZXIpO1xuICAgIH1cbiAgICAvLyBBcHBlbmQgcHJvZHVjdCB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAocHJvZHVjdCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgoL15vbiAvLnRlc3QoZGVzY3JpcHRpb25bZGVzY3JpcHRpb24ubGVuZ3RoIC0gMV0pID8gJycgOiAnb24gJykgKyBwcm9kdWN0KTtcbiAgICB9XG4gICAgLy8gUGFyc2UgdGhlIE9TIGludG8gYW4gb2JqZWN0LlxuICAgIGlmIChvcykge1xuICAgICAgZGF0YSA9IC8gKFtcXGQuK10rKSQvLmV4ZWMob3MpO1xuICAgICAgaXNTcGVjaWFsQ2FzZWRPUyA9IGRhdGEgJiYgb3MuY2hhckF0KG9zLmxlbmd0aCAtIGRhdGFbMF0ubGVuZ3RoIC0gMSkgPT0gJy8nO1xuICAgICAgb3MgPSB7XG4gICAgICAgICdhcmNoaXRlY3R1cmUnOiAzMixcbiAgICAgICAgJ2ZhbWlseSc6IChkYXRhICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/IG9zLnJlcGxhY2UoZGF0YVswXSwgJycpIDogb3MsXG4gICAgICAgICd2ZXJzaW9uJzogZGF0YSA/IGRhdGFbMV0gOiBudWxsLFxuICAgICAgICAndG9TdHJpbmcnOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgdmVyc2lvbiA9IHRoaXMudmVyc2lvbjtcbiAgICAgICAgICByZXR1cm4gdGhpcy5mYW1pbHkgKyAoKHZlcnNpb24gJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gJyAnICsgdmVyc2lvbiA6ICcnKSArICh0aGlzLmFyY2hpdGVjdHVyZSA9PSA2NCA/ICcgNjQtYml0JyA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gQWRkIGJyb3dzZXIvT1MgYXJjaGl0ZWN0dXJlLlxuICAgIGlmICgoZGF0YSA9IC9cXGIoPzpBTUR8SUF8V2lufFdPV3x4ODZffHgpNjRcXGIvaS5leGVjKGFyY2gpKSAmJiAhL1xcYmk2ODZcXGIvaS50ZXN0KGFyY2gpKSB7XG4gICAgICBpZiAob3MpIHtcbiAgICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgICAgIG9zLmZhbWlseSA9IG9zLmZhbWlseS5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSksICcnKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgICBuYW1lICYmICgvXFxiV09XNjRcXGIvaS50ZXN0KHVhKSB8fFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiAvXFx3KD86ODZ8MzIpJC8udGVzdChuYXYuY3B1Q2xhc3MgfHwgbmF2LnBsYXRmb3JtKSAmJiAhL1xcYldpbjY0OyB4NjRcXGIvaS50ZXN0KHVhKSkpXG4gICAgICApIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnMzItYml0Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENocm9tZSAzOSBhbmQgYWJvdmUgb24gT1MgWCBpcyBhbHdheXMgNjQtYml0LlxuICAgIGVsc2UgaWYgKFxuICAgICAgICBvcyAmJiAvXk9TIFgvLnRlc3Qob3MuZmFtaWx5KSAmJlxuICAgICAgICBuYW1lID09ICdDaHJvbWUnICYmIHBhcnNlRmxvYXQodmVyc2lvbikgPj0gMzlcbiAgICApIHtcbiAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgIH1cblxuICAgIHVhIHx8ICh1YSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBuYW1lIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgdmFyIHBsYXRmb3JtID0ge307XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gZGVzY3JpcHRpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmRlc2NyaXB0aW9uID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3NlcidzIGxheW91dCBlbmdpbmUuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gbGF5b3V0IGVuZ2luZXMgaW5jbHVkZTpcbiAgICAgKiBcIkJsaW5rXCIsIFwiRWRnZUhUTUxcIiwgXCJHZWNrb1wiLCBcIlRyaWRlbnRcIiBhbmQgXCJXZWJLaXRcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5sYXlvdXQgPSBsYXlvdXQgJiYgbGF5b3V0WzBdO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QncyBtYW51ZmFjdHVyZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBtYW51ZmFjdHVyZXJzIGluY2x1ZGU6XG4gICAgICogXCJBcHBsZVwiLCBcIkFyY2hvc1wiLCBcIkFtYXpvblwiLCBcIkFzdXNcIiwgXCJCYXJuZXMgJiBOb2JsZVwiLCBcIkJsYWNrQmVycnlcIixcbiAgICAgKiBcIkdvb2dsZVwiLCBcIkhQXCIsIFwiSFRDXCIsIFwiTEdcIiwgXCJNaWNyb3NvZnRcIiwgXCJNb3Rvcm9sYVwiLCBcIk5pbnRlbmRvXCIsXG4gICAgICogXCJOb2tpYVwiLCBcIlNhbXN1bmdcIiBhbmQgXCJTb255XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubWFudWZhY3R1cmVyID0gbWFudWZhY3R1cmVyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIvZW52aXJvbm1lbnQuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gYnJvd3NlciBuYW1lcyBpbmNsdWRlOlxuICAgICAqIFwiQ2hyb21lXCIsIFwiRWxlY3Ryb25cIiwgXCJGaXJlZm94XCIsIFwiRmlyZWZveCBmb3IgaU9TXCIsIFwiSUVcIixcbiAgICAgKiBcIk1pY3Jvc29mdCBFZGdlXCIsIFwiUGhhbnRvbUpTXCIsIFwiU2FmYXJpXCIsIFwiU2VhTW9ua2V5XCIsIFwiU2lsa1wiLFxuICAgICAqIFwiT3BlcmEgTWluaVwiIGFuZCBcIk9wZXJhXCJcbiAgICAgKlxuICAgICAqIE1vYmlsZSB2ZXJzaW9ucyBvZiBzb21lIGJyb3dzZXJzIGhhdmUgXCJNb2JpbGVcIiBhcHBlbmRlZCB0byB0aGVpciBuYW1lOlxuICAgICAqIGVnLiBcIkNocm9tZSBNb2JpbGVcIiwgXCJGaXJlZm94IE1vYmlsZVwiLCBcIklFIE1vYmlsZVwiIGFuZCBcIk9wZXJhIE1vYmlsZVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm5hbWUgPSBuYW1lO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFscGhhL2JldGEgcmVsZWFzZSBpbmRpY2F0b3IuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByZXJlbGVhc2UgPSBwcmVyZWxlYXNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIHByb2R1Y3QgaG9zdGluZyB0aGUgYnJvd3Nlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBwcm9kdWN0cyBpbmNsdWRlOlxuICAgICAqXG4gICAgICogXCJCbGFja0JlcnJ5XCIsIFwiR2FsYXh5IFM0XCIsIFwiTHVtaWFcIiwgXCJpUGFkXCIsIFwiaVBvZFwiLCBcImlQaG9uZVwiLCBcIktpbmRsZVwiLFxuICAgICAqIFwiS2luZGxlIEZpcmVcIiwgXCJOZXh1c1wiLCBcIk5vb2tcIiwgXCJQbGF5Qm9va1wiLCBcIlRvdWNoUGFkXCIgYW5kIFwiVHJhbnNmb3JtZXJcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcm9kdWN0ID0gcHJvZHVjdDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyJ3MgdXNlciBhZ2VudCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnVhID0gdWE7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS52ZXJzaW9uID0gbmFtZSAmJiB2ZXJzaW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5vcyA9IG9zIHx8IHtcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZSB0aGUgT1MgaXMgYnVpbHQgZm9yLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgbnVtYmVyfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2FyY2hpdGVjdHVyZSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIGZhbWlseSBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQ29tbW9uIHZhbHVlcyBpbmNsdWRlOlxuICAgICAgICogXCJXaW5kb3dzXCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCBSMiAvIDdcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IC8gVmlzdGFcIixcbiAgICAgICAqIFwiV2luZG93cyBYUFwiLCBcIk9TIFhcIiwgXCJVYnVudHVcIiwgXCJEZWJpYW5cIiwgXCJGZWRvcmFcIiwgXCJSZWQgSGF0XCIsIFwiU3VTRVwiLFxuICAgICAgICogXCJBbmRyb2lkXCIsIFwiaU9TXCIgYW5kIFwiV2luZG93cyBQaG9uZVwiXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAnZmFtaWx5JzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAndmVyc2lvbic6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogUmV0dXJucyB0aGUgT1Mgc3RyaW5nLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIE9TIHN0cmluZy5cbiAgICAgICAqL1xuICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7IHJldHVybiAnbnVsbCc7IH1cbiAgICB9O1xuXG4gICAgcGxhdGZvcm0ucGFyc2UgPSBwYXJzZTtcbiAgICBwbGF0Zm9ybS50b1N0cmluZyA9IHRvU3RyaW5nUGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0udmVyc2lvbikge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCh2ZXJzaW9uKTtcbiAgICB9XG4gICAgaWYgKHBsYXRmb3JtLm5hbWUpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuICAgIGlmIChvcyAmJiBuYW1lICYmICEob3MgPT0gU3RyaW5nKG9zKS5zcGxpdCgnICcpWzBdICYmIChvcyA9PSBuYW1lLnNwbGl0KCcgJylbMF0gfHwgcHJvZHVjdCkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKHByb2R1Y3QgPyAnKCcgKyBvcyArICcpJyA6ICdvbiAnICsgb3MpO1xuICAgIH1cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLmpvaW4oJyAnKTtcbiAgICB9XG4gICAgcmV0dXJuIHBsYXRmb3JtO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IHBsYXRmb3JtLlxuICB2YXIgcGxhdGZvcm0gPSBwYXJzZSgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMsIGxpa2Ugci5qcywgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEV4cG9zZSBwbGF0Zm9ybSBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIHBsYXRmb3JtIGlzXG4gICAgLy8gbG9hZGVkIGJ5IGEgc2NyaXB0IHRhZyBpbiB0aGUgcHJlc2VuY2Ugb2YgYW4gQU1EIGxvYWRlci5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvIHBsYXRmb3JtIGNhbiBiZSBhbGlhc2VkIHRocm91Z2ggcGF0aCBtYXBwaW5nLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBhbiBgZXhwb3J0c2Agb2JqZWN0LlxuICBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZvck93bihwbGF0Zm9ybSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgZnJlZUV4cG9ydHNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJ2YXIgdjEgPSByZXF1aXJlKCcuL3YxJyk7XG52YXIgdjQgPSByZXF1aXJlKCcuL3Y0Jyk7XG5cbnZhciB1dWlkID0gdjQ7XG51dWlkLnYxID0gdjE7XG51dWlkLnY0ID0gdjQ7XG5cbm1vZHVsZS5leHBvcnRzID0gdXVpZDtcbiIsIi8qKlxuICogQ29udmVydCBhcnJheSBvZiAxNiBieXRlIHZhbHVlcyB0byBVVUlEIHN0cmluZyBmb3JtYXQgb2YgdGhlIGZvcm06XG4gKiBYWFhYWFhYWC1YWFhYLVhYWFgtWFhYWC1YWFhYWFhYWFhYWFhcbiAqL1xudmFyIGJ5dGVUb0hleCA9IFtdO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICBieXRlVG9IZXhbaV0gPSAoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpO1xufVxuXG5mdW5jdGlvbiBieXRlc1RvVXVpZChidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IG9mZnNldCB8fCAwO1xuICB2YXIgYnRoID0gYnl0ZVRvSGV4O1xuICByZXR1cm4gYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArICctJyArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gKyAnLScgK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dICsgJy0nICtcbiAgICAgICAgICBidGhbYnVmW2krK11dICsgYnRoW2J1ZltpKytdXSArXG4gICAgICAgICAgYnRoW2J1ZltpKytdXSArIGJ0aFtidWZbaSsrXV0gK1xuICAgICAgICAgIGJ0aFtidWZbaSsrXV0gKyBidGhbYnVmW2krK11dO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJ5dGVzVG9VdWlkO1xuIiwiLy8gVW5pcXVlIElEIGNyZWF0aW9uIHJlcXVpcmVzIGEgaGlnaCBxdWFsaXR5IHJhbmRvbSAjIGdlbmVyYXRvci4gIEluIHRoZVxuLy8gYnJvd3NlciB0aGlzIGlzIGEgbGl0dGxlIGNvbXBsaWNhdGVkIGR1ZSB0byB1bmtub3duIHF1YWxpdHkgb2YgTWF0aC5yYW5kb20oKVxuLy8gYW5kIGluY29uc2lzdGVudCBzdXBwb3J0IGZvciB0aGUgYGNyeXB0b2AgQVBJLiAgV2UgZG8gdGhlIGJlc3Qgd2UgY2FuIHZpYVxuLy8gZmVhdHVyZS1kZXRlY3Rpb25cblxuLy8gZ2V0UmFuZG9tVmFsdWVzIG5lZWRzIHRvIGJlIGludm9rZWQgaW4gYSBjb250ZXh0IHdoZXJlIFwidGhpc1wiIGlzIGEgQ3J5cHRvIGltcGxlbWVudGF0aW9uLlxudmFyIGdldFJhbmRvbVZhbHVlcyA9ICh0eXBlb2YoY3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQoY3J5cHRvKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAodHlwZW9mKG1zQ3J5cHRvKSAhPSAndW5kZWZpbmVkJyAmJiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChtc0NyeXB0bykpO1xuaWYgKGdldFJhbmRvbVZhbHVlcykge1xuICAvLyBXSEFUV0cgY3J5cHRvIFJORyAtIGh0dHA6Ly93aWtpLndoYXR3Zy5vcmcvd2lraS9DcnlwdG9cbiAgdmFyIHJuZHM4ID0gbmV3IFVpbnQ4QXJyYXkoMTYpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB3aGF0d2dSTkcoKSB7XG4gICAgZ2V0UmFuZG9tVmFsdWVzKHJuZHM4KTtcbiAgICByZXR1cm4gcm5kczg7XG4gIH07XG59IGVsc2Uge1xuICAvLyBNYXRoLnJhbmRvbSgpLWJhc2VkIChSTkcpXG4gIC8vXG4gIC8vIElmIGFsbCBlbHNlIGZhaWxzLCB1c2UgTWF0aC5yYW5kb20oKS4gIEl0J3MgZmFzdCwgYnV0IGlzIG9mIHVuc3BlY2lmaWVkXG4gIC8vIHF1YWxpdHkuXG4gIHZhciBybmRzID0gbmV3IEFycmF5KDE2KTtcblxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1hdGhSTkcoKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIHI7IGkgPCAxNjsgaSsrKSB7XG4gICAgICBpZiAoKGkgJiAweDAzKSA9PT0gMCkgciA9IE1hdGgucmFuZG9tKCkgKiAweDEwMDAwMDAwMDtcbiAgICAgIHJuZHNbaV0gPSByID4+PiAoKGkgJiAweDAzKSA8PCAzKSAmIDB4ZmY7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJuZHM7XG4gIH07XG59XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG4vLyAqKmB2MSgpYCAtIEdlbmVyYXRlIHRpbWUtYmFzZWQgVVVJRCoqXG4vL1xuLy8gSW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL0xpb3NLL1VVSUQuanNcbi8vIGFuZCBodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvdXVpZC5odG1sXG5cbnZhciBfbm9kZUlkO1xudmFyIF9jbG9ja3NlcTtcblxuLy8gUHJldmlvdXMgdXVpZCBjcmVhdGlvbiB0aW1lXG52YXIgX2xhc3RNU2VjcyA9IDA7XG52YXIgX2xhc3ROU2VjcyA9IDA7XG5cbi8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYnJvb2ZhL25vZGUtdXVpZCBmb3IgQVBJIGRldGFpbHNcbmZ1bmN0aW9uIHYxKG9wdGlvbnMsIGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gYnVmICYmIG9mZnNldCB8fCAwO1xuICB2YXIgYiA9IGJ1ZiB8fCBbXTtcblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgdmFyIG5vZGUgPSBvcHRpb25zLm5vZGUgfHwgX25vZGVJZDtcbiAgdmFyIGNsb2Nrc2VxID0gb3B0aW9ucy5jbG9ja3NlcSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jbG9ja3NlcSA6IF9jbG9ja3NlcTtcblxuICAvLyBub2RlIGFuZCBjbG9ja3NlcSBuZWVkIHRvIGJlIGluaXRpYWxpemVkIHRvIHJhbmRvbSB2YWx1ZXMgaWYgdGhleSdyZSBub3RcbiAgLy8gc3BlY2lmaWVkLiAgV2UgZG8gdGhpcyBsYXppbHkgdG8gbWluaW1pemUgaXNzdWVzIHJlbGF0ZWQgdG8gaW5zdWZmaWNpZW50XG4gIC8vIHN5c3RlbSBlbnRyb3B5LiAgU2VlICMxODlcbiAgaWYgKG5vZGUgPT0gbnVsbCB8fCBjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgdmFyIHNlZWRCeXRlcyA9IHJuZygpO1xuICAgIGlmIChub2RlID09IG51bGwpIHtcbiAgICAgIC8vIFBlciA0LjUsIGNyZWF0ZSBhbmQgNDgtYml0IG5vZGUgaWQsICg0NyByYW5kb20gYml0cyArIG11bHRpY2FzdCBiaXQgPSAxKVxuICAgICAgbm9kZSA9IF9ub2RlSWQgPSBbXG4gICAgICAgIHNlZWRCeXRlc1swXSB8IDB4MDEsXG4gICAgICAgIHNlZWRCeXRlc1sxXSwgc2VlZEJ5dGVzWzJdLCBzZWVkQnl0ZXNbM10sIHNlZWRCeXRlc1s0XSwgc2VlZEJ5dGVzWzVdXG4gICAgICBdO1xuICAgIH1cbiAgICBpZiAoY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuMi4yLCByYW5kb21pemUgKDE0IGJpdCkgY2xvY2tzZXFcbiAgICAgIGNsb2Nrc2VxID0gX2Nsb2Nrc2VxID0gKHNlZWRCeXRlc1s2XSA8PCA4IHwgc2VlZEJ5dGVzWzddKSAmIDB4M2ZmZjtcbiAgICB9XG4gIH1cblxuICAvLyBVVUlEIHRpbWVzdGFtcHMgYXJlIDEwMCBuYW5vLXNlY29uZCB1bml0cyBzaW5jZSB0aGUgR3JlZ29yaWFuIGVwb2NoLFxuICAvLyAoMTU4Mi0xMC0xNSAwMDowMCkuICBKU051bWJlcnMgYXJlbid0IHByZWNpc2UgZW5vdWdoIGZvciB0aGlzLCBzb1xuICAvLyB0aW1lIGlzIGhhbmRsZWQgaW50ZXJuYWxseSBhcyAnbXNlY3MnIChpbnRlZ2VyIG1pbGxpc2Vjb25kcykgYW5kICduc2VjcydcbiAgLy8gKDEwMC1uYW5vc2Vjb25kcyBvZmZzZXQgZnJvbSBtc2Vjcykgc2luY2UgdW5peCBlcG9jaCwgMTk3MC0wMS0wMSAwMDowMC5cbiAgdmFyIG1zZWNzID0gb3B0aW9ucy5tc2VjcyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5tc2VjcyA6IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuXG4gIC8vIFBlciA0LjIuMS4yLCB1c2UgY291bnQgb2YgdXVpZCdzIGdlbmVyYXRlZCBkdXJpbmcgdGhlIGN1cnJlbnQgY2xvY2tcbiAgLy8gY3ljbGUgdG8gc2ltdWxhdGUgaGlnaGVyIHJlc29sdXRpb24gY2xvY2tcbiAgdmFyIG5zZWNzID0gb3B0aW9ucy5uc2VjcyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5uc2VjcyA6IF9sYXN0TlNlY3MgKyAxO1xuXG4gIC8vIFRpbWUgc2luY2UgbGFzdCB1dWlkIGNyZWF0aW9uIChpbiBtc2VjcylcbiAgdmFyIGR0ID0gKG1zZWNzIC0gX2xhc3RNU2VjcykgKyAobnNlY3MgLSBfbGFzdE5TZWNzKS8xMDAwMDtcblxuICAvLyBQZXIgNC4yLjEuMiwgQnVtcCBjbG9ja3NlcSBvbiBjbG9jayByZWdyZXNzaW9uXG4gIGlmIChkdCA8IDAgJiYgb3B0aW9ucy5jbG9ja3NlcSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgY2xvY2tzZXEgPSBjbG9ja3NlcSArIDEgJiAweDNmZmY7XG4gIH1cblxuICAvLyBSZXNldCBuc2VjcyBpZiBjbG9jayByZWdyZXNzZXMgKG5ldyBjbG9ja3NlcSkgb3Igd2UndmUgbW92ZWQgb250byBhIG5ld1xuICAvLyB0aW1lIGludGVydmFsXG4gIGlmICgoZHQgPCAwIHx8IG1zZWNzID4gX2xhc3RNU2VjcykgJiYgb3B0aW9ucy5uc2VjcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbnNlY3MgPSAwO1xuICB9XG5cbiAgLy8gUGVyIDQuMi4xLjIgVGhyb3cgZXJyb3IgaWYgdG9vIG1hbnkgdXVpZHMgYXJlIHJlcXVlc3RlZFxuICBpZiAobnNlY3MgPj0gMTAwMDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3V1aWQudjEoKTogQ2FuXFwndCBjcmVhdGUgbW9yZSB0aGFuIDEwTSB1dWlkcy9zZWMnKTtcbiAgfVxuXG4gIF9sYXN0TVNlY3MgPSBtc2VjcztcbiAgX2xhc3ROU2VjcyA9IG5zZWNzO1xuICBfY2xvY2tzZXEgPSBjbG9ja3NlcTtcblxuICAvLyBQZXIgNC4xLjQgLSBDb252ZXJ0IGZyb20gdW5peCBlcG9jaCB0byBHcmVnb3JpYW4gZXBvY2hcbiAgbXNlY3MgKz0gMTIyMTkyOTI4MDAwMDA7XG5cbiAgLy8gYHRpbWVfbG93YFxuICB2YXIgdGwgPSAoKG1zZWNzICYgMHhmZmZmZmZmKSAqIDEwMDAwICsgbnNlY3MpICUgMHgxMDAwMDAwMDA7XG4gIGJbaSsrXSA9IHRsID4+PiAyNCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiAxNiAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdGwgJiAweGZmO1xuXG4gIC8vIGB0aW1lX21pZGBcbiAgdmFyIHRtaCA9IChtc2VjcyAvIDB4MTAwMDAwMDAwICogMTAwMDApICYgMHhmZmZmZmZmO1xuICBiW2krK10gPSB0bWggPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bWggJiAweGZmO1xuXG4gIC8vIGB0aW1lX2hpZ2hfYW5kX3ZlcnNpb25gXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMjQgJiAweGYgfCAweDEwOyAvLyBpbmNsdWRlIHZlcnNpb25cbiAgYltpKytdID0gdG1oID4+PiAxNiAmIDB4ZmY7XG5cbiAgLy8gYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgIChQZXIgNC4yLjIgLSBpbmNsdWRlIHZhcmlhbnQpXG4gIGJbaSsrXSA9IGNsb2Nrc2VxID4+PiA4IHwgMHg4MDtcblxuICAvLyBgY2xvY2tfc2VxX2xvd2BcbiAgYltpKytdID0gY2xvY2tzZXEgJiAweGZmO1xuXG4gIC8vIGBub2RlYFxuICBmb3IgKHZhciBuID0gMDsgbiA8IDY7ICsrbikge1xuICAgIGJbaSArIG5dID0gbm9kZVtuXTtcbiAgfVxuXG4gIHJldHVybiBidWYgPyBidWYgOiBieXRlc1RvVXVpZChiKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB2MTtcbiIsInZhciBybmcgPSByZXF1aXJlKCcuL2xpYi9ybmcnKTtcbnZhciBieXRlc1RvVXVpZCA9IHJlcXVpcmUoJy4vbGliL2J5dGVzVG9VdWlkJyk7XG5cbmZ1bmN0aW9uIHY0KG9wdGlvbnMsIGJ1Ziwgb2Zmc2V0KSB7XG4gIHZhciBpID0gYnVmICYmIG9mZnNldCB8fCAwO1xuXG4gIGlmICh0eXBlb2Yob3B0aW9ucykgPT0gJ3N0cmluZycpIHtcbiAgICBidWYgPSBvcHRpb25zID09PSAnYmluYXJ5JyA/IG5ldyBBcnJheSgxNikgOiBudWxsO1xuICAgIG9wdGlvbnMgPSBudWxsO1xuICB9XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBybmRzID0gb3B0aW9ucy5yYW5kb20gfHwgKG9wdGlvbnMucm5nIHx8IHJuZykoKTtcblxuICAvLyBQZXIgNC40LCBzZXQgYml0cyBmb3IgdmVyc2lvbiBhbmQgYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgXG4gIHJuZHNbNl0gPSAocm5kc1s2XSAmIDB4MGYpIHwgMHg0MDtcbiAgcm5kc1s4XSA9IChybmRzWzhdICYgMHgzZikgfCAweDgwO1xuXG4gIC8vIENvcHkgYnl0ZXMgdG8gYnVmZmVyLCBpZiBwcm92aWRlZFxuICBpZiAoYnVmKSB7XG4gICAgZm9yICh2YXIgaWkgPSAwOyBpaSA8IDE2OyArK2lpKSB7XG4gICAgICBidWZbaSArIGlpXSA9IHJuZHNbaWldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWYgfHwgYnl0ZXNUb1V1aWQocm5kcyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjQ7XG4iLCIvKlxyXG5XaWxkRW1pdHRlci5qcyBpcyBhIHNsaW0gbGl0dGxlIGV2ZW50IGVtaXR0ZXIgYnkgQGhlbnJpa2pvcmV0ZWcgbGFyZ2VseSBiYXNlZFxyXG5vbiBAdmlzaW9ubWVkaWEncyBFbWl0dGVyIGZyb20gVUkgS2l0LlxyXG5cclxuV2h5PyBJIHdhbnRlZCBpdCBzdGFuZGFsb25lLlxyXG5cclxuSSBhbHNvIHdhbnRlZCBzdXBwb3J0IGZvciB3aWxkY2FyZCBlbWl0dGVycyBsaWtlIHRoaXM6XHJcblxyXG5lbWl0dGVyLm9uKCcqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgb3RoZXIsIGV2ZW50LCBwYXlsb2Fkcykge1xyXG5cclxufSk7XHJcblxyXG5lbWl0dGVyLm9uKCdzb21lbmFtZXNwYWNlKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIHBheWxvYWRzKSB7XHJcblxyXG59KTtcclxuXHJcblBsZWFzZSBub3RlIHRoYXQgY2FsbGJhY2tzIHRyaWdnZXJlZCBieSB3aWxkY2FyZCByZWdpc3RlcmVkIGV2ZW50cyBhbHNvIGdldFxyXG50aGUgZXZlbnQgbmFtZSBhcyB0aGUgZmlyc3QgYXJndW1lbnQuXHJcbiovXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IFdpbGRFbWl0dGVyO1xyXG5cclxuZnVuY3Rpb24gV2lsZEVtaXR0ZXIoKSB7IH1cclxuXHJcbldpbGRFbWl0dGVyLm1peGluID0gZnVuY3Rpb24gKGNvbnN0cnVjdG9yKSB7XHJcbiAgICB2YXIgcHJvdG90eXBlID0gY29uc3RydWN0b3IucHJvdG90eXBlIHx8IGNvbnN0cnVjdG9yO1xyXG5cclxuICAgIHByb3RvdHlwZS5pc1dpbGRFbWl0dGVyPSB0cnVlO1xyXG5cclxuICAgIC8vIExpc3RlbiBvbiB0aGUgZ2l2ZW4gYGV2ZW50YCB3aXRoIGBmbmAuIFN0b3JlIGEgZ3JvdXAgbmFtZSBpZiBwcmVzZW50LlxyXG4gICAgcHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXHJcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcclxuICAgICAgICBmdW5jLl9ncm91cE5hbWUgPSBncm91cDtcclxuICAgICAgICAodGhpcy5jYWxsYmFja3NbZXZlbnRdID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdIHx8IFtdKS5wdXNoKGZ1bmMpO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBBZGRzIGFuIGBldmVudGAgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBzaW5nbGVcclxuICAgIC8vIHRpbWUgdGhlbiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQuXHJcbiAgICBwcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xyXG4gICAgICAgIHZhciBzZWxmID0gdGhpcyxcclxuICAgICAgICAgICAgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXHJcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcclxuICAgICAgICBmdW5jdGlvbiBvbigpIHtcclxuICAgICAgICAgICAgc2VsZi5vZmYoZXZlbnQsIG9uKTtcclxuICAgICAgICAgICAgZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLm9uKGV2ZW50LCBncm91cCwgb24pO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBVbmJpbmRzIGFuIGVudGlyZSBncm91cFxyXG4gICAgcHJvdG90eXBlLnJlbGVhc2VHcm91cCA9IGZ1bmN0aW9uIChncm91cE5hbWUpIHtcclxuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xyXG4gICAgICAgIHZhciBpdGVtLCBpLCBsZW4sIGhhbmRsZXJzO1xyXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBoYW5kbGVycyA9IHRoaXMuY2FsbGJhY2tzW2l0ZW1dO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBoYW5kbGVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICAgICAgICAgICAgaWYgKGhhbmRsZXJzW2ldLl9ncm91cE5hbWUgPT09IGdyb3VwTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coJ3JlbW92aW5nJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0IGFuZCBzaG9ydGVuIHRoZSBhcnJheSB3ZSdyZSBsb29waW5nIHRocm91Z2hcclxuICAgICAgICAgICAgICAgICAgICBoYW5kbGVycy5zcGxpY2UoaSwgMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaS0tO1xyXG4gICAgICAgICAgICAgICAgICAgIGxlbi0tO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBSZW1vdmUgdGhlIGdpdmVuIGNhbGxiYWNrIGZvciBgZXZlbnRgIG9yIGFsbFxyXG4gICAgLy8gcmVnaXN0ZXJlZCBjYWxsYmFja3MuXHJcbiAgICBwcm90b3R5cGUub2ZmID0gZnVuY3Rpb24gKGV2ZW50LCBmbikge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcclxuICAgICAgICAgICAgaTtcclxuXHJcbiAgICAgICAgaWYgKCFjYWxsYmFja3MpIHJldHVybiB0aGlzO1xyXG5cclxuICAgICAgICAvLyByZW1vdmUgYWxsIGhhbmRsZXJzXHJcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcclxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyByZW1vdmUgc3BlY2lmaWMgaGFuZGxlclxyXG4gICAgICAgIGkgPSBjYWxsYmFja3MuaW5kZXhPZihmbik7XHJcbiAgICAgICAgY2FsbGJhY2tzLnNwbGljZShpLCAxKTtcclxuICAgICAgICBpZiAoY2FsbGJhY2tzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8vIEVtaXQgYGV2ZW50YCB3aXRoIHRoZSBnaXZlbiBhcmdzLlxyXG4gICAgLy8gYWxzbyBjYWxscyBhbnkgYCpgIGhhbmRsZXJzXHJcbiAgICBwcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIChldmVudCkge1xyXG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XHJcbiAgICAgICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXHJcbiAgICAgICAgICAgIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcclxuICAgICAgICAgICAgc3BlY2lhbENhbGxiYWNrcyA9IHRoaXMuZ2V0V2lsZGNhcmRDYWxsYmFja3MoZXZlbnQpLFxyXG4gICAgICAgICAgICBpLFxyXG4gICAgICAgICAgICBsZW4sXHJcbiAgICAgICAgICAgIGl0ZW0sXHJcbiAgICAgICAgICAgIGxpc3RlbmVycztcclxuXHJcbiAgICAgICAgaWYgKGNhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBjYWxsYmFja3Muc2xpY2UoKTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoc3BlY2lhbENhbGxiYWNrcykge1xyXG4gICAgICAgICAgICBsZW4gPSBzcGVjaWFsQ2FsbGJhY2tzLmxlbmd0aDtcclxuICAgICAgICAgICAgbGlzdGVuZXJzID0gc3BlY2lhbENhbGxiYWNrcy5zbGljZSgpO1xyXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgW2V2ZW50XS5jb25jYXQoYXJncykpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLy8gSGVscGVyIGZvciBmb3IgZmluZGluZyBzcGVjaWFsIHdpbGRjYXJkIGV2ZW50IGhhbmRsZXJzIHRoYXQgbWF0Y2ggdGhlIGV2ZW50XHJcbiAgICBwcm90b3R5cGUuZ2V0V2lsZGNhcmRDYWxsYmFja3MgPSBmdW5jdGlvbiAoZXZlbnROYW1lKSB7XHJcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcclxuICAgICAgICB2YXIgaXRlbSxcclxuICAgICAgICAgICAgc3BsaXQsXHJcbiAgICAgICAgICAgIHJlc3VsdCA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcclxuICAgICAgICAgICAgc3BsaXQgPSBpdGVtLnNwbGl0KCcqJyk7XHJcbiAgICAgICAgICAgIGlmIChpdGVtID09PSAnKicgfHwgKHNwbGl0Lmxlbmd0aCA9PT0gMiAmJiBldmVudE5hbWUuc2xpY2UoMCwgc3BsaXRbMF0ubGVuZ3RoKSA9PT0gc3BsaXRbMF0pKSB7XHJcbiAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KHRoaXMuY2FsbGJhY2tzW2l0ZW1dKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfTtcclxuXHJcbn07XHJcblxyXG5XaWxkRW1pdHRlci5taXhpbihXaWxkRW1pdHRlcik7XHJcbiIsIi8qIVxuICogRXZlbnRFbWl0dGVyIHY1LjIuNCAtIGdpdC5pby9lZVxuICogVW5saWNlbnNlIC0gaHR0cDovL3VubGljZW5zZS5vcmcvXG4gKiBPbGl2ZXIgQ2FsZHdlbGwgLSBodHRwOi8vb2xpLm1lLnVrL1xuICogQHByZXNlcnZlXG4gKi9cblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuICAgICd1c2Ugc3RyaWN0JztcblxuICAgIC8qKlxuICAgICAqIENsYXNzIGZvciBtYW5hZ2luZyBldmVudHMuXG4gICAgICogQ2FuIGJlIGV4dGVuZGVkIHRvIHByb3ZpZGUgZXZlbnQgZnVuY3Rpb25hbGl0eSBpbiBvdGhlciBjbGFzc2VzLlxuICAgICAqXG4gICAgICogQGNsYXNzIEV2ZW50RW1pdHRlciBNYW5hZ2VzIGV2ZW50IHJlZ2lzdGVyaW5nIGFuZCBlbWl0dGluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7fVxuXG4gICAgLy8gU2hvcnRjdXRzIHRvIGltcHJvdmUgc3BlZWQgYW5kIHNpemVcbiAgICB2YXIgcHJvdG8gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlO1xuICAgIHZhciBvcmlnaW5hbEdsb2JhbFZhbHVlID0gZXhwb3J0cy5FdmVudEVtaXR0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyB0aGUgaW5kZXggb2YgdGhlIGxpc3RlbmVyIGZvciB0aGUgZXZlbnQgaW4gaXRzIHN0b3JhZ2UgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IGxpc3RlbmVycyBBcnJheSBvZiBsaXN0ZW5lcnMgdG8gc2VhcmNoIHRocm91Z2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGxvb2sgZm9yLlxuICAgICAqIEByZXR1cm4ge051bWJlcn0gSW5kZXggb2YgdGhlIHNwZWNpZmllZCBsaXN0ZW5lciwgLTEgaWYgbm90IGZvdW5kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVycywgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzW2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFsaWFzIGEgbWV0aG9kIHdoaWxlIGtlZXBpbmcgdGhlIGNvbnRleHQgY29ycmVjdCwgdG8gYWxsb3cgZm9yIG92ZXJ3cml0aW5nIG9mIHRhcmdldCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGFsaWFzZWQgbWV0aG9kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWxpYXMobmFtZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gYWxpYXNDbG9zdXJlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbbmFtZV0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBsaXN0ZW5lciBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaWxsIGluaXRpYWxpc2UgdGhlIGV2ZW50IG9iamVjdCBhbmQgbGlzdGVuZXIgYXJyYXlzIGlmIHJlcXVpcmVkLlxuICAgICAqIFdpbGwgcmV0dXJuIGFuIG9iamVjdCBpZiB5b3UgdXNlIGEgcmVnZXggc2VhcmNoLiBUaGUgb2JqZWN0IGNvbnRhaW5zIGtleXMgZm9yIGVhY2ggbWF0Y2hlZCBldmVudC4gU28gL2JhW3J6XS8gbWlnaHQgcmV0dXJuIGFuIG9iamVjdCBjb250YWluaW5nIGJhciBhbmQgYmF6LiBCdXQgb25seSBpZiB5b3UgaGF2ZSBlaXRoZXIgZGVmaW5lZCB0aGVtIHdpdGggZGVmaW5lRXZlbnQgb3IgYWRkZWQgc29tZSBsaXN0ZW5lcnMgdG8gdGhlbS5cbiAgICAgKiBFYWNoIHByb3BlcnR5IGluIHRoZSBvYmplY3QgcmVzcG9uc2UgaXMgYW4gYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfE9iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgdGhlIGV2ZW50LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldExpc3RlbmVycyhldnQpIHtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmV0dXJuIGEgY29uY2F0ZW5hdGVkIGFycmF5IG9mIGFsbCBtYXRjaGluZyBldmVudHMgaWZcbiAgICAgICAgLy8gdGhlIHNlbGVjdG9yIGlzIGEgcmVndWxhciBleHByZXNzaW9uLlxuICAgICAgICBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2Vba2V5XSA9IGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0gZXZlbnRzW2V2dF0gfHwgKGV2ZW50c1tldnRdID0gW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGxpc3Qgb2YgbGlzdGVuZXIgb2JqZWN0cyBhbmQgZmxhdHRlbnMgaXQgaW50byBhIGxpc3Qgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3RbXX0gbGlzdGVuZXJzIFJhdyBsaXN0ZW5lciBvYmplY3RzLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW119IEp1c3QgdGhlIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKi9cbiAgICBwcm90by5mbGF0dGVuTGlzdGVuZXJzID0gZnVuY3Rpb24gZmxhdHRlbkxpc3RlbmVycyhsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGZsYXRMaXN0ZW5lcnMgPSBbXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgZmxhdExpc3RlbmVycy5wdXNoKGxpc3RlbmVyc1tpXS5saXN0ZW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmxhdExpc3RlbmVycztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgcmVxdWVzdGVkIGxpc3RlbmVycyB2aWEgZ2V0TGlzdGVuZXJzIGJ1dCB3aWxsIGFsd2F5cyByZXR1cm4gdGhlIHJlc3VsdHMgaW5zaWRlIGFuIG9iamVjdC4gVGhpcyBpcyBtYWlubHkgZm9yIGludGVybmFsIHVzZSBidXQgb3RoZXJzIG1heSBmaW5kIGl0IHVzZWZ1bC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciBhbiBldmVudCBpbiBhbiBvYmplY3QuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzQXNPYmplY3QgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnNBc09iamVjdChldnQpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBpZiAobGlzdGVuZXJzIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICByZXNwb25zZVtldnRdID0gbGlzdGVuZXJzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlIHx8IGxpc3RlbmVycztcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gaXNWYWxpZExpc3RlbmVyIChsaXN0ZW5lcikge1xuICAgICAgICBpZiAodHlwZW9mIGxpc3RlbmVyID09PSAnZnVuY3Rpb24nIHx8IGxpc3RlbmVyIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9IGVsc2UgaWYgKGxpc3RlbmVyICYmIHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIubGlzdGVuZXIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBsaXN0ZW5lciBmdW5jdGlvbiB0byB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFRoZSBsaXN0ZW5lciB3aWxsIG5vdCBiZSBhZGRlZCBpZiBpdCBpcyBhIGR1cGxpY2F0ZS5cbiAgICAgKiBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGl0IGlzIGNhbGxlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSB0aGVuIHRoZSBsaXN0ZW5lciB3aWxsIGJlIGFkZGVkIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICghaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJJc1dyYXBwZWQgPSB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnB1c2gobGlzdGVuZXJJc1dyYXBwZWQgPyBsaXN0ZW5lciA6IHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgICAgICAgICBvbmNlOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZExpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub24gPSBhbGlhcygnYWRkTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIFNlbWktYWxpYXMgb2YgYWRkTGlzdGVuZXIuIEl0IHdpbGwgYWRkIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlXG4gICAgICogYXV0b21hdGljYWxseSByZW1vdmVkIGFmdGVyIGl0cyBmaXJzdCBleGVjdXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZE9uY2VMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZE9uY2VMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZExpc3RlbmVyKGV2dCwge1xuICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgb25jZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkT25jZUxpc3RlbmVyLlxuICAgICAqL1xuICAgIHByb3RvLm9uY2UgPSBhbGlhcygnYWRkT25jZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmVzIGFuIGV2ZW50IG5hbWUuIFRoaXMgaXMgcmVxdWlyZWQgaWYgeW91IHdhbnQgdG8gdXNlIGEgcmVnZXggdG8gYWRkIGEgbGlzdGVuZXIgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIElmIHlvdSBkb24ndCBkbyB0aGlzIHRoZW4gaG93IGRvIHlvdSBleHBlY3QgaXQgdG8ga25vdyB3aGF0IGV2ZW50IHRvIGFkZCB0bz8gU2hvdWxkIGl0IGp1c3QgYWRkIHRvIGV2ZXJ5IHBvc3NpYmxlIG1hdGNoIGZvciBhIHJlZ2V4PyBOby4gVGhhdCBpcyBzY2FyeSBhbmQgYmFkLlxuICAgICAqIFlvdSBuZWVkIHRvIHRlbGwgaXQgd2hhdCBldmVudCBuYW1lcyBzaG91bGQgYmUgbWF0Y2hlZCBieSBhIHJlZ2V4LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBjcmVhdGUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnQgPSBmdW5jdGlvbiBkZWZpbmVFdmVudChldnQpIHtcbiAgICAgICAgdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFVzZXMgZGVmaW5lRXZlbnQgdG8gZGVmaW5lIG11bHRpcGxlIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nW119IGV2dHMgQW4gYXJyYXkgb2YgZXZlbnQgbmFtZXMgdG8gZGVmaW5lLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50cyA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50cyhldnRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXZ0cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgdGhpcy5kZWZpbmVFdmVudChldnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIGZyb20gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaGVuIHBhc3NlZCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSwgaXQgd2lsbCByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byByZW1vdmUgZnJvbSB0aGUgZXZlbnQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBpbmRleDtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcik7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUxpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub2ZmID0gYWxpYXMoJ3JlbW92ZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBhZGQgdGhlIGFycmF5IG9mIGxpc3RlbmVycyB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICogWWVhaCwgdGhpcyBmdW5jdGlvbiBkb2VzIHF1aXRlIGEgYml0LiBUaGF0J3MgcHJvYmFibHkgYSBiYWQgdGhpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyhmYWxzZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byByZW1vdmUgdGhlIGxpc3RlbmVycyBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byByZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXJzID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnModHJ1ZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBFZGl0cyBsaXN0ZW5lcnMgaW4gYnVsay4gVGhlIGFkZExpc3RlbmVycyBhbmQgcmVtb3ZlTGlzdGVuZXJzIG1ldGhvZHMgYm90aCB1c2UgdGhpcyB0byBkbyB0aGVpciBqb2IuIFlvdSBzaG91bGQgcmVhbGx5IHVzZSB0aG9zZSBpbnN0ZWFkLCB0aGlzIGlzIGEgbGl0dGxlIGxvd2VyIGxldmVsLlxuICAgICAqIFRoZSBmaXJzdCBhcmd1bWVudCB3aWxsIGRldGVybWluZSBpZiB0aGUgbGlzdGVuZXJzIGFyZSByZW1vdmVkICh0cnVlKSBvciBhZGRlZCAoZmFsc2UpLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHlvdSBjYW4gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkL3JlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gbWFuaXB1bGF0ZSB0aGUgbGlzdGVuZXJzIG9mIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVtb3ZlIFRydWUgaWYgeW91IHdhbnQgdG8gcmVtb3ZlIGxpc3RlbmVycywgZmFsc2UgaWYgeW91IHdhbnQgdG8gYWRkLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkL3JlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5tYW5pcHVsYXRlTGlzdGVuZXJzID0gZnVuY3Rpb24gbWFuaXB1bGF0ZUxpc3RlbmVycyhyZW1vdmUsIGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgdmFsdWU7XG4gICAgICAgIHZhciBzaW5nbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVyIDogdGhpcy5hZGRMaXN0ZW5lcjtcbiAgICAgICAgdmFyIG11bHRpcGxlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lcnMgOiB0aGlzLmFkZExpc3RlbmVycztcblxuICAgICAgICAvLyBJZiBldnQgaXMgYW4gb2JqZWN0IHRoZW4gcGFzcyBlYWNoIG9mIGl0cyBwcm9wZXJ0aWVzIHRvIHRoaXMgbWV0aG9kXG4gICAgICAgIGlmICh0eXBlb2YgZXZ0ID09PSAnb2JqZWN0JyAmJiAhKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgICAgICAgIGZvciAoaSBpbiBldnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZ0Lmhhc093blByb3BlcnR5KGkpICYmICh2YWx1ZSA9IGV2dFtpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGFzcyB0aGUgc2luZ2xlIGxpc3RlbmVyIHN0cmFpZ2h0IHRocm91Z2ggdG8gdGhlIHNpbmd1bGFyIG1ldGhvZFxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgcGFzcyBiYWNrIHRvIHRoZSBtdWx0aXBsZSBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBTbyBldnQgbXVzdCBiZSBhIHN0cmluZ1xuICAgICAgICAgICAgLy8gQW5kIGxpc3RlbmVycyBtdXN0IGJlIGFuIGFycmF5IG9mIGxpc3RlbmVyc1xuICAgICAgICAgICAgLy8gTG9vcCBvdmVyIGl0IGFuZCBwYXNzIGVhY2ggb25lIHRvIHRoZSBtdWx0aXBsZSBtZXRob2RcbiAgICAgICAgICAgIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGV2dCwgbGlzdGVuZXJzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgZnJvbSBhIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBJZiB5b3UgZG8gbm90IHNwZWNpZnkgYW4gZXZlbnQgdGhlbiBhbGwgbGlzdGVuZXJzIHdpbGwgYmUgcmVtb3ZlZC5cbiAgICAgKiBUaGF0IG1lYW5zIGV2ZXJ5IGV2ZW50IHdpbGwgYmUgZW1wdGllZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ2V4IHRvIHJlbW92ZSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IFtldnRdIE9wdGlvbmFsIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvci4gV2lsbCByZW1vdmUgZnJvbSBldmVyeSBldmVudCBpZiBub3QgcGFzc2VkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24gcmVtb3ZlRXZlbnQoZXZ0KSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mIGV2dDtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJlbW92ZSBkaWZmZXJlbnQgdGhpbmdzIGRlcGVuZGluZyBvbiB0aGUgc3RhdGUgb2YgZXZ0XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbZXZ0XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgZXZlbnRzIG1hdGNoaW5nIHRoZSByZWdleC5cbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBpbiBhbGwgZXZlbnRzXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUV2ZW50LlxuICAgICAqXG4gICAgICogQWRkZWQgdG8gbWlycm9yIHRoZSBub2RlIEFQSS5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBhbGlhcygncmVtb3ZlRXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGFuIGV2ZW50IG9mIHlvdXIgY2hvaWNlLlxuICAgICAqIFdoZW4gZW1pdHRlZCwgZXZlcnkgbGlzdGVuZXIgYXR0YWNoZWQgdG8gdGhhdCBldmVudCB3aWxsIGJlIGV4ZWN1dGVkLlxuICAgICAqIElmIHlvdSBwYXNzIHRoZSBvcHRpb25hbCBhcmd1bWVudCBhcnJheSB0aGVuIHRob3NlIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCB0byBldmVyeSBsaXN0ZW5lciB1cG9uIGV4ZWN1dGlvbi5cbiAgICAgKiBCZWNhdXNlIGl0IHVzZXMgYGFwcGx5YCwgeW91ciBhcnJheSBvZiBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgYXMgaWYgeW91IHdyb3RlIHRoZW0gb3V0IHNlcGFyYXRlbHkuXG4gICAgICogU28gdGhleSB3aWxsIG5vdCBhcnJpdmUgd2l0aGluIHRoZSBhcnJheSBvbiB0aGUgb3RoZXIgc2lkZSwgdGhleSB3aWxsIGJlIHNlcGFyYXRlLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthcmdzXSBPcHRpb25hbCBhcnJheSBvZiBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdEV2ZW50ID0gZnVuY3Rpb24gZW1pdEV2ZW50KGV2dCwgYXJncykge1xuICAgICAgICB2YXIgbGlzdGVuZXJzTWFwID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJzO1xuICAgICAgICB2YXIgbGlzdGVuZXI7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzTWFwKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzTWFwLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnNNYXBba2V5XS5zbGljZSgwKTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHNoYWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkIGVpdGhlciB3aXRoIGEgYmFzaWMgY2FsbCBvciBhbiBhcHBseSBpZiB0aGVyZSBpcyBhbiBhcmdzIGFycmF5XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChsaXN0ZW5lci5vbmNlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBsaXN0ZW5lci5saXN0ZW5lci5hcHBseSh0aGlzLCBhcmdzIHx8IFtdKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgPT09IHRoaXMuX2dldE9uY2VSZXR1cm5WYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGVtaXRFdmVudFxuICAgICAqL1xuICAgIHByb3RvLnRyaWdnZXIgPSBhbGlhcygnZW1pdEV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBTdWJ0bHkgZGlmZmVyZW50IGZyb20gZW1pdEV2ZW50IGluIHRoYXQgaXQgd2lsbCBwYXNzIGl0cyBhcmd1bWVudHMgb24gdG8gdGhlIGxpc3RlbmVycywgYXMgb3Bwb3NlZCB0byB0YWtpbmcgYSBzaW5nbGUgYXJyYXkgb2YgYXJndW1lbnRzIHRvIHBhc3Mgb24uXG4gICAgICogQXMgd2l0aCBlbWl0RXZlbnQsIHlvdSBjYW4gcGFzcyBhIHJlZ2V4IGluIHBsYWNlIG9mIHRoZSBldmVudCBuYW1lIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gT3B0aW9uYWwgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdCA9IGZ1bmN0aW9uIGVtaXQoZXZ0KSB7XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW1pdEV2ZW50KGV2dCwgYXJncyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmIGFcbiAgICAgKiBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhlIG9uZSBzZXQgaGVyZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZFxuICAgICAqIGFmdGVyIGV4ZWN1dGlvbi4gVGhpcyB2YWx1ZSBkZWZhdWx0cyB0byB0cnVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbmV3IHZhbHVlIHRvIGNoZWNrIGZvciB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uc2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gc2V0T25jZVJldHVyblZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX29uY2VSZXR1cm5WYWx1ZSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWZcbiAgICAgKiB0aGUgbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoaXMgb25lIHRoZW4gaXQgc2hvdWxkIGJlIHJlbW92ZWRcbiAgICAgKiBhdXRvbWF0aWNhbGx5LiBJdCB3aWxsIHJldHVybiB0cnVlIGJ5IGRlZmF1bHQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHsqfEJvb2xlYW59IFRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGZvciBvciB0aGUgZGVmYXVsdCwgdHJ1ZS5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gX2dldE9uY2VSZXR1cm5WYWx1ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkoJ19vbmNlUmV0dXJuVmFsdWUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29uY2VSZXR1cm5WYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGV2ZW50cyBvYmplY3QgYW5kIGNyZWF0ZXMgb25lIGlmIHJlcXVpcmVkLlxuICAgICAqXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgZXZlbnRzIHN0b3JhZ2Ugb2JqZWN0LlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRFdmVudHMgPSBmdW5jdGlvbiBfZ2V0RXZlbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXZlbnRzIHx8ICh0aGlzLl9ldmVudHMgPSB7fSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJldmVydHMgdGhlIGdsb2JhbCB7QGxpbmsgRXZlbnRFbWl0dGVyfSB0byBpdHMgcHJldmlvdXMgdmFsdWUgYW5kIHJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhpcyB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IE5vbiBjb25mbGljdGluZyBFdmVudEVtaXR0ZXIgY2xhc3MuXG4gICAgICovXG4gICAgRXZlbnRFbWl0dGVyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiBub0NvbmZsaWN0KCkge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IG9yaWdpbmFsR2xvYmFsVmFsdWU7XG4gICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgfTtcblxuICAgIC8vIEV4cG9zZSB0aGUgY2xhc3MgZWl0aGVyIHZpYSBBTUQsIENvbW1vbkpTIG9yIHRoZSBnbG9iYWwgb2JqZWN0XG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKXtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG59KHRoaXMgfHwge30pKTtcbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdS9PcGVuVmlkdSc7XG5cbmlmICh3aW5kb3cpIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tc3RyaW5nLWxpdGVyYWxcbiAgICB3aW5kb3dbJ09wZW5WaWR1J10gPSBPcGVuVmlkdTtcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IFN0cmVhbU9wdGlvbnNTZXJ2ZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TdHJlYW1PcHRpb25zU2VydmVyJztcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG5cbiAgICAgICAgbGV0IG1zZyA9IFwiJ0Nvbm5lY3Rpb24nIGNyZWF0ZWQgXCI7XG4gICAgICAgIGlmICghIW9wdHMpIHtcbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgb3B0cy5pZCArICddJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5pbmZvKG1zZyk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcblxuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSBvcHRzLmlkO1xuICAgICAgICAgICAgaWYgKG9wdHMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBvcHRzLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdHMuc3RyZWFtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFJlbW90ZVN0cmVhbXMob3B0cy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpOiB2b2lkIHtcblxuICAgICAgICBjb25zb2xlLmRlYnVnKCghIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCcgOiAnUmVtb3RlJyksICdjYW5kaWRhdGUgZm9yJyxcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkLCBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcblxuICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ29uSWNlQ2FuZGlkYXRlJywge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJ1xuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0UmVtb3RlU3RyZWFtcyhvcHRpb25zOiBTdHJlYW1PcHRpb25zU2VydmVyW10pOiB2b2lkIHtcblxuICAgICAgICAvLyBUaGlzIGlzIHJlYWR5IGZvciBzdXBwb3J0aW5nIG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb24gb2JqZWN0LiBSaWdodCBub3cgdGhlIGxvb3Agd2lsbCBhbHdheXMgcnVuIGp1c3Qgb25jZVxuICAgICAgICAvLyB0aGlzLnN0cmVhbSBzaG91bGQgYWxzbyBiZSByZXBsYWNlZCBieSBhIGNvbGxlY3Rpb24gb2Ygc3RyZWFtcyB0byBzdXBwb3J0IG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb25cbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IG9wdHMuaWQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogdGhpcyxcbiAgICAgICAgICAgICAgICBmcmFtZVJhdGU6IG9wdHMuZnJhbWVSYXRlLFxuICAgICAgICAgICAgICAgIHJlY3ZBdWRpbzogb3B0cy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICByZWN2VmlkZW86IG9wdHMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW9cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyZWFtKHRoaXMuc2Vzc2lvbiwgc3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgIHRoaXMuYWRkU3RyZWFtKHN0cmVhbSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnQ29ubmVjdGlvbicgd2l0aCAnY29ubmVjdGlvbklkJyBbXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArICddIGlzIG5vdyBjb25maWd1cmVkIGZvciByZWNlaXZpbmcgU3RyZWFtcyB3aXRoIG9wdGlvbnM6ICcsIHRoaXMuc3RyZWFtLmluYm91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkU3RyZWFtKHN0cmVhbTogU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5jb25uZWN0aW9uID0gdGhpcztcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZVN0cmVhbShzdHJlYW1JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IExvY2FsUmVjb3JkZXJTdGF0ZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmRlY2xhcmUgdmFyIE1lZGlhUmVjb3JkZXI6IGFueTtcblxuXG4vKipcbiAqIEVhc3kgcmVjb3JkaW5nIG9mIFtbU3RyZWFtXV0gb2JqZWN0cyBzdHJhaWdodGF3YXkgZnJvbSB0aGUgYnJvd3Nlci5cbiAqXG4gKiA+IFdBUk5JTkc6IFBlcmZvcm1pbmcgYnJvd3NlciBsb2NhbCByZWNvcmRpbmcgb2YgKipyZW1vdGUgc3RyZWFtcyoqIG1heSBjYXVzZSBzb21lIHRyb3VibGVzLiBBIGxvbmcgd2FpdGluZyB0aW1lIG1heSBiZSByZXF1aXJlZCBhZnRlciBjYWxsaW5nIF9Mb2NhbFJlY29yZGVyLnN0b3AoKV8gaW4gdGhpcyBjYXNlXG4gKi9cbmV4cG9ydCBjbGFzcyBMb2NhbFJlY29yZGVyIHtcblxuICAgIHN0YXRlOiBMb2NhbFJlY29yZGVyU3RhdGU7XG5cbiAgICBwcml2YXRlIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuICAgIHByaXZhdGUgbWVkaWFSZWNvcmRlcjogYW55O1xuICAgIHByaXZhdGUgY2h1bmtzOiBhbnlbXSA9IFtdO1xuICAgIHByaXZhdGUgYmxvYjogQmxvYjtcbiAgICBwcml2YXRlIGNvdW50ID0gMDtcbiAgICBwcml2YXRlIGlkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXdTcmM6IHN0cmluZztcbiAgICBwcml2YXRlIGh0bWxQYXJlbnRFbGVtZW50SWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlldzogSFRNTFZpZGVvRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gKCEhdGhpcy5zdHJlYW0uY29ubmVjdGlvbikgPyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA6ICdkZWZhdWx0LWNvbm5lY3Rpb24nO1xuICAgICAgICB0aGlzLmlkID0gdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXycgKyB0aGlzLmNvbm5lY3Rpb25JZCArICdfbG9jYWxyZWNvcmQnO1xuICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU3RhcnRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQURZYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdGFydGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZWNvcmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdHJ5IHtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBicm93c2VyLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlY29yZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQURZXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuY2xlYW4oKVxcJyBvciBpbml0IGEgbmV3IExvY2FsUmVjb3JkZXIgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIlN0YXJ0aW5nIGxvY2FsIHJlY29yZGluZyBvZiBzdHJlYW0gJ1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyBcIicgb2YgY29ubmVjdGlvbiAnXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArIFwiJ1wiKTtcblxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBsZXQgb3B0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDknKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz12cDknIH07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQoJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JyB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz12cDgnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGU6ICd2aWRlby93ZWJtO2NvZGVjcz12cDgnIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1VzaW5nIG1pbWVUeXBlICcgKyBvcHRpb25zLm1pbWVUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIodGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdpc1R5cGVTdXBwb3J0ZWQgaXMgbm90IHN1cHBvcnRlZCwgdXNpbmcgZGVmYXVsdCBjb2RlY3MgZm9yIGJyb3dzZXInKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIodGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXJ0KDEwKTtcblxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmRhdGFhdmFpbGFibGUgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY2h1bmtzLnB1c2goZS5kYXRhKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmVycm9yID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdNZWRpYVJlY29yZGVyIGVycm9yOiAnLCBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0YXJ0ID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0YXJ0ZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnBhdXNlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHBhdXNlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25yZXN1bWUgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgcmVzdW1lZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub253YXJuaW5nID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciB3YXJuaW5nOiAnICsgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgIHJlc29sdmUoKTtcblxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEVuZHMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYCBvciBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgRklOSVNIRURgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgc3VjY2Vzc2Z1bGx5IHN0b3BwZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHN0b3AoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIG9yIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0b3AoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUGF1c2VzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2AuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFBBVVNFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyB3YXMgc3VjY2Vzc2Z1bGx5IHBhdXNlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcGF1c2UoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC5wYXVzZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgb3IgXFwnTG9jYWxSZWNvcmRlci5yZXN1bWUoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5wYXVzZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXN1bWVzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFBBVVNFRGAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyB3YXMgc3VjY2Vzc2Z1bGx5IHJlc3VtZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHJlc3VtZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlc3VtZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnBhdXNlKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucmVzdW1lKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHJldmlld3MgdGhlIHJlY29yZGluZywgYXBwZW5kaW5nIGEgbmV3IEhUTUxWaWRlb0VsZW1lbnQgdG8gZWxlbWVudCB3aXRoIGlkIGBwYXJlbnRJZGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBwcmV2aWV3KHBhcmVudEVsZW1lbnQpOiBIVE1MVmlkZW9FbGVtZW50IHtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnByZXZpZXcoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuaWQgPSB0aGlzLmlkO1xuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5hdXRvcGxheSA9IHRydWU7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBwYXJlbnRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhpcy5odG1sUGFyZW50RWxlbWVudElkID0gcGFyZW50RWxlbWVudDtcblxuICAgICAgICAgICAgY29uc3QgcGFyZW50RWxlbWVudERvbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBhcmVudEVsZW1lbnQpO1xuICAgICAgICAgICAgaWYgKHBhcmVudEVsZW1lbnREb20pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnREb20uYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5odG1sUGFyZW50RWxlbWVudElkID0gcGFyZW50RWxlbWVudC5pZDtcbiAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5zcmMgPSB0aGlzLnZpZGVvUHJldmlld1NyYztcblxuICAgICAgICByZXR1cm4gdGhpcy52aWRlb1ByZXZpZXc7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBHcmFjZWZ1bGx5IHN0b3BzIGFuZCBjbGVhbnMgdGhlIGN1cnJlbnQgcmVjb3JkaW5nIChXQVJOSU5HOiBpdCBpcyBjb21wbGV0ZWx5IGRpc21pc3NlZCkuIFNldHMgW1tzdGF0ZV1dIHRvIGBSRUFEWWAgc28gdGhlIHJlY29yZGluZyBjYW4gc3RhcnQgYWdhaW5cbiAgICAgKi9cbiAgICBjbGVhbigpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZiA9ICgpID0+IHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmJsb2I7XG4gICAgICAgICAgICB0aGlzLmNodW5rcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5jb3VudCA9IDA7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tZWRpYVJlY29yZGVyO1xuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkcgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgdGhpcy5zdG9wKCkudGhlbigoKSA9PiBmKCkpLmNhdGNoKCgpID0+IGYoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIERvd25sb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gdGhyb3VnaCB0aGUgYnJvd3Nlci4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIGRvd25sb2FkKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLmRvd25sb2FkKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgYTogSFRNTEFuY2hvckVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICAgICAgICBhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xuXG4gICAgICAgICAgICBjb25zdCB1cmwgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgYS5ocmVmID0gdXJsO1xuICAgICAgICAgICAgYS5kb3dubG9hZCA9IHRoaXMuaWQgKyAnLndlYm0nO1xuICAgICAgICAgICAgYS5jbGljaygpO1xuICAgICAgICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcblxuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHJhdyBCbG9iIGZpbGUuIE1ldGhvZHMgcHJldmlldywgZG93bmxvYWQsIHVwbG9hZEFzQmluYXJ5IGFuZCB1cGxvYWRBc011bHRpcGFydGZpbGUgdXNlIHRoaXMgc2FtZSBmaWxlIHRvIHBlcmZvcm0gdGhlaXIgc3BlY2lmaWMgYWN0aW9ucy4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIGdldEJsb2IoKTogQmxvYiB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignQ2FsbCBcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgYmVmb3JlIGdldHRpbmcgQmxvYiBmaWxlJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmxvYjtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBsb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gYXMgYSBiaW5hcnkgZmlsZSBwZXJmb3JtaW5nIGFuIEhUVFAvUE9TVCBvcGVyYXRpb24gdG8gVVJMIGBlbmRwb2ludGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGAuIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBjYW4gYmUgcGFzc2VkIGFzIHNlY29uZCBwYXJhbWV0ZXIuIEZvciBleGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHZhciBoZWFkZXJzID0ge1xuICAgICAqICBcIkNvb2tpZVwiOiBcIiRWZXJzaW9uPTE7IFNraW49bmV3O1wiLFxuICAgICAqICBcIkF1dGhvcml6YXRpb25cIjpcIkJhc2ljIFFXeGhaR3BianB1SUhObGN0WlE9PVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB3aXRoIHRoZSBgaHR0cC5yZXNwb25zZVRleHRgIGZyb20gc2VydmVyIGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggdGhlIGZhaWxlZCBgaHR0cC5zdGF0dXNgIGlmIG5vdFxuICAgICAqL1xuICAgIHVwbG9hZEFzQmluYXJ5KGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNCaW5hcnkoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoaHR0cC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBodHRwLnNlbmQodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIG11bHRpcGFydCBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90OlxuICAgICAqL1xuICAgIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzZW5kYWJsZSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgICAgIHNlbmRhYmxlLmFwcGVuZCgnZmlsZScsIHRoaXMuYmxvYiwgdGhpcy5pZCArICcud2VibScpO1xuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoaHR0cC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGh0dHAuc2VuZChzZW5kYWJsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIG9uU3RvcERlZmF1bHQoKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHN0b3BwZWQgIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcblxuICAgICAgICB0aGlzLmJsb2IgPSBuZXcgQmxvYih0aGlzLmNodW5rcywgeyB0eXBlOiAndmlkZW8vd2VibScgfSk7XG4gICAgICAgIHRoaXMuY2h1bmtzID0gW107XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXdTcmMgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTCh0aGlzLmJsb2IpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQ7XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IExvY2FsUmVjb3JkZXIgfSBmcm9tICcuL0xvY2FsUmVjb3JkZXInO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBEZXZpY2UgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0RldmljZSc7XG5pbXBvcnQgeyBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IHsgUHVibGlzaGVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvUHVibGlzaGVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmdBdXRvIGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8nO1xuaW1wb3J0ICogYXMgc2NyZWVuU2hhcmluZyBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZyc7XG5cbmltcG9ydCBScGNCdWlsZGVyID0gcmVxdWlyZSgnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbi8qKlxuICogRW50cnlwb2ludCBvZiBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKiBVc2UgaXQgdG8gaW5pdGlhbGl6ZSBvYmplY3RzIG9mIHR5cGUgW1tTZXNzaW9uXV0sIFtbUHVibGlzaGVyXV0gYW5kIFtbTG9jYWxSZWNvcmRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdSB7XG5cbiAgcHJpdmF0ZSBqc29uUnBjQ2xpZW50OiBhbnk7XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlc3Npb246IFNlc3Npb247XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICB3c1VyaTogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VjcmV0ID0gJyc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByZWNvcmRlciA9IGZhbHNlO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaWNlU2VydmVyczogUlRDSWNlU2VydmVyW107XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICByb2xlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBhZHZhbmNlZENvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uID0ge307XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgY29uc29sZS5pbmZvKFwiJ09wZW5WaWR1JyBpbml0aWFsaXplZFwiKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgbmV3IHNlc3Npb25cbiAgICovXG4gIGluaXRTZXNzaW9uKCk6IFNlc3Npb24ge1xuICAgIHRoaXMuc2Vzc2lvbiA9IG5ldyBTZXNzaW9uKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnNlc3Npb247XG4gIH1cblxuXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcblxuICAvKipcbiAgICogUmV0dXJucyBhIG5ldyBwdWJsaXNoZXJcbiAgICpcbiAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzRGlhbG9nT3BlbmVkYCBldmVudCwgb25seSBpZiB0aGUgcG9wLXVwIHNob3duIGJ5IHRoZSBicm93c2VyIHRvIHJlcXVlc3QgcGVybWlzc2lvbnMgZm9yIHRoZSBjYW1lcmEgaXMgb3BlbmVkLiBZb3UgY2FuIHVzZSB0aGlzIGV2ZW50IHRvIGFsZXJ0IHRoZSB1c2VyIGFib3V0IGdyYW50aW5nIHBlcm1pc3Npb25zXG4gICAqIGZvciB5b3VyIHdlYnNpdGUuIEFuIGBhY2Nlc3NEaWFsb2dDbG9zZWRgIGV2ZW50IHdpbGwgYWxzbyBiZSBkaXNwYXRjaGVkIGFmdGVyIHVzZXIgY2xpY2tzIG9uIFwiQWxsb3dcIiBvciBcIkJsb2NrXCIgaW4gdGhlIHBvcC11cC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGBhY2Nlc3NEZW5pZWRgIGV2ZW50IG9uY2UgaXQgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSBhIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2AgZXZlbnQgb25jZSB0aGUgbG9jYWwgc3RyZWFtcyBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgIEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSkuIElmICpudWxsKiBvciAqdW5kZWZpbmVkKiBubyBkZWZhdWx0IHZpZGVvIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBQdWJsaXNoZXIuXG4gICAqIFlvdSBjYW4gYWx3YXlzIGNhbGwgbWV0aG9kIFtbUHVibGlzaGVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24pXG4gICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBpbml0UHVibGlzaGVyYCBzdWNjZWVkcywgYW5kIGlzIGRlZmluZWQgaWYgaXQgZmFpbHMuXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICBgY29tcGxldGlvbkhhbmRsZXJgIGZ1bmN0aW9uIGlzIGNhbGxlZCBiZWZvcmUgdGhlIFB1Ymxpc2hlciBkaXNwYXRjaGVzIGFuIGBhY2Nlc3NBbGxvd2VkYCBvciBhbiBgYWNjZXNzRGVuaWVkYCBldmVudFxuICAgKi9cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcGFyYW0yPywgcGFyYW0zPyk6IFB1Ymxpc2hlciB7XG5cbiAgICBsZXQgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcztcblxuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiAhPT0gJ2Z1bmN0aW9uJykpIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzKScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0gKDxQdWJsaXNoZXJQcm9wZXJ0aWVzPnBhcmFtMik7XG5cbiAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGF1ZGlvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgOiB1bmRlZmluZWQsXG4gICAgICAgIGZyYW1lUmF0ZTogdGhpcy5pc01lZGlhU3RyZWFtVHJhY2socHJvcGVydGllcy52aWRlb1NvdXJjZSkgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5mcmFtZVJhdGUgOiB1bmRlZmluZWQpLFxuICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSAhPT0gJ3VuZGVmaW5lZCcpID8gKCh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlID09PSAnc3RyaW5nJykgPyBWaWRlb0luc2VydE1vZGVbcHJvcGVydGllcy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6ICh0eXBlb2YgcHJvcGVydGllcy5taXJyb3IgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMubWlycm9yIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaEF1ZGlvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaEF1ZGlvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hWaWRlbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiB0aGlzLmlzTWVkaWFTdHJlYW1UcmFjayhwcm9wZXJ0aWVzLnZpZGVvU291cmNlKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMucmVzb2x1dGlvbiAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5yZXNvbHV0aW9uIDogJzY0MHg0ODAnKSxcbiAgICAgICAgdmlkZW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy52aWRlb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy52aWRlb1NvdXJjZSA6IHVuZGVmaW5lZFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogdHJ1ZSxcbiAgICAgICAgcHVibGlzaEF1ZGlvOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246ICc2NDB4NDgwJ1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBwdWJsaXNoZXI6IFB1Ymxpc2hlciA9IG5ldyBQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgdGhpcyk7XG5cbiAgICBsZXQgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTI7XG4gICAgfSBlbHNlIGlmICghIXBhcmFtMykge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTM7XG4gICAgfVxuXG4gICAgcHVibGlzaGVyLmluaXRpYWxpemUoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzQWxsb3dlZCcsIFtdKTtcbiAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnLCBbXSk7XG4gICAgICB9KTtcblxuICAgIHJldHVybiBwdWJsaXNoZXI7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBQcm9taXNpZmllZCB2ZXJzaW9uIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqXG4gICAqID4gV0FSTklORzogZXZlbnRzIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGFuZCBgYWNjZXNzRGlhbG9nQ2xvc2VkYCB3aWxsIG5vdCBiZSBkaXNwYXRjaGVkIGlmIHVzaW5nIHRoaXMgbWV0aG9kIGluc3RlYWQgb2YgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICovXG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFByb21pc2U8UHVibGlzaGVyPjtcbiAgaW5pdFB1Ymxpc2hlckFzeW5jKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+O1xuXG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQcm9taXNlPFB1Ymxpc2hlcj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxQdWJsaXNoZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgbGV0IHB1Ymxpc2hlcjogUHVibGlzaGVyO1xuXG4gICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUocHVibGlzaGVyKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICBwdWJsaXNoZXIgPSB0aGlzLmluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgbG9jYWwgcmVjb3JkZXIgZm9yIHJlY29yZGluZyBzdHJlYW1zIHN0cmFpZ2h0IGF3YXkgZnJvbSB0aGUgYnJvd3NlclxuICAgKiBAcGFyYW0gc3RyZWFtICBTdHJlYW0gdG8gcmVjb3JkXG4gICAqL1xuICBpbml0TG9jYWxSZWNvcmRlcihzdHJlYW06IFN0cmVhbSk6IExvY2FsUmVjb3JkZXIge1xuICAgIHJldHVybiBuZXcgTG9jYWxSZWNvcmRlcihzdHJlYW0pO1xuICB9XG5cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1XG4gICAqIEByZXR1cm5zIDEgaWYgdGhlIGJyb3dzZXIgc3VwcG9ydHMgT3BlblZpZHUsIDAgb3RoZXJ3aXNlXG4gICAqL1xuICBjaGVja1N5c3RlbVJlcXVpcmVtZW50cygpOiBudW1iZXIge1xuICAgIGNvbnN0IGJyb3dzZXIgPSBwbGF0Zm9ybS5uYW1lO1xuICAgIGNvbnN0IHZlcnNpb24gPSBwbGF0Zm9ybS52ZXJzaW9uO1xuXG4gICAgaWYgKChicm93c2VyICE9PSAnQ2hyb21lJykgJiYgKGJyb3dzZXIgIT09ICdDaHJvbWUgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnRmlyZWZveCcpICYmIChicm93c2VyICE9PSAnRmlyZWZveCBNb2JpbGUnKSAmJiAoYnJvd3NlciAhPT0gJ0ZpcmVmb3ggZm9yIGlPUycpICYmXG4gICAgICAoYnJvd3NlciAhPT0gJ09wZXJhJykgJiYgKGJyb3dzZXIgIT09ICdPcGVyYSBNb2JpbGUnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdTYWZhcmknKSkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIENvbGxlY3RzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtZWRpYSBpbnB1dCBkZXZpY2VzIGF2YWlsYWJsZSBvbiB0aGUgc3lzdGVtLiBZb3UgY2FuIHBhc3MgcHJvcGVydHkgYGRldmljZUlkYCBvZiBhIFtbRGV2aWNlXV0gb2JqZWN0IGFzIHZhbHVlIG9mIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgKi9cbiAgZ2V0RGV2aWNlcygpOiBQcm9taXNlPERldmljZVtdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPERldmljZVtdPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKS50aGVuKChkZXZpY2VJbmZvcykgPT4ge1xuICAgICAgICBjb25zdCBkZXZpY2VzOiBEZXZpY2VbXSA9IFtdO1xuICAgICAgICBkZXZpY2VJbmZvcy5mb3JFYWNoKGRldmljZUluZm8gPT4ge1xuICAgICAgICAgIGlmIChkZXZpY2VJbmZvLmtpbmQgPT09ICdhdWRpb2lucHV0JyB8fCBkZXZpY2VJbmZvLmtpbmQgPT09ICd2aWRlb2lucHV0Jykge1xuICAgICAgICAgICAgZGV2aWNlcy5wdXNoKHtcbiAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICBkZXZpY2VJZDogZGV2aWNlSW5mby5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgbGFiZWw6IGRldmljZUluZm8ubGFiZWxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlc29sdmUoZGV2aWNlcyk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZ2V0dGluZyBkZXZpY2VzJywgZXJyb3IpO1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBHZXQgYSBNZWRpYVN0cmVhbSBvYmplY3QgdGhhdCB5b3UgY2FuIGN1c3RvbWl6ZSBiZWZvcmUgY2FsbGluZyBbW2luaXRQdWJsaXNoZXJdXSAocGFzcyBfTWVkaWFTdHJlYW1UcmFja18gcHJvcGVydHkgb2YgdGhlIF9NZWRpYVN0cmVhbV8gdmFsdWUgcmVzb2x2ZWQgYnkgdGhlIFByb21pc2UgYXMgYGF1ZGlvU291cmNlYCBvciBgdmlkZW9Tb3VyY2VgIHByb3BlcnRpZXMgaW4gW1tpbml0UHVibGlzaGVyXV0pXG4gICAqXG4gICAqIFBhcmFtZXRlciBgb3B0aW9uc2AgaXMgdGhlIHNhbWUgYXMgaW4gW1tpbml0UHVibGlzaGVyXV0gc2Vjb25kIHBhcmFtZXRlciAob2YgdHlwZSBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSksIGJ1dCBvbmx5IHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyB3aWxsIGJlIGFwcGxpZWQ6IGBhdWRpb1NvdXJjZWAsIGB2aWRlb1NvdXJjZWAsIGBmcmFtZVJhdGVgLCBgcmVzb2x1dGlvbmBcbiAgICpcbiAgICogVG8gY3VzdG9taXplIHRoZSBQdWJsaXNoZXIncyB2aWRlbywgdGhlIEFQSSBmb3IgSFRNTENhbnZhc0VsZW1lbnQgaXMgdmVyeSB1c2VmdWwuIEZvciBleGFtcGxlLCB0byBnZXQgYSBibGFjay1hbmQtd2hpdGUgdmlkZW8gYXQgMTAgZnBzIGFuZCBIRCByZXNvbHV0aW9uIHdpdGggbm8gc291bmQ6XG4gICAqIGBgYFxuICAgKiB2YXIgT1YgPSBuZXcgT3BlblZpZHUoKTtcbiAgICogdmFyIEZSQU1FX1JBVEUgPSAxMDtcbiAgICpcbiAgICogT1YuZ2V0VXNlck1lZGlhKHtcbiAgICogICAgYXVkaW9Tb3VyY2U6IGZhbHNlO1xuICAgKiAgICB2aWRlb1NvdXJjZTogdW5kZWZpbmVkLFxuICAgKiAgICByZXNvbHV0aW9uOiAnMTI4MHg3MjAnLFxuICAgKiAgICBmcmFtZVJhdGU6IEZSQU1FX1JBVEVcbiAgICogfSlcbiAgICogLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgKlxuICAgKiAgICB2YXIgdmlkZW9UcmFjayA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAqICAgIHZpZGVvLnNyY09iamVjdCA9IG5ldyBNZWRpYVN0cmVhbShbdmlkZW9UcmFja10pO1xuICAgKlxuICAgKiAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAqICAgIHZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICogICAgY3R4LmZpbHRlciA9ICdncmF5c2NhbGUoMTAwJSknO1xuICAgKlxuICAgKiAgICB2aWRlby5hZGRFdmVudExpc3RlbmVyKCdwbGF5JywgKCkgPT4ge1xuICAgKiAgICAgIHZhciBsb29wID0gKCkgPT4ge1xuICAgKiAgICAgICAgaWYgKCF2aWRlby5wYXVzZWQgJiYgIXZpZGVvLmVuZGVkKSB7XG4gICAqICAgICAgICAgIGN0eC5kcmF3SW1hZ2UodmlkZW8sIDAsIDAsIDMwMCwgMTcwKTtcbiAgICogICAgICAgICAgc2V0VGltZW91dChsb29wLCAxMDAwLyBGUkFNRV9SQVRFKTsgLy8gRHJhd2luZyBhdCAxMCBmcHNcbiAgICogICAgICAgIH1cbiAgICogICAgICB9O1xuICAgKiAgICAgIGxvb3AoKTtcbiAgICogICAgfSk7XG4gICAqICAgIHZpZGVvLnBsYXkoKTtcbiAgICpcbiAgICogICAgdmFyIGdyYXlWaWRlb1RyYWNrID0gY2FudmFzLmNhcHR1cmVTdHJlYW0oRlJBTUVfUkFURSkuZ2V0VmlkZW9UcmFja3MoKVswXTtcbiAgICogICAgdmFyIHB1Ymxpc2hlciA9IHRoaXMuT1YuaW5pdFB1Ymxpc2hlcihcbiAgICogICAgICBteUh0bWxUYXJnZXQsXG4gICAqICAgICAge1xuICAgKiAgICAgICAgYXVkaW9Tb3VyY2U6IGZhbHNlLFxuICAgKiAgICAgICAgdmlkZW9Tb3VyY2U6IGdyYXlWaWRlb1RyYWNrXG4gICAqICAgICAgfSk7XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGdldFVzZXJNZWRpYShvcHRpb25zOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxNZWRpYVN0cmVhbT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5nZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMob3B0aW9ucylcbiAgICAgICAgLnRoZW4oY29uc3RyYWludHMgPT4ge1xuICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKVxuICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICBsZXQgZXJyb3JOYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKCEob3B0aW9ucy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbicpKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoZXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG5cbiAgLyogdHNsaW50OmRpc2FibGU6bm8tZW1wdHkgKi9cbiAgLyoqXG4gICAqIERpc2FibGUgYWxsIGxvZ2dpbmcgZXhjZXB0IGVycm9yIGxldmVsXG4gICAqL1xuICBlbmFibGVQcm9kTW9kZSgpOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmRlYnVnID0gKCkgPT4geyB9O1xuICAgIGNvbnNvbGUuaW5mbyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLndhcm4gPSAoKSA9PiB7IH07XG4gIH1cbiAgLyogdHNsaW50OmVuYWJsZTpuby1lbXB0eSAqL1xuXG5cbiAgLyoqXG4gICAqIFNldCBPcGVuVmlkdSBhZHZhbmNlZCBjb25maWd1cmF0aW9uIG9wdGlvbnMuIEN1cnJlbnRseSBgY29uZmlndXJhdGlvbmAgaXMgYW4gb2JqZWN0IHdpdGggdGhlIGZvbGxvd2luZyBvcHRpb25hbCBwcm9wZXJ0aWVzIChzZWUgW1tPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbl1dIGZvciBtb3JlIGRldGFpbHMpOlxuICAgKiAtIGBpY2VTZXJ2ZXJzYDogc2V0IGN1c3RvbSBTVFVOL1RVUk4gc2VydmVycyB0byBiZSB1c2VkIGJ5IE9wZW5WaWR1IEJyb3dzZXJcbiAgICogLSBgc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb25gOiB1cmwgdG8gYSBjdXN0b20gc2NyZWVuIHNoYXJlIGV4dGVuc2lvbiBmb3IgQ2hyb21lIHRvIGJlIHVzZWQgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBvbmUsIGJhc2VkIG9uIG91cnMgW2h0dHBzOi8vZ2l0aHViLmNvbS9PcGVuVmlkdS9vcGVudmlkdS1zY3JlZW4tc2hhcmluZy1jaHJvbWUtZXh0ZW5zaW9uXShodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbilcbiAgICogLSBgcHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zYDogY3VzdG9tIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBbW1B1Ymxpc2hlclNwZWFraW5nRXZlbnRdXSBmZWF0dXJlXG4gICAqL1xuICBzZXRBZHZhbmNlZENvbmZpZ3VyYXRpb24oY29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24pOiB2b2lkIHtcbiAgICB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb247XG4gIH1cblxuXG4gIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyhwdWJsaXNoZXJQcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPE1lZGlhU3RyZWFtQ29uc3RyYWludHM+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGxldCBhdWRpbywgdmlkZW87XG5cbiAgICAgIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBudWxsIHx8IHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgPT09IGZhbHNlKSB7XG4gICAgICAgIGF1ZGlvID0gZmFsc2U7XG4gICAgICB9IGVsc2UgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBhdWRpbyA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhdWRpbyA9IHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBudWxsIHx8IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09IGZhbHNlKSB7XG4gICAgICAgIHZpZGVvID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2aWRlbyA9IHtcbiAgICAgICAgICBoZWlnaHQ6IHtcbiAgICAgICAgICAgIGlkZWFsOiA0ODBcbiAgICAgICAgICB9LFxuICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICBpZGVhbDogNjQwXG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtZWRpYUNvbnN0cmFpbnRzOiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbyxcbiAgICAgICAgdmlkZW9cbiAgICAgIH07XG5cbiAgICAgIGlmICh0eXBlb2YgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgbWVkaWFDb25zdHJhaW50cy5hdWRpbyA9IHsgZGV2aWNlSWQ6IHsgZXhhY3Q6IG1lZGlhQ29uc3RyYWludHMuYXVkaW8gfSB9O1xuICAgICAgfVxuXG4gICAgICBpZiAobWVkaWFDb25zdHJhaW50cy52aWRlbykge1xuXG4gICAgICAgIGlmICghIXB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbikge1xuICAgICAgICAgIGNvbnN0IHdpZHRoQW5kSGVpZ2h0ID0gcHVibGlzaGVyUHJvcGVydGllcy5yZXNvbHV0aW9uLnRvTG93ZXJDYXNlKCkuc3BsaXQoJ3gnKTtcbiAgICAgICAgICBjb25zdCB3aWR0aCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFswXSk7XG4gICAgICAgICAgY29uc3QgaGVpZ2h0ID0gTnVtYmVyKHdpZHRoQW5kSGVpZ2h0WzFdKTtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLndpZHRoLmlkZWFsID0gd2lkdGg7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS5oZWlnaHQuaWRlYWwgPSBoZWlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZSkge1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuZnJhbWVSYXRlID0geyBpZGVhbDogcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghIXB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgJiYgdHlwZW9mIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzdHJpbmcnKSB7XG5cbiAgICAgICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbicpIHtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUgIT09ICdDaHJvbWUnICYmIHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVELCAnWW91IGNhbiBvbmx5IHNjcmVlbiBzaGFyZSBpbiBkZXNrdG9wIENocm9tZSBhbmQgRmlyZWZveC4gRGV0ZWN0ZWQgYnJvd3NlcjogJyArIHBsYXRmb3JtLm5hbWUpO1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gJiYgIShwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSkge1xuXG4gICAgICAgICAgICAgICAgLy8gQ3VzdG9tIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lXG5cbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldFNjcmVlbkNvbnN0cmFpbnRzKChlcnJvciwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yIHx8ICEhc2NyZWVuQ29uc3RyYWludHMubWFuZGF0b3J5ICYmIHNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZSA9PT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnIHx8IGVycm9yID09PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25JZCA9IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIS5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbklkLCAoc3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICg8c3RyaW5nPnRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHM7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAvLyBEZWZhdWx0IHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lXG5cbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nQXV0by5nZXRTY3JlZW5JZCgoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25VcmwgPSAhIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uID8gdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gOlxuICAgICAgICAgICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2hyb21lLmdvb2dsZS5jb20vd2Vic3RvcmUvZGV0YWlsL29wZW52aWR1LXNjcmVlbnNoYXJpbmcvbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCBleHRlbnNpb25VcmwpO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdpbnN0YWxsZWQtZGlzYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9ICdzY3JlZW4nO1xuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1zdHJpbmctbGl0ZXJhbFxuICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlb1snZGV2aWNlSWQnXSA9IHsgZXhhY3Q6IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgfTtcbiAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc3RhcnRXcyhvbkNvbm5lY3RTdWNjZXM6IChlcnJvcjogRXJyb3IpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSB7XG4gICAgICBoZWFydGJlYXQ6IDUwMDAsXG4gICAgICBzZW5kQ2xvc2VNZXNzYWdlOiBmYWxzZSxcbiAgICAgIHdzOiB7XG4gICAgICAgIHVyaTogdGhpcy53c1VyaSxcbiAgICAgICAgdXNlU29ja0pTOiBmYWxzZSxcbiAgICAgICAgb25jb25uZWN0ZWQ6IG9uQ29ubmVjdFN1Y2NlcyxcbiAgICAgICAgb25kaXNjb25uZWN0OiB0aGlzLmRpc2Nvbm5lY3RDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBvbnJlY29ubmVjdGluZzogdGhpcy5yZWNvbm5lY3RpbmdDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBvbnJlY29ubmVjdGVkOiB0aGlzLnJlY29ubmVjdGVkQ2FsbGJhY2suYmluZCh0aGlzKVxuICAgICAgfSxcbiAgICAgIHJwYzoge1xuICAgICAgICByZXF1ZXN0VGltZW91dDogMTAwMDAsXG4gICAgICAgIHBhcnRpY2lwYW50Sm9pbmVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEpvaW5lZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50UHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50VW5wdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50VW5wdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudExlZnQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50TGVmdC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50RXZpY3RlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRFdmljdGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RhcnRlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RhcnRlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0b3BwZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0b3BwZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzZW5kTWVzc2FnZTogdGhpcy5zZXNzaW9uLm9uTmV3TWVzc2FnZS5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kUmVxdWVzdChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBhbnksIGNhbGxiYWNrPyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgcGFyYW1zID0ge307XG4gICAgfVxuICAgIGNvbnNvbGUuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNNZWRpYVN0cmVhbVRyYWNrKG1lZGlhU291cmNlOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBpcyA9ICghIW1lZGlhU291cmNlICYmXG4gICAgICBtZWRpYVNvdXJjZS5lbmFibGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmVuYWJsZWQgPT09ICdib29sZWFuJyAmJlxuICAgICAgbWVkaWFTb3VyY2UuaWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UuaWQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5raW5kICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLmtpbmQgPT09ICdzdHJpbmcnICYmXG4gICAgICBtZWRpYVNvdXJjZS5sYWJlbCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBtZWRpYVNvdXJjZS5sYWJlbCA9PT0gJ3N0cmluZycgJiZcbiAgICAgIG1lZGlhU291cmNlLm11dGVkICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lZGlhU291cmNlLm11dGVkID09PSAnYm9vbGVhbicgJiZcbiAgICAgIG1lZGlhU291cmNlLnJlYWR5U3RhdGUgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgbWVkaWFTb3VyY2UucmVhZHlTdGF0ZSA9PT0gJ3N0cmluZycpO1xuICAgIHJldHVybiBpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRXc1VyaSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLndzVXJpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFNlY3JldCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlY3JldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRSZWNvcmRlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRlcjtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgY29ubmVjdGlvbiBsb3N0Jyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlY29ubmVjdGVkQ2FsbGJhY2soKTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdXZWJzb2NrZXQgcmVjb25uZWN0ZWQnKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNSb29tQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLnNlc3Npb24gIT09IHVuZGVmaW5lZCAmJiB0aGlzLnNlc3Npb24gaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5cbi8qKlxuICogUGFja3MgbG9jYWwgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGNhbiBwdWJsaXNoIGl0IHRvIGEgc2Vzc2lvbi4gSW5pdGlhbGl6ZWQgd2l0aCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAqL1xuZXhwb3J0IGNsYXNzIFB1Ymxpc2hlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgUHVibGlzaGVyIGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3RcbiAgICAgKi9cbiAgICBhY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHlvdSBoYXZlIGNhbGxlZCBbW1B1Ymxpc2hlci5zdWJzY3JpYmVUb1JlbW90ZV1dIHdpdGggdmFsdWUgYHRydWVgIG9yIGBmYWxzZWAgKCpmYWxzZSogYnkgZGVmYXVsdClcbiAgICAgKi9cbiAgICBpc1N1YnNjcmliZWRUb1JlbW90ZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIHRvIHdoaWNoIHRoZSBQdWJsaXNoZXIgYmVsb25nc1xuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247IC8vIEluaXRpYWxpemVkIGJ5IFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpXG5cbiAgICBwcml2YXRlIGFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcztcbiAgICBwcml2YXRlIHBlcm1pc3Npb25EaWFsb2dUaW1lb3V0OiBOb2RlSlMuVGltZXI7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgcHJpdmF0ZSBvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIobmV3IFN0cmVhbSgoISFvcGVudmlkdS5zZXNzaW9uKSA/IG9wZW52aWR1LnNlc3Npb24gOiBuZXcgU2Vzc2lvbihvcGVudmlkdSksIHsgcHVibGlzaGVyUHJvcGVydGllczogcHJvcGVydGllcywgbWVkaWFDb25zdHJhaW50czoge30gfSksIHRhcmdFbCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uZWUub24oJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQtYnktZGlzY29ubmVjdCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvdXIoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgYXVkaW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIGF1ZGlvIHN0cmVhbScpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gcHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVucHVibGlzaCBpdFxuICAgICAqL1xuICAgIHB1Ymxpc2hWaWRlbyh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArICh2YWx1ZSA/ICdwdWJsaXNoZWQnIDogJ3VucHVibGlzaGVkJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIENhbGwgdGhpcyBtZXRob2QgYmVmb3JlIFtbU2Vzc2lvbi5wdWJsaXNoXV0gdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBQdWJsaXNoZXIge1xuICAgICAgICBzdXBlci5vbmNlKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbUNyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHRoaXMuc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUub25jZSgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgZXJyb3JDYWxsYmFjayA9IChvcGVuVmlkdUVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJlamVjdChvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5pc01lZGlhU3RyZWFtVHJhY2sodGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlKSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5yZW1vdmVUcmFjayhtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soKDxNZWRpYVN0cmVhbVRyYWNrPnRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmlzTWVkaWFTdHJlYW1UcmFjayh0aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjaygoPE1lZGlhU3RyZWFtVHJhY2s+dGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQXBwbHkgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW8gYW5kIFB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvXG4gICAgICAgICAgICAgICAgaWYgKCEhbWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdLmVuYWJsZWQgPSAhIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCEhbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSAhIXRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBzdWJzY3JpYmVkIHRvIG91ciByZW1vdGUgd2UgZG9uJ3Qgc3RpbGwgc2V0IHRoZSBNZWRpYVN0cmVhbSBvYmplY3QgaW4gdGhlIHZpZGVvIGVsZW1lbnRzIHRvXG4gICAgICAgICAgICAgICAgICAgIC8vIGF2b2lkIGVhcmx5ICdzdHJlYW1QbGF5aW5nJyBldmVudFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS51cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcblxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuZmlyc3RWaWRlb0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVWaWRlb0VsZW1lbnQodGhpcy5maXJzdFZpZGVvRWxlbWVudC50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnRoaXMucHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyh0aGlzLnByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgLnRoZW4oY29uc3RyYWludHMgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG91dGJvdW5kU3RyZWFtT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IGNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyUHJvcGVydGllczogdGhpcy5wcm9wZXJ0aWVzXG4gICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHNBdXg6IE1lZGlhU3RyZWFtQ29uc3RyYWludHMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGltZUZvckRpYWxvZ0V2ZW50ID0gMTI1MDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kVmlkZW8oKSB8fCB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZpbmVkQXVkaW9Db25zdHJhaW50ID0gKChjb25zdHJhaW50cy5hdWRpbyA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiBjb25zdHJhaW50cy5hdWRpbyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gZmFsc2UgOiBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBjb25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIodGltZUZvckRpYWxvZ0V2ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHNBdXgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgJiYgdGhpcy5zdHJlYW0uaXNTZW5kQXVkaW8oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiBnZXR0aW5nIGRlc2t0b3AgYXMgdXNlciBtZWRpYSBhdWRpbyBjb25zdHJhaW50IG11c3QgYmUgZmFsc2UuIE5vdyB3ZSBjYW4gYXNrIGZvciBpdCBpZiByZXF1aXJlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXguYXVkaW8gPSBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihhdWRpb09ubHlTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soYXVkaW9Pbmx5U3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWUsIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnb3ZlcmNvbnN0cmFpbmVkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlBVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWUsIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogY29uc3RyYWludHMudmlkZW9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEIDogT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ1wiICsgKDxDb25zdHJhaW5ET01TdHJpbmdQYXJhbWV0ZXJzPig8TWVkaWFUcmFja0NvbnN0cmFpbnRzPmNvbnN0cmFpbnRzLmF1ZGlvKS5kZXZpY2VJZCEhKS5leGFjdCArIFwiJyBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IHRoZSB2YWx1ZSBwYXNzZWQgZm9yIGNvbnN0cmFpbnQgJ1wiICsgZXJyb3IuY29uc3RyYWludCArIFwiJ1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiVmlkZW8gaW5wdXQgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ1wiICsgKDxDb25zdHJhaW5ET01TdHJpbmdQYXJhbWV0ZXJzPig8TWVkaWFUcmFja0NvbnN0cmFpbnRzPmNvbnN0cmFpbnRzLnZpZGVvKS5kZXZpY2VJZCEhKS5leGFjdCArIFwiJyBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IHRoZSB2YWx1ZSBwYXNzZWQgZm9yIGNvbnN0cmFpbnQgJ1wiICsgZXJyb3IuY29uc3RyYWludCArIFwiJ1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk5PX0lOUFVUX1NPVVJDRV9TRVQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJQcm9wZXJ0aWVzICdhdWRpb1NvdXJjZScgYW5kICd2aWRlb1NvdXJjZScgY2Fubm90IGJlIHNldCB0byBmYWxzZSBvciBudWxsIGF0IHRoZSBzYW1lIHRpbWUgd2hlbiBjYWxsaW5nICdPcGVuVmlkdS5pbml0UHVibGlzaGVyJ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVTZXNzaW9uKHNlc3Npb246IFNlc3Npb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbiA9IHNlc3Npb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVtaXRFdmVudCh0eXBlOiBzdHJpbmcsIGV2ZW50QXJyYXk6IGFueVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KHR5cGUsIGV2ZW50QXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWVzdGFibGlzaFN0cmVhbVBsYXlpbmdFdmVudCgpIHtcbiAgICAgICAgaWYgKHRoaXMuZWUuZ2V0TGlzdGVuZXJzKCdzdHJlYW1QbGF5aW5nJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5hZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIHNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih3YWl0VGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMucGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEaWFsb2dPcGVuZWQnLCBbXSk7XG4gICAgICAgIH0sIHdhaXRUaW1lKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZTogbnVtYmVyLCB3YWl0VGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0KTtcbiAgICAgICAgaWYgKChEYXRlLm5vdygpIC0gc3RhcnRUaW1lKSA+IHdhaXRUaW1lKSB7XG4gICAgICAgICAgICAvLyBQZXJtaXNzaW9uIGRpYWxvZyB3YXMgc2hvd24gYW5kIG5vdyBpcyBjbG9zZWRcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdhY2Nlc3NEaWFsb2dDbG9zZWQnLCBbXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4vUHVibGlzaGVyJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU3Vic2NyaWJlciB9IGZyb20gJy4vU3Vic2NyaWJlcic7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTaWduYWxPcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TaWduYWxPcHRpb25zJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0Nvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IE9iak1hcCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL09iak1hcCc7XG5pbXBvcnQgeyBTZXNzaW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL1Nlc3Npb25PcHRpb25zJztcbmltcG9ydCB7IENvbm5lY3Rpb25FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0Nvbm5lY3Rpb25FdmVudCc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5pbXBvcnQgeyBSZWNvcmRpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1JlY29yZGluZ0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudCc7XG5pbXBvcnQgeyBTaWduYWxFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50JztcbmltcG9ydCB7IFN0cmVhbUV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLy8gVGhpcyBtYXAgaXMgb25seSB1c2VkIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gJ2pvaW5Sb29tJyByZXNwb25zZSBhbmQgJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnIG5vdGlmaWNhdGlvblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVTdHJlYW1zQ3JlYXRlZDogT2JqTWFwPGJvb2xlYW4+ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE9iak1hcDxDb25uZWN0aW9uPiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcml6ZWQgZm9ybWF0XG4gICAgICogYXMgSlNPTiBvciBYTUwgaXMgYSBnb29kIGlkZWEpLCB0aGUgb25seSByZXN0cmljdGlvbiBpcyBhIG1heGltdW0gbGVuZ3RoIG9mIDEwMDAwIGNoYXJzLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRhZGF0YSBpcyBub3QgY29uc2lkZXJlZCBzZWN1cmUsIGFzIGl0IGlzIGdlbmVyYXRlZCBpbiB0aGUgY2xpZW50IHNpZGUuIFRvIHBhc3Mgc2VjdXJpemVkIGRhdGEsIGFkZCBpdCBhcyBhIHBhcmFtZXRlciBpbiB0aGVcbiAgICAgKiB0b2tlbiBnZW5lcmF0aW9uIG9wZXJhdGlvbiAodGhyb3VnaCB0aGUgQVBJIFJFU1QsIG9wZW52aWR1LWphdmEtY2xpZW50IG9yIG9wZW52aWR1LW5vZGUtY2xpZW50KS5cbiAgICAgKlxuICAgICAqIE9ubHkgYWZ0ZXIgdGhlIHJldHVybmVkIFByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gb2JqZWN0IHdpbGwgYmUgYXZhaWxhYmxlIGFuZCBwcm9wZXJseSBkZWZpbmVkLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBmaXJzdCBkaXNwYXRjaCBvbmUgb3IgbW9yZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cyB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2Q6XG4gICAgICogLSBGaXJzdCBvbmUgZm9yIHlvdXIgb3duIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0LCBzbyB5b3UgY2FuIHJldHJpZXZlIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gcHJvcGVydHkuXG4gICAgICogLSBUaGVuIG9uZSBmb3IgZWFjaCByZW1vdGUgQ29ubmVjdGlvbiBwcmV2aW91c2x5IGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiwgaWYgYW55LiBBbnkgb3RoZXIgcmVtb3RlIHVzZXIgY29ubmVjdGluZyB0byB0aGUgU2Vzc2lvbiBhZnRlciB5b3UgaGF2ZVxuICAgICAqIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCB3aGVuIHRoZXkgZG8gc28uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgZm9yIGVhY2ggcmVtb3RlIGFjdGl2ZSBbW1B1Ymxpc2hlcl1dIHRoYXQgd2FzIGFscmVhZHkgc3RyZWFtaW5nXG4gICAgICogd2hlbiBjb25uZWN0aW5nLCBqdXN0IGFmdGVyIGRpc3BhdGNoaW5nIGFsbCByZW1vdGUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0byB3aGljaCB5b3UgbXVzdCBzdWJzY3JpYmUgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqXG4gICAgICovXG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YT86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1Rva2VuKHRva2VuKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMub3BlbnZpZHUuY2hlY2tTeXN0ZW1SZXF1aXJlbWVudHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIEVhcmx5IGNvbmZpZ3VyYXRpb24gdG8gZGVhY3RpdmF0ZSBhdXRvbWF0aWMgc3Vic2NyaXB0aW9uIHRvIHN0cmVhbXNcbiAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50SWQ6IHRva2VuLFxuICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogISFtZXRhZGF0YSA/IHRoaXMuc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGEpIDogJydcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdEF1eCh0b2tlbikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBwbGF0Zm9ybS5uYW1lICsgJyAnICsgcGxhdGZvcm0udmVyc2lvbiArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGVhdmVzIHRoZSBzZXNzaW9uLCBkZXN0cm95aW5nIGFsbCBzdHJlYW1zIGFuZCBkZWxldGluZyB0aGUgdXNlciBhcyBhIHBhcnRpY2lwYW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBlYWNoIFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgdG8gYXZvaWQgdGhpcyBiZWhhdmlvdXIgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cHBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24gKHRvIGRvIHNvIGl0IGlzIGEgbWFuZGF0b3J5IHJlcXVpcmVtZW50IHRvIGNhbGwgYFNlc3Npb24udW5wdWJsaXNoKClgXG4gICAgICogb3IvYW5kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaW4gdGhlIHByZXZpb3VzIHNlc3Npb24pLiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZGlzY29ubmVjdGVkIHBhcnRpY2lwYW50IHdhcyBwdWJsaXNoaW5nLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwcG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvdXIgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgaW4gYW55IGNhc2UuIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sZWF2ZShmYWxzZSwgJ2Rpc2Nvbm5lY3QnKTtcbiAgICB9XG5cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgYHN0cmVhbWAsIGFkZGluZyBhIG5ldyBIVE1MIHZpZGVvIGVsZW1lbnQgdG8gRE9NIHdpdGggYHN1YnNjcmliZXJQcm9wZXJ0aWVzYCBzZXR0aW5ncy4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWQgaW4gdGhlIGNhbGxiYWNrIG9mIGBzdHJlYW1DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliaW5nIHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZCA9IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAndW5zdWJzY3JpYmVGcm9tVmlkZW8nLFxuICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHVuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcykgYW5kXG4gICAgICogZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW91ciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsJywgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0uY29ubmVjdGlvbiAhPT0gdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5wdWJsaXNoaW5nIGxvY2FsIG1lZGlhICgnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyknKTtcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyBvbmUgc2lnbmFsLiBgc2lnbmFsYCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiBgYGBqc29uXG4gICAgICoge2RhdGE6c3RyaW5nLCB0bzpDb25uZWN0aW9uW10sIHR5cGU6c3RyaW5nfVxuICAgICAqIGBgYFxuICAgICAqIEFsbCB1c2VycyBzdWJzY3JpYmVkIHRvIHRoYXQgc2lnbmFsIChgc2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCAuLi4pYCBvciBgc2Vzc2lvbi5vbignc2lnbmFsJywgLi4uKWAgZm9yIGFsbCBzaWduYWxzKSBhbmQgd2hvc2UgQ29ubmVjdGlvbiBvYmplY3RzIGFyZSBpbiBgdG9gIGFycmF5IHdpbGwgcmVjZWl2ZSBpdC4gVGhlaXIgbG9jYWxcbiAgICAgKiBTZXNzaW9uIG9iamVjdHMgd2lsbCBkaXNwYXRjaCBhIGBzaWduYWxgIG9yIGBzaWduYWw6dHlwZWAgZXZlbnQuIFNlZSBbW1NpZ25hbEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgbWVzc2FnZSBzdWNjZXNzZnVsbHkgcmVhY2hlZCBvcGVudmlkdS1zZXJ2ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdC4gX1RoaXMgZG9lc24ndFxuICAgICAqIG1lYW4gdGhhdCBvcGVudmlkdS1zZXJ2ZXIgY291bGQgcmVzZW5kIHRoZSBtZXNzYWdlIHRvIGFsbCB0aGUgbGlzdGVkIHJlY2VpdmVycy5fXG4gICAgICovXG4gICAgLyogdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cbiAgICBzaWduYWwoc2lnbmFsOiBTaWduYWxPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsTWVzc2FnZSA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWRzLnB1c2goY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3R5cGUnXSA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnJztcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgnc2VuZE1lc3NhZ2UnLCB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogSlNPTi5zdHJpbmdpZnkoc2lnbmFsTWVzc2FnZSlcbiAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qIHRzbGludDplbmFibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayAnc3BlYWtpbmcnIGV2ZW50IGluIGFsbCBvZiB0aGVtXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBpZiAoISFzdHIgJiYgIXN0ci5zcGVlY2hFdmVudCAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgfHwgdHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIHRoaXMuc3BlYWtpbmdFdmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmICFzdHIuc3BlZWNoRXZlbnQgJiYgc3RyLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5lbmFibGVPbmNlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZih0eXBlOiBzdHJpbmcsIGhhbmRsZXI/OiAoZXZlbnQ6IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB8IFNpZ25hbEV2ZW50IHwgU3RyZWFtRXZlbnQgfCBDb25uZWN0aW9uRXZlbnQgfCBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IHwgUmVjb3JkaW5nRXZlbnQpID0+IHZvaWQpOiBTZXNzaW9uIHtcblxuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGRpc2FibGFlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiAhIXN0ci5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24ocmVzcG9uc2UuaWQsICcnKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Nvbm5lY3Rpb24gJyArIHJlc3BvbnNlLmlkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tyZXNwb25zZS5pZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5uYW1lLCAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIG1zZy5uYW1lICsgXCIgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50TGVmdCcuIFwiICtcbiAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBzdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgbXNnLnJlYXNvbildKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50UHVibGlzaGVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGFmdGVyQ29ubmVjdGlvbkZvdW5kID0gKGNvbm5lY3Rpb24pID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdID0gY29ubmVjdGlvbjtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkW2Nvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkXSkge1xuICAgICAgICAgICAgICAgIC8vIEF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gc3RyZWFtLnN1YnNjcmliZSgpIGluIFwib25QYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGFuZCBpbiBcImpvaW5Sb29tXCIgcnBjIGNhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBjb25kaXRpb24gaXMgZmFsc2UgaWYgb3BlbnZpZHUtc2VydmVyIHNlbmRzIFwicGFydGljaXBhbnRQdWJsaXNoZWRcIiBldmVudCB0byBhIHN1YnNjcmliZXIgcGFydGljaXBhbnQgdGhhdCBoYXNcbiAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IHN1YnNjcmliZWQgdG8gY2VydGFpbiBzdHJlYW0gaW4gdGhlIGNhbGxiYWNrIG9mIFwiam9pblJvb21cIiBtZXRob2RcblxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBHZXQgdGhlIGV4aXN0aW5nIENvbm5lY3Rpb24gY3JlYXRlZCBvbiAnb25QYXJ0aWNpcGFudEpvaW5lZCcgZm9yXG4gICAgICAgIC8vIGV4aXN0aW5nIHBhcnRpY2lwYW50cyBvciBjcmVhdGUgYSBuZXcgb25lIGZvciBuZXcgcGFydGljaXBhbnRzXG4gICAgICAgIGxldCBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24ocmVzcG9uc2UuaWQsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgcmVzcG9uc2UuaWQgKyBcIicgdW5rbm93biB3aGVuICdvblBhcnRpY2lwYW50UHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29uID0+IHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgZXhpc3RpbmcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBjb247XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UubWV0YWRhdGEgPSBjb24uZGF0YTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLm9wdGlvbnMgPSByZXNwb25zZTtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmluaXRSZW1vdGVTdHJlYW1zKHJlc3BvbnNlLnN0cmVhbXMpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgbmV3IENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGFmdGVyQ29ubmVjdGlvbkZvdW5kKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5uYW1lLCBcIlJlbW90ZSBjb25uZWN0aW9uICdcIiArIG1zZy5uYW1lICsgXCInIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgY29ubmVjdGlvbi5zdHJlYW0sIG1zZy5yZWFzb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuXG4gICAgICAgICAgICAgICAgLy8gRGVsZXRpbmcgdGhlIHJlbW90ZSBzdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZDogc3RyaW5nID0gY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ucmVtb3ZlU3RyZWFtKHN0cmVhbUlkKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50RXZpY3RlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgLyp0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24obXNnLm5hbWUsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLm5hbWUgKyBcIiB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRMZWZ0Jy4gXCIgK1xuICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSlcblxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHN0cmVhbSwgJ2ZvcmNlRGlzY29ubmVjdCcpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5kaXNwb3NlKCk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbi5jb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uRGVzdHJveWVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uRGVzdHJveWVkJywgY29ubmVjdGlvbiwgJ2ZvcmNlRGlzY29ubmVjdCcpXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTsqL1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk5ld01lc3NhZ2UobXNnKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgc2lnbmFsOiAnICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG5cbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKG1zZy5mcm9tLCBcIkNvbm5lY3Rpb24gJ1wiICsgbXNnLmZyb20gKyBcIicgdW5rbm93IHdoZW4gJ29uTmV3TWVzc2FnZScuIEV4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogXCJcbiAgICAgICAgICAgICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpICsgJy4gRXhpc3RpbmcgbG9jYWwgY29ubmVjdGlvbjogJyArIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWwnLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIG1zZy50eXBlLCBtc2cuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsOicgKyBtc2cudHlwZSwgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVjdkljZUNhbmRpZGF0ZShtc2cpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY2FuZGlkYXRlID0ge1xuICAgICAgICAgICAgY2FuZGlkYXRlOiBtc2cuY2FuZGlkYXRlLFxuICAgICAgICAgICAgc2RwTWlkOiBtc2cuc2RwTWlkLFxuICAgICAgICAgICAgc2RwTUxpbmVJbmRleDogbXNnLnNkcE1MaW5lSW5kZXgsXG4gICAgICAgICAgICB0b0pTT046ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKG1zZy5lbmRwb2ludE5hbWUsICdDb25uZWN0aW9uIG5vdCBmb3VuZCBmb3IgZW5kcG9pbnQgJyArIG1zZy5lbmRwb2ludE5hbWUgKyAnLiBJY2UgY2FuZGlkYXRlIHdpbGwgYmUgaWdub3JlZDogJyArIGNhbmRpZGF0ZSlcbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgIHN0cmVhbS5nZXRXZWJSdGNQZWVyKCkuYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBhZGRpbmcgY2FuZGlkYXRlIGZvciAnICsgc3RyZWFtLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblNlc3Npb25DbG9zZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnU2Vzc2lvbiBjbG9zZWQ6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcbiAgICAgICAgY29uc3QgcyA9IG1zZy5yb29tO1xuICAgICAgICBpZiAocyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbi1jbG9zZWQnLCBbe1xuICAgICAgICAgICAgICAgIHNlc3Npb246IHNcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiB1bmRlZmluZWQgb24gc2Vzc2lvbiBjbG9zZWQnLCBtc2cpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uTG9zdENvbm5lY3Rpb24oKTogdm9pZCB7XG5cbiAgICAgICAgLyppZiAoIXRoaXMuY29ubmVjdGlvbikge1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vdCBjb25uZWN0ZWQgdG8gc2Vzc2lvbjogaWYgeW91IGFyZSBub3QgZGVidWdnaW5nLCB0aGlzIGlzIHByb2JhYmx5IGEgY2VydGlmaWNhdGUgZXJyb3InKTtcblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJ2h0dHBzOi8vJyArIHRoaXMub3BlbnZpZHUuZ2V0V3NVcmkoKS5zcGxpdCgnd3NzOi8vJylbMV0uc3BsaXQoJy9vcGVudmlkdScpWzBdO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKCdJZiB5b3UgYXJlIG5vdCBkZWJ1Z2dpbmcsIHRoaXMgaXMgcHJvYmFibHkgYSBjZXJ0aWZpY2F0ZSBlcnJvciBhdCBcXFwiJyArIHVybCArICdcXFwiXFxuXFxuQ2xpY2sgT0sgdG8gbmF2aWdhdGUgYW5kIGFjY2VwdCBpdCcpKSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uYXNzaWduKHVybCArICcvYWNjZXB0LWNlcnRpZmljYXRlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0qL1xuXG4gICAgICAgIGNvbnNvbGUud2FybignTG9zdCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgdGhpcy5sZWF2ZSh0cnVlLCAnbmV0d29ya0Rpc2Nvbm5lY3QnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk1lZGlhRXJyb3IocGFyYW1zKTogdm9pZCB7XG5cbiAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWEgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgY29uc3QgZXJyID0gcGFyYW1zLmVycm9yO1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnZXJyb3ItbWVkaWEnLCBbe1xuICAgICAgICAgICAgICAgIGVycm9yOiBlcnJcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignUmVjZWl2ZWQgdW5kZWZpbmVkIG1lZGlhIGVycm9yLiBQYXJhbXM6JywgcGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0YXJ0ZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0YXJ0ZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdGFydGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3JkaW5nU3RvcHBlZChyZXNwb25zZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgncmVjb3JkaW5nU3RvcHBlZCcsIFtuZXcgUmVjb3JkaW5nRXZlbnQodGhpcywgJ3JlY29yZGluZ1N0b3BwZWQnLCByZXNwb25zZS5pZCwgcmVzcG9uc2UubmFtZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxlYXZlKGZvcmNlZDogYm9vbGVhbiwgcmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBmb3JjZWQgPSAhIWZvcmNlZDtcbiAgICAgICAgY29uc29sZS5pbmZvKCdMZWF2aW5nIFNlc3Npb24gKGZvcmNlZD0nICsgZm9yY2VkICsgJyknKTtcblxuICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkICYmICFmb3JjZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdsZWF2ZVJvb20nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVlLmVtaXRFdmVudCgnbG9jYWwtc3RyZWFtLWRlc3Ryb3llZC1ieS1kaXNjb25uZWN0JywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBNYWtlIFNlc3Npb24gb2JqZWN0IGRpc3BhdGNoICdzZXNzaW9uRGlzY29ubmVjdGVkJyBldmVudCAoaWYgaXQgaXMgbm90IGFscmVhZHkgZGlzcG9zZWQpXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudCA9IG5ldyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQodGhpcywgcmVhc29uKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcsIFtzZXNzaW9uRGlzY29ubmVjdEV2ZW50XSk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudC5jYWxsRGVmYXVsdEJlaGF2aW91cigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3Ugd2VyZSBub3QgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0QXV4KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zdGFydFdzKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBqb2luUGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46ICghIXRva2VuKSA/IHRva2VuIDogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKSxcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdqb2luUm9vbScsIGpvaW5QYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGF0YSA9IHJlc3BvbnNlLm1ldGFkYXRhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSByZW1vdGUgQ29ubmVjdGlvbnMgd2l0aCB2YWx1ZSByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25zOiBuZXcgQXJyYXk8Q29ubmVjdGlvbj4oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogbmV3IEFycmF5PFN0cmVhbT4oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdQYXJ0aWNpcGFudHM6IENvbm5lY3Rpb25PcHRpb25zW10gPSByZXNwb25zZS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50cy5mb3JFYWNoKHBhcnRpY2lwYW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMucHVzaChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLnB1c2goY29ubmVjdGlvbi5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPd24gJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCB0aGlzLmNvbm5lY3Rpb24sICcnKV0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggZXhpc3RpbmcgY29ubmVjdGlvbiBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgY29ubmVjdGlvbiwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ3N0cmVhbUNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGFjdGl2ZSBzdHJlYW0gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5mb3JFYWNoKHN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCBzdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW1vdGVDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIGNvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwodG9rZW4pO1xuICAgICAgICB0aGlzLnNlc3Npb25JZCA9IDxzdHJpbmc+dXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Nlc3Npb25JZCcpO1xuICAgICAgICBjb25zdCBzZWNyZXQgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnc2VjcmV0Jyk7XG4gICAgICAgIGNvbnN0IHJlY29yZGVyID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3JlY29yZGVyJyk7XG4gICAgICAgIGNvbnN0IHR1cm5Vc2VybmFtZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0dXJuVXNlcm5hbWUnKTtcbiAgICAgICAgY29uc3QgdHVybkNyZWRlbnRpYWwgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndHVybkNyZWRlbnRpYWwnKTtcbiAgICAgICAgY29uc3Qgcm9sZSA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdyb2xlJyk7XG5cbiAgICAgICAgaWYgKCEhc2VjcmV0KSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISFyZWNvcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdHVyblVzZXJuYW1lICYmICEhdHVybkNyZWRlbnRpYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0dW5VcmwgPSAnc3R1bjonICsgdXJsLmhvc3RuYW1lICsgJzozNDc4JztcbiAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICBjb25zdCB0dXJuVXJsMiA9IHR1cm5VcmwxICsgJz90cmFuc3BvcnQ9dGNwJztcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtcbiAgICAgICAgICAgICAgICB7IHVybHM6IFtzdHVuVXJsXSB9LFxuICAgICAgICAgICAgICAgIHsgdXJsczogW3R1cm5VcmwxLCB0dXJuVXJsMl0sIHVzZXJuYW1lOiB0dXJuVXNlcm5hbWUsIGNyZWRlbnRpYWw6IHR1cm5DcmVkZW50aWFsIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnVFVSTiB0ZW1wIGNyZWRlbnRpYWxzIFsnICsgdHVyblVzZXJuYW1lICsgJzonICsgdHVybkNyZWRlbnRpYWwgKyAnXScpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhcm9sZSkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yb2xlID0gcm9sZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub3BlbnZpZHUud3NVcmkgPSAnd3NzOi8vJyArIHVybC5ob3N0ICsgJy9vcGVudmlkdSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBXZWJSdGNQZWVyLCBXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlclNlbmRyZWN2IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNQZWVyL1dlYlJ0Y1BlZXInO1xuaW1wb3J0IHsgV2ViUnRjU3RhdHMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1N0YXRzL1dlYlJ0Y1N0YXRzJztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5pbXBvcnQgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKTtcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIG1lZGlhIHN0cmVhbXMgYXZhaWxhYmxlIGluIE9wZW5WaWR1IFNlcnZlciBmb3IgY2VydGFpbiBzZXNzaW9uLlxuICogRWFjaCBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBoYXMgYW4gYXR0cmlidXRlIG9mIHR5cGUgU3RyZWFtLCBhcyB0aGV5IGdpdmUgYWNjZXNzXG4gKiB0byBvbmUgb2YgdGhlbSAoc2VuZGluZyBhbmQgcmVjZWl2aW5nIGl0LCByZXNwZWN0aXZlbHkpXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW0ge1xuXG4gICAgLyoqXG4gICAgICogVGhlIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgaXMgcHVibGlzaGluZyB0aGUgc3RyZWFtXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZyYW1lIHJhdGUgb2YgdGhlIHZpZGVvIGluIGZyYW1lcyBwZXIgc2Vjb25kLiBUaGlzIHByb3BlcnR5IGlzIG9ubHkgZGVmaW5lZCBpZiB0aGUgW1tQdWJsaXNoZXJdXSBvZlxuICAgICAqIHRoZSBzdHJlYW0gd2FzIGluaXRpYWxpemVkIHBhc3NpbmcgYSBfZnJhbWVSYXRlXyBwcm9wZXJ0eSBvbiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBtZXRob2RcbiAgICAgKi9cbiAgICBmcmFtZVJhdGU/OiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIGEgdmlkZW8gdHJhY2sgb3Igbm90XG4gICAgICovXG4gICAgaGFzVmlkZW86IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIGFuIGF1ZGlvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc0F1ZGlvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIHN0cmVhbUlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBgXCJDQU1FUkFcImAgb3IgYFwiU0NSRUVOXCJgLiAqdW5kZWZpbmVkKiBpZiBzdHJlYW0gaXMgYXVkaW8tb25seVxuICAgICAqL1xuICAgIHR5cGVPZlZpZGVvPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtTWFuYWdlciBvYmplY3QgKFtbUHVibGlzaGVyXV0gb3IgW1tTdWJzY3JpYmVyXV0pIGluIGNoYXJnZSBvZiBkaXNwbGF5aW5nIHRoaXMgc3RyZWFtIGluIHRoZSBET01cbiAgICAgKi9cbiAgICBzdHJlYW1NYW5hZ2VyOiBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHJpdmF0ZSB3ZWJSdGNQZWVyOiBXZWJSdGNQZWVyO1xuICAgIHByaXZhdGUgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHM6IFdlYlJ0Y1N0YXRzO1xuXG4gICAgcHJpdmF0ZSBpc1N1YnNjcmliZVRvUmVtb3RlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5ib3VuZFN0cmVhbU9wdHM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3BlZWNoRXZlbnQ6IGFueTtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlc3Npb246IFNlc3Npb24sIG9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zIHwgT3V0Ym91bmRTdHJlYW1PcHRpb25zIHwge30pIHtcblxuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCdpZCcpKSB7XG4gICAgICAgICAgICAvLyBJbmJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBTdWJzY3JpYmVyXG4gICAgICAgICAgICB0aGlzLmluYm91bmRTdHJlYW1PcHRzID0gPEluYm91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnJlY3ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAoIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW8pID8gdW5kZWZpbmVkIDogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbztcbiAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE91dGJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBQdWJsaXNoZXJcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gPE91dGJvdW5kU3RyZWFtT3B0aW9ucz5vcHRpb25zO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICdTQ1JFRU4nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHlwZU9mVmlkZW8gPSAnQ0FNRVJBJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMudHlwZU9mVmlkZW87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pc1NlbmRBdWRpbygpO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaXNTZW5kVmlkZW8oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gbWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBoYXJrT3B0aW9ucyA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgaGFya09wdGlvbnMuaW50ZXJ2YWwgPSAodHlwZW9mIGhhcmtPcHRpb25zLmludGVydmFsID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDUwO1xuICAgICAgICAgICAgaGFya09wdGlvbnMudGhyZXNob2xkID0gKHR5cGVvZiBoYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLnRocmVzaG9sZCA6IC01MDtcblxuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZVNwZWFraW5nRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgIHRoaXMuc3BlZWNoRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWwoKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGluYm91bmQgb3B0aW9ucyB1bmRlZmluZWQgYW5kIG91dGJvdW5kIG9wdGlvbnMgZGVmaW5lZFxuICAgICAgICByZXR1cm4gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzICYmICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5nZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlcG9ydCA9PiByZXNvbHZlKHJlcG9ydCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpOiBSVENJY2VDYW5kaWRhdGVbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclNlbmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgdXNlck1lZGlhQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pc1NlbmRWaWRlbygpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3B1Ymxpc2hWaWRlbycsIHtcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW0sXG4gICAgICAgICAgICAgICAgICAgIGRvTG9vcGJhY2s6IHRoaXMuZGlzcGxheU15UmVtb3RlKCkgfHwgZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvQWN0aXZlOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiB0aGlzLmlzU2VuZFZpZGVvKCksXG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiAoKHRoaXMuaXNTZW5kVmlkZW8oKSkgPyAodGhpcy5pc1NlbmRTY3JlZW4oKSA/ICdTQ1JFRU4nIDogJ0NBTUVSQScpIDogJycpLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xXG4gICAgICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnRXJyb3Igb24gcHVibGlzaFZpZGVvOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSByZXNwb25zZS5pZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0xvY2FsU3RyZWFtUHVibGlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlUGVlclN1Y2Nlc2Z1bGx5RXN0YWJsaXNoZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCInUHVibGlzaGVyJyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIHRvIHNlc3Npb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kcmVjdihvcHRpb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kb25seShvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5nZW5lcmF0ZU9mZmVyKCkudGhlbihvZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclJlY2VpdmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgb2ZmZXJDb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5yZWN2QXVkaW8sXG4gICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMucmVjdlZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWQuIENvbnN0cmFpbnRzIG9mIGdlbmVyYXRlIFNEUCBvZmZlclwiLFxuICAgICAgICAgICAgICAgIG9mZmVyQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gc3Vic2NyaWJlIHRvICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3JlY2VpdmVWaWRlb0Zyb20nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gcmVjdlZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNmdWxseUVzdGFibGlzaGVkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclJlY3Zvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKVxuICAgICAgICAgICAgICAgIC50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbW90ZVBlZXJTdWNjZXNmdWxseUVzdGFibGlzaGVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gdGhpcy53ZWJSdGNQZWVyLnBjLmdldFJlbW90ZVN0cmVhbXMoKVswXTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnUGVlciByZW1vdGUgc3RyZWFtJywgdGhpcy5tZWRpYVN0cmVhbSk7XG5cbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSAmJiAhIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSAmJiB0aGlzLnNlc3Npb24uc3BlYWtpbmdFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVTcGVha2luZ0V2ZW50cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMgPSBuZXcgV2ViUnRjU3RhdHModGhpcyk7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wV2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMud2ViUnRjU3RhdHMgJiYgdGhpcy53ZWJSdGNTdGF0cy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5zdG9wV2ViUnRjU3RhdHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SWNlU2VydmVyc0NvbmYoKTogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgcmV0dXJuVmFsdWU7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMgPT09ICdmcmVlaWNlJyA/XG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5cblxuLyoqXG4gKiBJbnRlcmZhY2UgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhlIG1lZGlhIHN0cmVhbXMgaW4gdGhlIEhUTUwgRE9NLiBUaGlzIHdyYXBzIGFueSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSBvYmplY3QuXG4gKiBZb3UgY2FuIGluc2VydCBhcyBtYW55IHZpZGVvIHBsYXllcnMgZm8gdGhlIHNhbWUgU3RyZWFtIGFzIHlvdSB3YW50IGJ5IGNhbGxpbmcgW1tTdHJlYW1NYW5hZ2VyLmFkZFZpZGVvRWxlbWVudF1dIG9yXG4gKiBbW1N0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0uXG4gKlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXIgaW1wbGVtZW50cyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogVGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGJ5IHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQWxsIHRoZSB2aWRlb3MgZGlzcGxheWluZyB0aGUgU3RyZWFtIG9mIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICB2aWRlb3M6IFN0cmVhbU1hbmFnZXJWaWRlb1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBpcyBsb2NhbCBvciByZW1vdGVcbiAgICAgKiAtIGBmYWxzZWAgZm9yIFtbUHVibGlzaGVyXV1cbiAgICAgKiAtIGB0cnVlYCBmb3IgW1tTdWJzY3JpYmVyXV1cbiAgICAgKi9cbiAgICByZW1vdGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRE9NIEhUTUxFbGVtZW50IGFzc2lnbmVkIGFzIHRhcmdldCBlbGVtZW50IHdoZW4gY3JlYXRpbmcgdGhlIHZpZGVvIGZvciB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIuIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBgaWRgIGF0dHJpYnV0ZSBvZiB0aGUgRE9NIHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIncyBzdHJlYW0uIFRoaXMgcHJvcGVydHkgaXMgb25seSBkZWZpbmVkIGlmOlxuICAgICAqIC0gW1tQdWJsaXNoZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqIC0gW1tTdWJzY3JpYmVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICovXG4gICAgaWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaXJzdFZpZGVvRWxlbWVudDogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3Q7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyID0gdGhpcztcbiAgICAgICAgdGhpcy5yZW1vdGUgPSAhdGhpcy5zdHJlYW0uaXNMb2NhbCgpO1xuXG4gICAgICAgIGlmICghIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyksXG4gICAgICAgICAgICAgICAgICAgIGlkOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMpXSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgdGhpcy5lZS5vbmNlKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2VcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcyldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGB2aWRlb2AgZWxlbWVudCBwYXJhbWV0ZXIgZGlzcGxheSB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IGFyZVxuICAgICAqIFttYW5hZ2luZyB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd25dKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpXG4gICAgICpcbiAgICAgKiBDYWxsaW5nIHRoaXMgbWV0aG9kIHdpdGggYSB2aWRlbyBhbHJlYWR5IGFkZGVkIHRvIG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgY2F1c2UgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYmVcbiAgICAgKiBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBwcmV2aW91cyBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgdG8gYmUgYXNzb2NpYXRlZCB0byB0aGlzIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIDEgaWYgdGhlIHZpZGVvIHdhc24ndCBhc3NvY2lhdGVkIHRvIGFueSBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqIDAgaWYgdGhlIHZpZGVvIHdhcyBhbHJlYWR5IGFkZGVkIHRvIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXIuIC0xIGlmIHRoZSB2aWRlbyB3YXMgcHJldmlvdXNseSBhc3NvY2lhdGVkIHRvIGFueSBvdGhlclxuICAgICAqIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgb25lIGFuZCBwcm9wZXJseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKi9cbiAgICBhZGRWaWRlb0VsZW1lbnQodmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgLy8gSWYgdGhlIHZpZGVvIGVsZW1lbnQgaXMgYWxyZWFkeSBwYXJ0IG9mIHRoaXMgU3RyZWFtTWFuYWdlciBkbyBub3RoaW5nXG4gICAgICAgIGZvciAoY29uc3QgdiBvZiB0aGlzLnZpZGVvcykge1xuICAgICAgICAgICAgaWYgKHYudmlkZW8gPT09IHZpZGVvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmV0dXJuTnVtYmVyID0gMTtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCdOZXcgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvICcsIHRoaXMpO1xuXG4gICAgICAgIHJldHVybiByZXR1cm5OdW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGFsbG93cyB5b3UgdG8gaGF2ZSBtdWx0aXBsZSB2aWRlbyBlbGVtZW50cyBkaXNwbGF5aW5nIHRoZSBzYW1lIG1lZGlhIHN0cmVhbS5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGFyZ2V0RWxlbWVudCBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkXG4gICAgICogQHBhcmFtIGluc2VydE1vZGUgSG93IHRoZSB2aWRlbyBlbGVtZW50IHdpbGwgYmUgaW5zZXJ0ZWQgYWNjb3JkaW5nbHkgdG8gYHRhcmdldEVsZW1ldGBcbiAgICAgKi9cbiAgICBjcmVhdGVWaWRlb0VsZW1lbnQodGFyZ2V0RWxlbWVudD86IHN0cmluZyB8IEhUTUxFbGVtZW50LCBpbnNlcnRNb2RlPzogVmlkZW9JbnNlcnRNb2RlKTogSFRNTFZpZGVvRWxlbWVudCB7XG4gICAgICAgIGxldCB0YXJnRWw7XG4gICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdFbCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuXG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuICAgICAgICBpZiAoIXZpZGVvLmlkKSB7XG4gICAgICAgICAgICB2aWRlby5pZCA9ICh0aGlzLnJlbW90ZSA/ICdyZW1vdGUtJyA6ICdsb2NhbC0nKSArICd2aWRlby0nICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQ7XG4gICAgICAgICAgICAvLyBERVBSRUNBVEVEIHByb3BlcnR5OiBhc3NpZ24gb25jZSB0aGUgcHJvcGVydHkgaWQgaWYgdGhlIHVzZXIgcHJvdmlkZWQgYSB2YWxpZCB0YXJnZXRFbGVtZW50XG4gICAgICAgICAgICBpZiAoIXRoaXMuaWQgJiYgISF0aGlzLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdmlkZW8uaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3Muc2xpY2UoKS5yZXZlcnNlKCkuZm9yRWFjaCgoc3RyZWFtTWFuYWdlclZpZGVvLCBpbmRleCwgdmlkZW9zKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgb25jYW5wbGF5IGV2ZW50IGxpc3RlbmVyIChvbmx5IE9wZW5WaWR1IGJyb3dzZXIgb25lLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICAgICAgaWYgKCEhc3RyZWFtTWFuYWdlclZpZGVvLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbW92ZSB2aWRlb3MgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyICh0aG9zZSBnZW5lcmF0ZWQgYnkgcGFzc2luZyBhIHZhbGlkIHRhcmdldEVsZW1lbnQgaW4gT3BlblZpZHUuaW5pdFB1Ymxpc2hlciBhbmQgU2Vzc2lvbi5zdWJzY3JpYmVcbiAgICAgICAgICAgICAgICAvLyBvciB0aG9zZSBjcmVhdGVkIGJ5IFN0cmVhbU1hbmFnZXIuY3JlYXRlVmlkZW9FbGVtZW50KS4gVGhlc2UgYXJlIGFsc28gdGhlIHZpZGVvcyB0aGF0IHRyaWdnZXJlZCBhIHZpZGVvRWxlbWVudENyZWF0ZWQgZXZlbnRcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8ucGFyZW50Tm9kZSEucmVtb3ZlQ2hpbGQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50RGVzdHJveWVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnREZXN0cm95ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zLnNwbGljZSh2aWRlb3MubGVuZ3RoIC0gMSAtIGluZGV4LCAxKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHNyY09iamVjdCBpbiBhbGwgdmlkZW9zIG1hbmFnZWQgYnkgdGhlIHVzZXJcbiAgICAgICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkaXNhc3NvY2lhdGVkID0gZmFsc2U7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWRlb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1tpXS52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAodGhpcy52aWRlb3NbMF0udmlkZW8ub25jYW5wbGF5ID09PSBudWxsKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyB2aWRlbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbi8qKlxuICogRGVmaW5lcyBwcm9wZXJ0eSBbW09wZW5WaWR1RXJyb3IubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIE9wZW5WaWR1RXJyb3JOYW1lIHtcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZCBieSBPcGVuVmlkdS5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tTZXNzaW9uLmNvbm5lY3RdXVxuICAgICAqL1xuICAgIEJST1dTRVJfTk9UX1NVUFBPUlRFRCA9ICdCUk9XU0VSX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gdGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwcG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHVzZXIgaGFzbid0IGdyYW50ZWQgcGVybWlzc2lvbnMgdG8gY2FwdHVyZSBzb21lIGRlc2t0b3Agc2NyZWVuIHdoZW4gdGhlIGJyb3dzZXIgYXNrZWQgZm9yIHRoZW0uXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fU0hBUklOR19OT1RfU1VQUE9SVEVEID0gJ1NDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQnLFxuXG4gICAgLyoqXG4gICAgICogT25seSBmb3IgQ2hyb21lLCB0aGVyZSdzIG5vIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpbnN0YWxsZWRcbiAgICAgKiBSZXR1cm5lZCB1cHBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE5vIGF1ZGlvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBoYXMgYmVlbiBjYWxsZWQgd2l0aCBwcm9wZXJ0aWVzIGB2aWRlb1NvdXJjZWAgYW5kIGBhdWRpb1NvdXJjZWAgb2ZcbiAgICAgKiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBwYXJhbWV0ZXIgYm90aCBzZXQgdG8gKmZhbHNlKiBvciAqbnVsbCpcbiAgICAgKi9cbiAgICBOT19JTlBVVF9TT1VSQ0VfU0VUID0gJ05PX0lOUFVUX1NPVVJDRV9TRVQnLFxuXG4gICAgLyoqXG4gICAgICogU29tZSBtZWRpYSBwcm9wZXJ0eSBvZiBbW1B1Ymxpc2hlclByb3BlcnRpZXNdXSBzdWNoIGFzIGBmcmFtZVJhdGVgIG9yIGByZXNvbHV0aW9uYCBpcyBub3Qgc3VwcG9ydGVkXG4gICAgICogYnkgdGhlIGlucHV0IGRldmljZXMgKHdoZW5ldmVyIGl0IGlzIHBvc3NpYmxlIHRoZXkgYXJlIGF1dG9tYXRpY2FsbHkgYWRqdXN0ZWQgdG8gdGhlIG1vc3Qgc2ltaWxhciB2YWx1ZSkuXG4gICAgICogUmV0dXJuZWQgdXBwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEID0gJ09QRU5WSURVX1BFUk1JU1NJT05fREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIF9Ob3QgaW4gdXNlIHlldF9cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuLyoqXG4gKiBTaW1wbGUgb2JqZWN0IHRvIGlkZW50aWZ5IHJ1bnRpbWUgZXJyb3JzIG9uIHRoZSBjbGllbnQgc2lkZVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHVFcnJvciB7XG5cbiAgICBuYW1lOiBPcGVuVmlkdUVycm9yTmFtZTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBIb3cgdGhlIHZpZGVvIHdpbGwgYmUgaW5zZXJ0ZWQgaW4gdGhlIERPTSBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuIFNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dIGFuZCBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXVxuICovXG5leHBvcnQgZW51bSBWaWRlb0luc2VydE1vZGUge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHRhcmdldCBlbGVtZW50IChhcyBuZXh0IHNpYmxpbmcpXG4gICAgICovXG4gICAgQUZURVIgPSAnQUZURVInLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGxhc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgQVBQRU5EID0gJ0FQUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYmVmb3JlIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgcHJldmlvdXMgc2libGluZylcbiAgICAgKi9cbiAgICBCRUZPUkUgPSAnQkVGT1JFJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBmaXJzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBQUkVQRU5EID0gJ1BSRVBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIHJlcGxhY2VzIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUkVQTEFDRSA9ICdSRVBMQUNFJ1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYGNvbm5lY3Rpb25DcmVhdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgY29ubmVjdGlvbkRlc3Ryb3llZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIENvbm5lY3Rpb24gb2JqZWN0IHRoYXQgd2FzIGNyZWF0ZWQgb3IgZGVzdHJveWVkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIEZvciAnY29ubmVjdGlvbkRlc3Ryb3llZCcgZXZlbnQ6XG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIGV2ZW50IGhhcyBhIGRlZmF1bHQgYmVoYXZpb3VyIHRoYXQgbWF5IGJlIHByZXZlbnRlZCBieSBjYWxsaW5nIFtbRXZlbnQucHJldmVudERlZmF1bHRdXVxuICAgICAqL1xuICAgIGNhbmNlbGFibGU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb2JqZWN0IHRoYXQgZGlzcGF0Y2hlZCB0aGUgZXZlbnRcbiAgICAgKi9cbiAgICB0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHR5cGUgb2YgZXZlbnQuIFRoaXMgaXMgdGhlIHNhbWUgc3RyaW5nIHlvdSBwYXNzIGFzIGZpcnN0IHBhcmFtZXRlciB3aGVuIGNhbGxpbmcgbWV0aG9kIGBvbigpYCBvZiBhbnkgb2JqZWN0IGltcGxlbWVudGluZyBbW0V2ZW50RGlzcGF0Y2hlcl1dIGludGVyZmFjZVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIHByaXZhdGUgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgb2YgdGhlIGV2ZW50LiBUaGUgZm9sbG93aW5nIGV2ZW50cyBoYXZlIGEgZGVmYXVsdCBiZWhhdmlvdXI6XG4gICAgICpcbiAgICAgKiAtIGBzZXNzaW9uRGlzY29ubmVjdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKi9cbiAgICBwcmV2ZW50RGVmYXVsdCgpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgICAgIHRoaXMuY2FsbERlZmF1bHRCZWhhdmlvdXIgPSAoKSA9PiB7IH07XG4gICAgICAgIHRoaXMuaGFzQmVlblByZXZlbnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGNhbGxEZWZhdWx0QmVoYXZpb3VyKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKlxuICogTW9yZSBpbmZvcm1hdGlvbjpcbiAqIC0gVGhpcyBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBmb3IgKipyZW1vdGUgc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKipcbiAqIC0gQm90aCBldmVudHMgc2hhcmUgdGhlIHNhbWUgbGlmZWN5Y2xlLiBUaGF0IG1lYW5zIHRoYXQgeW91IGNhbiBzdWJzY3JpYmUgdG8gb25seSBvbmUgb2YgdGhlbSBpZiB5b3Ugd2FudCwgYnV0IGlmIHlvdSBjYWxsIGBTZXNzaW9uLm9mZigncHVibGlzaGVyU3RvcFNwZWFraW5nJylgLFxuICoga2VlcCBpbiBtaW5kIHRoYXQgdGhpcyB3aWxsIGFsc28gaW50ZXJuYWxseSByZW1vdmUgYW55ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyBldmVudFxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgc3RyZWFtSWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHN0cmVhbUlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHJlY29yZGluZ1N0YXJ0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGByZWNvcmRpbmdTdG9wcGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIElEIGdlbmVyYXRlZCBpbiBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlY29yZGluZyBuYW1lIHlvdSBzdXBwbGllZCB0byBvcGVudmlkdS1zZXJ2ZXIuIEZvciBleGFtcGxlLCB0byBuYW1lIHlvdXIgcmVjb3JkaW5nIGZpbGUgTVlfUkVDT1JESU5HOlxuICAgICAqIC0gV2l0aCAqKkFQSSBSRVNUKio6IFBPU1QgdG8gYC9hcGkvcmVjb3JkaW5ncy9zdGFydGAgcGFzc2luZyBKU09OIGJvZHkgYHtcInNlc3Npb25cIjpcInNlc3Npb25JZFwiLFwibmFtZVwiOlwiTVlfUkVDT1JESU5HXCJ9YFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LWphdmEtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIE1ZX1JFQ09SRElORylgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKE1ZX1JFQ09SRElORykuYnVpbGQoKSlgXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtbm9kZS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgTVlfUkVDT1JESU5HKWAgb3IgYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgbmV3IFJlY29yZGluZ1Byb3BlcnRpZXMuQnVpbGRlcigpLm5hbWUoTVlfUkVDT1JESU5HKS5idWlsZCgpKWBcbiAgICAgKlxuICAgICAqIElmIG5vIG5hbWUgaXMgc3VwcGxpZWQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSB1bmRlZmluZWQgYW5kIHRoZSByZWNvcmRlZCBmaWxlIHdpbGwgYmUgbmFtZWQgYWZ0ZXIgcHJvcGVydHkgW1tpZF1dXG4gICAgICovXG4gICAgbmFtZT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIGlmIChuYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVudCBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogeW91IGhhdmUgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogeW91ciBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHRydWUsIHRhcmdldCwgJ3Nlc3Npb25EaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3VyKCkge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkNhbGxpbmcgZGVmYXVsdCBiZWhhdmlvdXIgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IDxTZXNzaW9uPnRoaXMudGFyZ2V0O1xuXG4gICAgICAgIC8vIERpc3Bvc2UgYW5kIGRlbGV0ZSBhbGwgcmVtb3RlIENvbm5lY3Rpb25zXG4gICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5zdHJlYW1JZF07XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLmRpc3Bvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc2lnbmFsYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICogLSBgc2lnbmFsOlRZUEVgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIHNpZ25hbCAoY2FuIGJlIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzdWJzY3JpYmVkIHRvIGBTZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHRvIHJlY2VpdmUgdGhpcyBvYmplY3QgaW4gdGhlIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogU3Vic2NyaWJpbmcgdG8gYFNlc3Npb24ub24oJ3NpZ25hbCcsIGZ1bmN0aW9uKHNpZ25hbEV2ZW50KSB7Li4ufSlgIHdpbGwgdHJpZ2dlciBhbGwgdHlwZXMgb2Ygc2lnbmFscy5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW10cHkpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0aGF0IHNlbnQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGZyb206IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZywgZnJvbTogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvdXIoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEZvciAnc3RyZWFtRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwidW5wdWJsaXNoXCI6IG1ldGhvZCBgU2Vzc2lvbi51bnB1Ymxpc2goKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogbWV0aG9kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcIm5ldHdvcmtEaXNjb25uZWN0XCI6IHRoZSB1c2VyJ3MgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICpcbiAgICAgKiBGb3IgJ3N0cmVhbUNyZWF0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFB1Ymxpc2hlciwgdHlwZTogc3RyaW5nLCBzdHJlYW06IFN0cmVhbSwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3VyIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgUHVibGlzaGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9jYWwgU3RyZWFtXG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW91ciB1cG9uICdcIiArIHRoaXMudHlwZSArIFwiJyBldmVudCBkaXNwYXRjaGVkIGJ5ICdQdWJsaXNoZXInXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlcikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUGxheWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE4IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHZpZGVvRWxlbWVudENyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBpbnNlcnRlZCBpbnRvIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuIFNlZVxuICogW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uLlxuICogLSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSB3aGVuZXZlciBhbiBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWRlb0VsZW1lbnRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGVsZW1lbnQgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBlbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQsIHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW91cigpIHsgfVxuXG59IiwiZnVuY3Rpb24gTWFwcGVyKClcbntcbiAgdmFyIHNvdXJjZXMgPSB7fTtcblxuXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKVxuICB7XG4gICAgZm9yKHZhciBrZXkgaW4gc291cmNlcylcbiAgICB7XG4gICAgICB2YXIgc291cmNlID0gc291cmNlc1trZXldO1xuXG4gICAgICBmb3IodmFyIGtleTIgaW4gc291cmNlKVxuICAgICAgICBjYWxsYmFjayhzb3VyY2Vba2V5Ml0pO1xuICAgIH07XG4gIH07XG5cbiAgdGhpcy5nZXQgPSBmdW5jdGlvbihpZCwgc291cmNlKVxuICB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZihpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBpZHNbaWRdO1xuICB9O1xuXG4gIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcblxuICAgIGRlbGV0ZSBpZHNbaWRdO1xuXG4gICAgLy8gQ2hlY2sgaXQncyBlbXB0eVxuICAgIGZvcih2YXIgaSBpbiBpZHMpe3JldHVybiBmYWxzZX1cblxuICAgIGRlbGV0ZSBzb3VyY2VzW3NvdXJjZV07XG4gIH07XG5cbiAgdGhpcy5zZXQgPSBmdW5jdGlvbih2YWx1ZSwgaWQsIHNvdXJjZSlcbiAge1xuICAgIGlmKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHNvdXJjZXNbc291cmNlXSA9IGlkcyA9IHt9O1xuXG4gICAgaWRzW2lkXSA9IHZhbHVlO1xuICB9O1xufTtcblxuXG5NYXBwZXIucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG57XG4gIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGlkLCBzb3VyY2UpO1xuICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICByZXR1cm4gdmFsdWU7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gTWFwcGVyO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBKc29uUnBjQ2xpZW50ICA9IHJlcXVpcmUoJy4vanNvbnJwY2NsaWVudCcpO1xuXG5cbmV4cG9ydHMuSnNvblJwY0NsaWVudCAgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uLycpO1xudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5EYXRlLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiArbmV3IERhdGU7XG59O1xuXG52YXIgUElOR19JTlRFUlZBTCA9IDUwMDA7XG5cbnZhciBSRUNPTk5FQ1RJTkcgPSAnUkVDT05ORUNUSU5HJztcbnZhciBDT05ORUNURUQgPSAnQ09OTkVDVEVEJztcbnZhciBESVNDT05ORUNURUQgPSAnRElTQ09OTkVDVEVEJztcblxudmFyIExvZ2dlciA9IGNvbnNvbGU7XG5cbi8qKlxuICpcbiAqIGhlYXJ0YmVhdDogaW50ZXJ2YWwgaW4gbXMgZm9yIGVhY2ggaGVhcnRiZWF0IG1lc3NhZ2UsXG4gKiBzZW5kQ2xvc2VNZXNzYWdlIDogdHJ1ZSAvIGZhbHNlLCBiZWZvcmUgY2xvc2luZyB0aGUgY29ubmVjdGlvbiwgaXQgc2VuZHMgYSBjbG9zZVNlc3Npb24gbWVzc2FnZVxuICogPHByZT5cbiAqIHdzIDoge1xuICogXHR1cmkgOiBVUkkgdG8gY29ubnRlY3QgdG8sXG4gKiAgdXNlU29ja0pTIDogdHJ1ZSAodXNlIFNvY2tKUykgLyBmYWxzZSAodXNlIFdlYlNvY2tldCkgYnkgZGVmYXVsdCxcbiAqIFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuICogXHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCxcbiAqIFx0b25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG4gKiBcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbiAqIFx0b25lcnJvciA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGVyZSBpcyBhbiBlcnJvclxuICogfSxcbiAqIHJwYyA6IHtcbiAqIFx0cmVxdWVzdFRpbWVvdXQgOiB0aW1lb3V0IGZvciBhIHJlcXVlc3QsXG4gKiBcdHNlc3Npb25TdGF0dXNDaGFuZ2VkOiBjYWxsYmFjayBtZXRob2QgZm9yIGNoYW5nZXMgaW4gc2Vzc2lvbiBzdGF0dXMsXG4gKiBcdG1lZGlhUmVuZWdvdGlhdGlvbjogbWVkaWFSZW5lZ290aWF0aW9uXG4gKiB9XG4gKiA8L3ByZT5cbiAqL1xuZnVuY3Rpb24gSnNvblJwY0NsaWVudChjb25maWd1cmF0aW9uKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgd3NDb25maWcgPSBjb25maWd1cmF0aW9uLndzO1xuXG4gICAgdmFyIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSAtMTtcblxuICAgIHZhciBwaW5nTmV4dE51bSA9IDA7XG4gICAgdmFyIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgdmFyIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgIHZhciBwaW5nSW50ZXJ2YWw7XG5cbiAgICB2YXIgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgdmFyIG9ucmVjb25uZWN0aW5nID0gd3NDb25maWcub25yZWNvbm5lY3Rpbmc7XG4gICAgdmFyIG9ucmVjb25uZWN0ZWQgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGVkO1xuICAgIHZhciBvbmNvbm5lY3RlZCA9IHdzQ29uZmlnLm9uY29ubmVjdGVkO1xuICAgIHZhciBvbmVycm9yID0gd3NDb25maWcub25lcnJvcjtcblxuICAgIGNvbmZpZ3VyYXRpb24ucnBjLnB1bGwgPSBmdW5jdGlvbihwYXJhbXMsIHJlcXVlc3QpIHtcbiAgICAgICAgcmVxdWVzdC5yZXBseShudWxsLCBcInB1c2hcIik7XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNUSU5HIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBSRUNPTk5FQ1RJTkcpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIFJFQ09OTkVDVElORyBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVElORyBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXR1cyA9IFJFQ09OTkVDVElORztcbiAgICAgICAgaWYgKG9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RlZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9ucmVjb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uY29ubmVjdGVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05DT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVzZVBpbmcoKTtcblxuICAgICAgICBpZiAob25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9ORVJST1IgLS0tLS0tLS0tLS1cIik7XG5cbiAgICAgICAgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgICAgIGlmIChvbmVycm9yKSB7XG4gICAgICAgICAgICBvbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKHdzQ29uZmlnKTtcblxuICAgIExvZ2dlci5kZWJ1ZygnQ29ubmVjdGluZyB3ZWJzb2NrZXQgdG8gVVJJOiAnICsgd3NDb25maWcudXJpKTtcblxuICAgIHZhciBycGNCdWlsZGVyT3B0aW9ucyA9IHtcbiAgICAgICAgcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5yZXF1ZXN0VGltZW91dCxcbiAgICAgICAgcGluZ19yZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLmhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0XG4gICAgfTtcblxuICAgIHZhciBycGMgPSBuZXcgUnBjQnVpbGRlcihScGNCdWlsZGVyLnBhY2tlcnMuSnNvblJQQywgcnBjQnVpbGRlck9wdGlvbnMsIHdzLFxuICAgICAgICBmdW5jdGlvbihyZXF1ZXN0KSB7XG5cbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVjZWl2ZWQgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IGNvbmZpZ3VyYXRpb24ucnBjW3JlcXVlc3QubWV0aG9kXTtcblxuICAgICAgICAgICAgICAgIGlmIChmdW5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWV0aG9kIFwiICsgcmVxdWVzdC5tZXRob2QgKyBcIiBub3QgcmVnaXN0ZXJlZCBpbiBjbGllbnRcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyhyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKCdFeGNlcHRpb24gcHJvY2Vzc2luZyByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAobWV0aG9kICE9PSAncGluZycpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVxdWVzdDogbWV0aG9kOicgKyBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgcnBjLmVuY29kZShtZXRob2QsIHBhcmFtcywgZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1I6XCIgKyBlcnJvci5tZXNzYWdlICsgXCIgaW4gUmVxdWVzdDogbWV0aG9kOlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyBcIiByZXF1ZXN0OlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1IgREFUQTpcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yLmRhdGEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdFRpbWUgPSByZXF1ZXN0VGltZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT0gdW5kZWZpbmVkICYmIHJlc3VsdC52YWx1ZSAhPT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVzcG9uc2U6ICcgKyBKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIm5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBcIiArIHBpbmdOZXh0TnVtICsgJyAob2xkPScgK1xuICAgICAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiArICcpJyk7XG4gICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBwaW5nTmV4dE51bTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZW5kUGluZygpIHtcbiAgICAgICAgaWYgKGVuYWJsZWRQaW5ncykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG51bGw7XG4gICAgICAgICAgICBpZiAocGluZ05leHROdW0gPT0gMCB8fCBwaW5nTmV4dE51bSA9PSBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbDogY29uZmlndXJhdGlvbi5oZWFydGJlYXQgfHwgUElOR19JTlRFUlZBTFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwaW5nTmV4dE51bSsrO1xuXG4gICAgICAgICAgICBzZWxmLnNlbmQoJ3BpbmcnLCBwYXJhbXMsIChmdW5jdGlvbihwaW5nTnVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJFcnJvciBpbiBwaW5nIHJlcXVlc3QgI1wiICsgcGluZ051bSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubWVzc2FnZSArIFwiKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaW5nTnVtID4gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZXJ2ZXIgZGlkIG5vdCByZXNwb25kIHRvIHBpbmcgbWVzc2FnZSAjXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5nTnVtICsgXCIuIFJlY29ubmVjdGluZy4uLiBcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKHBpbmdOZXh0TnVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUcnlpbmcgdG8gc2VuZCBwaW5nLCBidXQgcGluZyBpcyBub3QgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgKiBJZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0IGhhcyBhbnkgdmFsdWUsIHRoZSBwaW5nLXBvbmcgd2lsbCB3b3JrIHdpdGggdGhlIGludGVydmFsXG4gICAgKiBvZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0XG4gICAgKi9cbiAgICBmdW5jdGlvbiB1c2VQaW5nKCkge1xuICAgICAgICBpZiAoIXBpbmdQb25nU3RhcnRlZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgcGluZyAoaWYgY29uZmlndXJlZClcIilcbiAgICAgICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwaW5nSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzZW5kUGluZywgY29uZmlndXJhdGlvbi5oZWFydGJlYXQpO1xuICAgICAgICAgICAgICAgIHNlbmRQaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NpbmcganNvblJwY0NsaWVudCBleHBsaWNpdGx5IGJ5IGNsaWVudFwiKTtcblxuICAgICAgICBpZiAocGluZ0ludGVydmFsICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xlYXJpbmcgcGluZyBpbnRlcnZhbFwiKTtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsKTtcbiAgICAgICAgfVxuICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGNvbmZpZ3VyYXRpb24uc2VuZENsb3NlTWVzc2FnZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VuZGluZyBjbG9zZSBtZXNzYWdlXCIpXG4gICAgICAgICAgICB0aGlzLnNlbmQoJ2Nsb3NlU2Vzc2lvbicsIG51bGwsIGZ1bmN0aW9uKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyBjbG9zZSBtZXNzYWdlOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcblx0XHRcdHdzLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24obWlsbGlzKSB7XG4gICAgICAgIHdzLmZvcmNlQ2xvc2UobWlsbGlzKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlY29ubmVjdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpzb25ScGNDbGllbnQ7XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gID0gcmVxdWlyZSgnLi93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uJyk7XG5cblxuZXhwb3J0cy5XZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb247IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxMy0yMDE1IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIEJyb3dzZXJXZWJTb2NrZXQgPSBnbG9iYWwuV2ViU29ja2V0IHx8IGdsb2JhbC5Nb3pXZWJTb2NrZXQ7XG5cbnZhciBMb2dnZXIgPSBjb25zb2xlO1xuXG4vKipcbiAqIEdldCBlaXRoZXIgdGhlIGBXZWJTb2NrZXRgIG9yIGBNb3pXZWJTb2NrZXRgIGdsb2JhbHNcbiAqIGluIHRoZSBicm93c2VyIG9yIHRyeSB0byByZXNvbHZlIFdlYlNvY2tldC1jb21wYXRpYmxlXG4gKiBpbnRlcmZhY2UgZXhwb3NlZCBieSBgd3NgIGZvciBOb2RlLWxpa2UgZW52aXJvbm1lbnQuXG4gKi9cblxuLyp2YXIgV2ViU29ja2V0ID0gQnJvd3NlcldlYlNvY2tldDtcbmlmICghV2ViU29ja2V0ICYmIHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgV2ViU29ja2V0ID0gcmVxdWlyZSgnd3MnKTtcbiAgICB9IGNhdGNoIChlKSB7IH1cbn0qL1xuXG4vL3ZhciBTb2NrSlMgPSByZXF1aXJlKCdzb2NranMtY2xpZW50Jyk7XG5cbnZhciBNQVhfUkVUUklFUyA9IDIwMDA7IC8vIEZvcmV2ZXIuLi5cbnZhciBSRVRSWV9USU1FX01TID0gMzAwMDsgLy8gRklYTUU6IEltcGxlbWVudCBleHBvbmVudGlhbCB3YWl0IHRpbWVzLi4uXG5cbnZhciBDT05ORUNUSU5HID0gMDtcbnZhciBPUEVOID0gMTtcbnZhciBDTE9TSU5HID0gMjtcbnZhciBDTE9TRUQgPSAzO1xuXG4vKlxuY29uZmlnID0ge1xuXHRcdHVyaSA6IHdzVXJpLFxuXHRcdHVzZVNvY2tKUyA6IHRydWUgKHVzZSBTb2NrSlMpIC8gZmFsc2UgKHVzZSBXZWJTb2NrZXQpIGJ5IGRlZmF1bHQsXG5cdFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuXHRcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0LFxuXHRcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuXHRcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcblx0fTtcbiovXG5mdW5jdGlvbiBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKGNvbmZpZykge1xuXG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciB1c2VTb2NrSlMgPSBjb25maWcudXNlU29ja0pTO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IGZhbHNlO1xuXG4gICAgdmFyIHdzO1xuXG4gICAgaWYgKHVzZVNvY2tKUykge1xuICAgICAgICB3cyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG4gICAgfVxuXG4gICAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ0Nvbm5lY3RlZCh3cywgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCB1bmV4cGVjdGVjbHkuIFJlY29ubmVjdGluZy4uLlwiKTtcbiAgICAgICAgICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwicmVjb25uZWN0VG9TYW1lVXJpIChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiKTtcblxuICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKHJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIExvZ2dlci53YXJuKFwiVHJ5aW5nIHRvIHJlY29ubmVjdFRvTmV3VXJpIHdoZW4gcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcmNpbmdEaXNjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCB3c1VyaSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5uZXdXc1VyaU9uUmVjb25uZWN0aW9uKGZ1bmN0aW9uKGVycm9yLCBuZXdXc1VyaSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0ZWQgYWZ0ZXIgXCIgKyBudW1SZXRyaWVzICsgXCIgYXR0ZW1wdHMuLi5cIik7XG4gICAgICAgICAgICBsb2dDb25uZWN0ZWQobmV3V3MsIHdzVXJpKTtcbiAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5vbnJlY29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RlZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXdXcy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgb25FcnJvck9yQ2xvc2UgPSBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG5cbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cblxuICAgIC8vIFRoaXMgbWV0aG9kIGlzIG9ubHkgZm9yIHRlc3RpbmdcbiAgICB0aGlzLmZvcmNlQ2xvc2UgPSBmdW5jdGlvbihtaWxsaXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogRm9yY2UgV2ViU29ja2V0IGNsb3NlXCIpO1xuXG4gICAgICAgIGlmIChtaWxsaXMpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRlc3Rpbmc6IENoYW5nZSB3c1VyaSBmb3IgXCIgKyBtaWxsaXMgKyBcIiBtaWxsaXMgdG8gc2ltdWxhdGUgbmV0IGZhaWx1cmVcIik7XG4gICAgICAgICAgICB2YXIgZ29vZFdzVXJpID0gd3NVcmk7XG4gICAgICAgICAgICB3c1VyaSA9IFwid3NzOi8vMjEuMjM0LjEyLjM0LjQ6NDQzL1wiO1xuXG4gICAgICAgICAgICBmb3JjaW5nRGlzY29ubmVjdGlvbiA9IHRydWU7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3RUb1NhbWVVcmkoTUFYX1JFVFJJRVMsIDEsIHdzVXJpKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24obWVzc2FnZSkge1xuICAgICAgICB3cy5zZW5kKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBjYWxsYmFjaykge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uO1xuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cblxudmFyIGRlZmluZVByb3BlcnR5X0lFOCA9IGZhbHNlXG5pZihPYmplY3QuZGVmaW5lUHJvcGVydHkpXG57XG4gIHRyeVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCBcInhcIiwge30pO1xuICB9XG4gIGNhdGNoKGUpXG4gIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgICAgZk5PUCAgICA9IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGZCb3VuZCAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpc1xuICAgICAgICAgICAgICAgICA/IHRoaXNcbiAgICAgICAgICAgICAgICAgOiBvVGhpcyxcbiAgICAgICAgICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgICAgfTtcblxuICAgIGZOT1AucHJvdG90eXBlID0gdGhpcy5wcm90b3R5cGU7XG4gICAgZkJvdW5kLnByb3RvdHlwZSA9IG5ldyBmTk9QKCk7XG5cbiAgICByZXR1cm4gZkJvdW5kO1xuICB9O1xufVxuXG5cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbnZhciBwYWNrZXJzID0gcmVxdWlyZSgnLi9wYWNrZXJzJyk7XG52YXIgTWFwcGVyID0gcmVxdWlyZSgnLi9NYXBwZXInKTtcblxuXG52YXIgQkFTRV9USU1FT1VUID0gNTAwMDtcblxuXG5mdW5jdGlvbiB1bmlmeVJlc3BvbnNlTWV0aG9kcyhyZXNwb25zZU1ldGhvZHMpXG57XG4gIGlmKCFyZXNwb25zZU1ldGhvZHMpIHJldHVybiB7fTtcblxuICBmb3IodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpXG4gIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID1cbiAgICAgIHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydClcbntcbiAgaWYoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7c2VuZDogdHJhbnNwb3J0fTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZih0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYodHJhbnNwb3J0LnBvc3RNZXNzYWdlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC5wb3N0TWVzc2FnZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gU3RyZWFtIEFQSVxuICBpZih0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZih0cmFuc3BvcnQucGF1c2UgaW5zdGFuY2VvZiBGdW5jdGlvbikgcmV0dXJuO1xuXG4gIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRyYW5zcG9ydCBpcyBub3QgYSBmdW5jdGlvbiBub3IgYSB2YWxpZCBvYmplY3RcIik7XG59O1xuXG5cbi8qKlxuICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgbm90aWZpY2F0aW9uXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAqL1xuZnVuY3Rpb24gUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKVxue1xuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gIHtcbiAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZFxuICAgIHRoaXMucGFyYW1zID0gcGFyYW1zXG4gIH1cbiAgZWxzZVxuICB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdtZXRob2QnLCB7dmFsdWU6IG1ldGhvZCwgZW51bWVyYWJsZTogdHJ1ZX0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGFyYW1zJywge3ZhbHVlOiBwYXJhbXMsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYWNrZXJcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29uUmVxdWVzdF1cbiAqL1xuZnVuY3Rpb24gUnBjQnVpbGRlcihwYWNrZXIsIG9wdGlvbnMsIHRyYW5zcG9ydCwgb25SZXF1ZXN0KVxue1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYoIXBhY2tlcilcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBub3QgZGVmaW5lZCcpO1xuXG4gIGlmKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gb3B0aW9ucztcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgb3B0aW9ucyAgID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZih0cmFuc3BvcnQgJiYgISh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJPbmx5IGEgZnVuY3Rpb24gY2FuIGJlIGFmdGVyIHRyYW5zcG9ydFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSBvcHRpb25zO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKG9uUmVxdWVzdCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IHRyYW5zcG9ydDtcbiAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZihvblJlcXVlc3QpXG4gICAgdGhpcy5vbigncmVxdWVzdCcsIG9uUmVxdWVzdCk7XG5cblxuICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7dmFsdWU6IG9wdGlvbnMucGVlcklEfSk7XG5cbiAgdmFyIG1heF9yZXRyaWVzID0gb3B0aW9ucy5tYXhfcmV0cmllcyB8fCAwO1xuXG5cbiAgZnVuY3Rpb24gdHJhbnNwb3J0TWVzc2FnZShldmVudClcbiAge1xuICAgIHNlbGYuZGVjb2RlKGV2ZW50LmRhdGEgfHwgZXZlbnQpO1xuICB9O1xuXG4gIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKHZhbHVlKVxuICB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmKHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYodHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgLy8gU2V0IGxpc3RlbmVyIG9uIG5ldyB0cmFuc3BvcnRcbiAgICBpZih2YWx1ZSlcbiAgICB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYodmFsdWUuYWRkRXZlbnRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZighZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICB7XG4gICAgICBnZXQ6IHRoaXMuZ2V0VHJhbnNwb3J0LmJpbmQodGhpcyksXG4gICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICB9KVxuXG4gIHRoaXMuc2V0VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cblxuICB2YXIgcmVxdWVzdF90aW1lb3V0ICAgICAgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCAgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ICAgICA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCAgICAgfHwgQkFTRV9USU1FT1VUO1xuICB2YXIgZHVwbGljYXRlc190aW1lb3V0ICAgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCAgIHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyAgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdClcbiAge1xuICAgIHZhciByZXNwb25zZSA9XG4gICAge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSlcbiAge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAge1xuICAgICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnJlbW92ZShhY2ssIGZyb20pO1xuICAgIH0sXG4gICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KVxuICB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbigpXG4gICAge1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAgICB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0JyxcbiAgICAgIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmKCEodHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCkpKVxuICAgIHtcbiAgICAgIGlmKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJyxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24oZXJyb3IsIHJlc3VsdCwgdHJhbnNwb3J0KVxuICAgIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZihlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICAgIHtcbiAgICAgICAgaWYocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZihyZXN1bHQgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgfHwgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYocmVzcG9uc2UpXG4gICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcblxuICAgICAgaWYoZnJvbSAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmKGVycm9yIHx8IHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICB7XG4gICAgICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZClcbiAgICAgICAge1xuICAgICAgICAgIGlmKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYocmVzcG9uc2VNZXRob2QpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihyZXNwb25zZU1ldGhvZC5lcnJvciA9PSB1bmRlZmluZWQgJiYgZXJyb3IpXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhciBtZXRob2QgPSBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA/IHJlc3BvbnNlTWV0aG9kLmVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2VNZXRob2QucmVzcG9uc2U7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICB7XG4gICAgICAgICAgICBlcnJvcjogIGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYocmVzcG9uc2UpXG4gICAgICAgIG1lc3NhZ2UgPSByZXNwb25zZS5tZXNzYWdlO1xuXG4gICAgICAvLyBOZXcgZW1wdHkgcmVwbHksIHJlc3BvbnNlIG51bGwgdmFsdWVcbiAgICAgIGVsc2VcbiAgICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKHtyZXN1bHQ6IG51bGx9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZih0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpXG4gIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYoIWtleSkgcmV0dXJuO1xuXG4gICAgZGVsZXRlIG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5wb3Aoa2V5LmlkLCBrZXkuZGVzdCk7XG4gICAgaWYoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbihtZXNzYWdlKVxuICB7XG4gICAgaWYobWVzc2FnZSkgcmV0dXJuIGNhbmNlbChtZXNzYWdlKTtcblxuICAgIGZvcih2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbigpXG4gIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5jbG9zZSlcbiAgICAgICB0cmFuc3BvcnQuY2xvc2UoKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYobWljcm9zb2Z0RWRnZSkge1xuICAgICAgICBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzKWNhdGNoKG9uRmFpbHVyZSk7XG4gICAgfVxufSwgJ3Bhc3Mgc2Vjb25kIHBhcmFtZXRlciBvbmx5IGlmIHlvdSB3YW50IHN5c3RlbSBhdWRpbycpO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGNhbGxiYWNrLCBjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKSkge1xuICAgICAgICAvLyBtaWNyb3NvZnQgZWRnZSA9PiBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgICAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSBnZXRTY3JlZW5JZDsiLCIvLyBnbG9iYWwgdmFyaWFibGVzXG52YXIgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbnZhciBzb3VyY2VJZDtcbnZhciBzY3JlZW5DYWxsYmFjaztcbnZhciBpc0ZpcmVmb3ggPSB0eXBlb2Ygd2luZG93Lkluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJztcbnZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG52YXIgaXNDaHJvbWUgPSAhIXdpbmRvdy5jaHJvbWUgJiYgIWlzT3BlcmE7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG59KTtcblxuLy8gYW5kIHRoZSBmdW5jdGlvbiB0aGF0IGhhbmRsZXMgcmVjZWl2ZWQgbWVzc2FnZXNcbmZ1bmN0aW9uIG9uTWVzc2FnZUNhbGxiYWNrKGRhdGEpIHtcbiAgICAvLyBcImNhbmNlbFwiIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgaWYgKGRhdGEgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgaWYgKHNjcmVlbkNhbGxiYWNrKVxuICAgICAgICAgICAgcmV0dXJuIHNjcmVlbkNhbGxiYWNrKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKTtcbiAgICB9XG4gICAgLy8gZXh0ZW5zaW9uIG5vdGlmaWVkIGhpcyBwcmVzZW5jZVxuICAgIGlmIChkYXRhID09ICdydGNtdWx0aWNvbm5lY3Rpb24tZXh0ZW5zaW9uLWxvYWRlZCcpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnZGVza3RvcCc7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBzaGFyZWQgdGVtcCBzb3VyY2VJZFxuICAgIGlmIChkYXRhLnNvdXJjZUlkICYmIHNjcmVlbkNhbGxiYWNrKSB7XG4gICAgICAgIHNjcmVlbkNhbGxiYWNrKHNvdXJjZUlkID0gZGF0YS5zb3VyY2VJZCwgZGF0YS5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9PT0gdHJ1ZSk7XG4gICAgfVxufVxuXG4vLyB0aGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byBjaGVjayBpZiBjaHJvbWUgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZCAmIGVuYWJsZWQuXG5mdW5jdGlvbiBpc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZShjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spIHJldHVybjtcbiAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ2Rlc2t0b3AnKSByZXR1cm4gY2FsbGJhY2sodHJ1ZSk7XG5cbiAgICAvLyBhc2sgZXh0ZW5zaW9uIGlmIGl0IGlzIGF2YWlsYWJsZVxuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXJlLXlvdS10aGVyZScsICcqJyk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICB9IGVsc2UgY2FsbGJhY2sodHJ1ZSk7XG4gICAgfSwgMjAwMCk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRTb3VyY2VJZChjYWxsYmFjaykge1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHRocm93ICdcImNhbGxiYWNrXCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeS4nO1xuICAgIGlmIChzb3VyY2VJZClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnZ2V0LXNvdXJjZUlkJywgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldEN1c3RvbVNvdXJjZUlkKGFyciwgY2FsbGJhY2spIHtcbiAgICBpZiAoIWFyciB8fCAhYXJyLmZvckVhY2gpIHRocm93ICdcImFyclwiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkgYW5kIGl0IG11c3QgYmUgYW4gYXJyYXkuJztcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcblxuICAgIGlmIChzb3VyY2VJZCkgcmV0dXJuIGNhbGxiYWNrKHNvdXJjZUlkKTtcblxuICAgIHNjcmVlbkNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgd2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgJ2dldC1jdXN0b20tc291cmNlSWQnOiBhcnJcbiAgICB9LCAnKicpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWRXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgnYXVkaW8tcGx1cy10YWInLCAnKicpO1xufVxuXG5mdW5jdGlvbiBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMoZXh0ZW5zaW9uaWQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCdub3QtY2hyb21lJyk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggIT0gMikge1xuICAgICAgICBjYWxsYmFjayA9IGV4dGVuc2lvbmlkO1xuICAgICAgICBleHRlbnNpb25pZCA9ICdsZmNnZmVwYWZub2JkbG9lY2NobmZhY2xpYmVuam9sZCc7IC8vIGRlZmF1bHQgZXh0ZW5zaW9uLWlkXG4gICAgfVxuICAgIHZhciBpbWFnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIGltYWdlLnNyYyA9ICdjaHJvbWUtZXh0ZW5zaW9uOi8vJyArIGV4dGVuc2lvbmlkICsgJy9pY29uLnBuZyc7XG4gICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZSA9ICdzY3JlZW4nO1xuICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnc2NyZWVuJykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZGlzYWJsZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICB9LCAyMDAwKTtcbiAgICB9O1xuICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKCdub3QtaW5zdGFsbGVkJyk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW8oY2FsbGJhY2spIHtcbiAgICBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgdHJ1ZSk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gZXhwbGFpbnMgaG93IHRvIHVzZSBhYm92ZSBtZXRob2RzL29iamVjdHNcbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGNhbGxiYWNrLCBjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICBzb3VyY2VJZCA9ICcnO1xuICAgIHZhciBmaXJlZm94U2NyZWVuQ29uc3RyYWludHMgPSB7XG4gICAgICAgIG1vek1lZGlhU291cmNlOiAnd2luZG93JyxcbiAgICAgICAgbWVkaWFTb3VyY2U6ICd3aW5kb3cnXG4gICAgfTtcbiAgICBpZiAoaXNGaXJlZm94KVxuICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzKTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCBkZWZpbmVzIGdldFVzZXJNZWRpYSBjb25zdHJhaW50c1xuICAgIC8vIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGNhcHR1cmUgY29udGVudCBvZiBzY3JlZW5cbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBjaHJvbWVNZWRpYVNvdXJjZSxcbiAgICAgICAgICAgIG1heFdpZHRoOiBzY3JlZW4ud2lkdGggPiAxOTIwID8gc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgIG1heEhlaWdodDogc2NyZWVuLmhlaWdodCA+IDEwODAgPyBzY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25hbDogW11cbiAgICB9O1xuICAgIC8vIHRoaXMgc3RhdGVtZW50IHZlcmlmaWVzIGNocm9tZSBleHRlbnNpb24gYXZhaWxhYmlsaXR5XG4gICAgLy8gaWYgaW5zdGFsbGVkIGFuZCBhdmFpbGFibGUgdGhlbiBpdCB3aWxsIGludm9rZSBleHRlbnNpb24gQVBJXG4gICAgLy8gb3RoZXJ3aXNlIGl0IHdpbGwgZmFsbGJhY2sgdG8gY29tbWFuZC1saW5lIGJhc2VkIHNjcmVlbiBjYXB0dXJpbmcgQVBJXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJyAmJiAhc291cmNlSWQpIHtcbiAgICAgICAgaWYgKGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbykge1xuICAgICAgICAgICAgZ2V0U291cmNlSWRXaXRoQXVkaW8oZnVuY3Rpb24gKHNvdXJjZUlkLCBjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5jYW5SZXF1ZXN0QXVkaW9UcmFjayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHNvdXJjZUlkID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InID8gc291cmNlSWQgOiBudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBnZXRTb3VyY2VJZChmdW5jdGlvbiAoc291cmNlSWQpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyB0aGlzIHN0YXRlbWVudCBzZXRzIGdldHMgJ3NvdXJjZUlkXCIgYW5kIHNldHMgXCJjaHJvbWVNZWRpYVNvdXJjZUlkXCIgXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTggT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCBmcmVlaWNlID0gcmVxdWlyZSgnZnJlZWljZScpO1xuaW1wb3J0IHV1aWQgPSByZXF1aXJlKCd1dWlkJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24ge1xuICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgYXVkaW86IGJvb2xlYW4sXG4gICAgICAgIHZpZGVvOiBib29sZWFuXG4gICAgfTtcbiAgICBzaW11bGNhc3Q6IGJvb2xlYW47XG4gICAgb25pY2VjYW5kaWRhdGU6IChldmVudCkgPT4gdm9pZDtcbiAgICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZDtcbiAgICBtZWRpYVN0cmVhbT86IE1lZGlhU3RyZWFtO1xuICAgIG1vZGU/OiBzdHJpbmc7IC8vIHNlbmRvbmx5LCByZWNvbmx5LCBzZW5kcmVjdlxuICAgIGlkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlciB7XG5cbiAgICBwYzogUlRDUGVlckNvbm5lY3Rpb247XG4gICAgaWQ6IHN0cmluZztcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBjYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbmZpZ3VyYXRpb246IFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzID0gKCEhdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiYgdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMubGVuZ3RoID4gMCkgPyB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA6IGZyZWVpY2UoKTtcblxuICAgICAgICB0aGlzLnBjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHsgaWNlU2VydmVyczogdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgfSk7XG4gICAgICAgIHRoaXMuaWQgPSAhIWNvbmZpZ3VyYXRpb24uaWQgPyBjb25maWd1cmF0aW9uLmlkIDogdXVpZC52NCgpO1xuXG4gICAgICAgIHRoaXMucGMub25pY2VjYW5kaWRhdGUgPSBldmVudCA9PiB7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSA9IGV2ZW50LmNhbmRpZGF0ZTtcbiAgICAgICAgICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ub25pY2VjYW5kaWRhdGUoZXZlbnQuY2FuZGlkYXRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5wYy5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKDxSVENJY2VDYW5kaWRhdGU+dGhpcy5pY2VDYW5kaWRhdGVMaXN0LnNoaWZ0KCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjcmVhdGVzIHRoZSBSVENQZWVyQ29ubmVjdGlvbiBvYmplY3QgdGFraW5nIGludG8gYWNjb3VudCB0aGVcbiAgICAgKiBwcm9wZXJ0aWVzIHJlY2VpdmVkIGluIHRoZSBjb25zdHJ1Y3Rvci4gSXQgc3RhcnRzIHRoZSBTRFAgbmVnb3RpYXRpb25cbiAgICAgKiBwcm9jZXNzOiBnZW5lcmF0ZXMgdGhlIFNEUCBvZmZlciBhbmQgaW52b2tlcyB0aGUgb25zZHBvZmZlciBjYWxsYmFjay4gVGhpc1xuICAgICAqIGNhbGxiYWNrIGlzIGV4cGVjdGVkIHRvIHNlbmQgdGhlIFNEUCBvZmZlciwgaW4gb3JkZXIgdG8gb2J0YWluIGFuIFNEUFxuICAgICAqIGFuc3dlciBmcm9tIGFub3RoZXIgcGVlci5cbiAgICAgKi9cbiAgICBzdGFydCgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdUaGUgcGVlciBjb25uZWN0aW9uIG9iamVjdCBpcyBpbiBcImNsb3NlZFwiIHN0YXRlLiBUaGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byBhbiBpbnZvY2F0aW9uIG9mIHRoZSBkaXNwb3NlIG1ldGhvZCBiZWZvcmUgYWNjZXB0aW5nIGluIHRoZSBkaWFsb2d1ZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRTdHJlYW0odGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gW0hhY2tdIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDM1NThcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9PT0gJ3NlbmRvbmx5JyAmJlxuICAgICAgICAgICAgICAgIChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJyAmJiBwbGF0Zm9ybS52ZXJzaW9uIS50b1N0cmluZygpLnN1YnN0cmluZygwLCAyKSA9PT0gJzM5JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgZnJlZXMgdGhlIHJlc291cmNlcyB1c2VkIGJ5IFdlYlJ0Y1BlZXJcbiAgICAgKi9cbiAgICBkaXNwb3NlKCkge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIHRoaXMucGMuZ2V0TG9jYWxTdHJlYW1zKCkuZm9yRWFjaChzdHIgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVN0b3Aoc3RyKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEZJWE1FIFRoaXMgaXMgbm90IHlldCBpbXBsZW1lbnRlZCBpbiBmaXJlZm94XG4gICAgICAgICAgICAgICAgLy8gaWYodmlkZW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbSh2aWRlb1N0cmVhbSk7XG4gICAgICAgICAgICAgICAgLy8gaWYoYXVkaW9TdHJlYW0pIHBjLnJlbW92ZVN0cmVhbShhdWRpb1N0cmVhbSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjLmNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdFeGNlcHRpb24gZGlzcG9zaW5nIHdlYnJ0YyBwZWVyICcgKyBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogMSkgRnVuY3Rpb24gdGhhdCBjcmVhdGVzIGFuIG9mZmVyLCBzZXRzIGl0IGFzIGxvY2FsIGRlc2NyaXB0aW9uIGFuZCByZXR1cm5zIHRoZSBvZmZlciBwYXJhbVxuICAgICAqIHRvIHNlbmQgdG8gT3BlblZpZHUgU2VydmVyICh3aWxsIGJlIHRoZSByZW1vdGUgZGVzY3JpcHRpb24gb2Ygb3RoZXIgcGVlcilcbiAgICAgKi9cbiAgICBnZW5lcmF0ZU9mZmVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgb2ZmZXJBdWRpbywgb2ZmZXJWaWRlbyA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cmFpbnRzIG11c3QgaGF2ZSBib3RoIGJsb2Nrc1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICBvZmZlclZpZGVvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiArICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlclZpZGVvKVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnUlRDUGVlckNvbm5lY3Rpb24gY29uc3RyYWludHM6ICcgKyBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cykpO1xuXG4gICAgICAgICAgICB0aGlzLnBjLmNyZWF0ZU9mZmVyKGNvbnN0cmFpbnRzKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24ob2ZmZXIpO1xuICAgICAgICAgICAgfSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSg8c3RyaW5nPmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0xvY2FsIGRlc2NyaXB0aW9uIGlzIG5vdCBkZWZpbmVkJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDIpIEZ1bmN0aW9uIHRvIGludm9rZSB3aGVuIGEgU0RQIG9mZmVyIGlzIHJlY2VpdmVkLiBTZXRzIGl0IGFzIHJlbW90ZSBkZXNjcmlwdGlvbixcbiAgICAgKiBnZW5lcmF0ZXMgYW5kIGFuc3dlciBhbmQgcmV0dXJucyBpdCB0byBzZW5kIGl0IHRvIE9wZW5WaWR1IFNlcnZlclxuICAgICAqL1xuICAgIHByb2Nlc3NPZmZlcihzZHBPZmZlcjogc3RyaW5nKTogUHJvbWlzZTxDb25zdHJhaW5ET01TdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdvZmZlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBPZmZlclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU0RQIG9mZmVyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBjLnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuY3JlYXRlQW5zd2VyKCk7XG4gICAgICAgICAgICAgICAgfSkudGhlbihhbnN3ZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBhbnN3ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICAgICAgICAgIH0pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbERlc2NyaXB0aW9uID0gdGhpcy5wYy5sb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFsb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdMb2NhbCBkZXNjcmlwdGlvbiBzZXQnLCBsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKDxzdHJpbmc+bG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDMpIEZ1bmN0aW9uIGludm9rZWQgd2hlbiBhIFNEUCBhbnN3ZXIgaXMgcmVjZWl2ZWQuIEZpbmFsIHN0ZXAgaW4gU0RQIG5lZ290aWF0aW9uLCB0aGUgcGVlclxuICAgICAqIGp1c3QgbmVlZHMgdG8gc2V0IHRoZSBhbnN3ZXIgYXMgaXRzIHJlbW90ZSBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIHByb2Nlc3NBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnUlRDUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZS5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdGFibGUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyZWFtU3RvcChzdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHtcbiAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIHN0cmVhbS5yZW1vdmVUcmFjayh0cmFjayk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclJlY3Zvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRyZWN2IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRyZWN2JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzRW5hYmxlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNJbnRlcnZhbElkOiBOb2RlSlMuVGltZXI7XG4gICAgcHJpdmF0ZSBzdGF0c0ludGVydmFsID0gMTtcbiAgICBwcml2YXRlIHN0YXRzOiBhbnkgPSB7XG4gICAgICAgIGluYm91bmQ6IHtcbiAgICAgICAgICAgIGF1ZGlvOiB7XG4gICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwLFxuICAgICAgICAgICAgICAgIGZyYW1lc0RlY29kZWQ6IDAsXG4gICAgICAgICAgICAgICAgbmFja0NvdW50OiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNFbmNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHsgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKGVsYXN0ZXN0SW5zdHJ1bWVudGF0aW9uKSB7XG4gICAgICAgICAgICAvLyBFbGFzVGVzdCBpbnN0cnVtZW50YXRpb24gb2JqZWN0IGZvdW5kIGluIGxvY2FsIHN0b3JhZ2VcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWJSdGMgc3RhdHMgZW5hYmxlZCBmb3Igc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGNvbnN0IGluc3RydW1lbnRhdGlvbiA9IEpTT04ucGFyc2UoZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24pO1xuICAgICAgICAgICAgdGhpcy5zdGF0c0ludGVydmFsID0gaW5zdHJ1bWVudGF0aW9uLndlYnJ0Yy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KGluc3RydW1lbnRhdGlvbikpO1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB9LCB0aGlzLnN0YXRzSW50ZXJ2YWwgKiAxMDAwKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0b3BXZWJSdGNTdGF0cygpIHtcbiAgICAgICAgaWYgKHRoaXMud2ViUnRjU3RhdHNFbmFibGVkKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignV2ViUnRjIHN0YXRzIHN0b3BwZWQgZm9yIGRpc3Bvc2VkIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLFxuICAgICAgICAgICAgICAgIChzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxvY2FsQ2FuZGlkYXRlSWQsIHJlbW90ZUNhbmRpZGF0ZUlkLCBnb29nQ2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gc3RhdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAnbG9jYWxjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlc1tzdGF0LmlkXSA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0LnR5cGUgPT09ICdyZW1vdGVjYW5kaWRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXNbc3RhdC5pZF0gPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdC50eXBlID09PSAnZ29vZ0NhbmRpZGF0ZVBhaXInICYmIChzdGF0Lmdvb2dBY3RpdmVDb25uZWN0aW9uID09PSAndHJ1ZScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVJZCA9IHN0YXQubG9jYWxDYW5kaWRhdGVJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzdGF0LnJlbW90ZUNhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaW5hbExvY2FsQ2FuZGlkYXRlID0gbG9jYWxDYW5kaWRhdGVzW2xvY2FsQ2FuZGlkYXRlSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZmluYWxMb2NhbENhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRMaXN0ID0gdGhpcy5zdHJlYW0uZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwQWRkcmVzcykgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnROdW1iZXIpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZS5yYXcgPSAhIWNhbmRbMF0gPyBjYW5kWzBdLmNhbmRpZGF0ZSA6ICdFUlJPUjogQ2Fubm90IGZpbmQgbG9jYWwgY2FuZGlkYXRlIGluIGxpc3Qgb2Ygc2VudCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSBsb2NhbCBJQ0UgY2FuZGlkYXRlLiBQcm9iYWJseSBJQ0UtVENQIGlzIGJlaW5nIHVzZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSByZW1vdGVDYW5kaWRhdGVzW3JlbW90ZUNhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5pcEFkZHJlc3MpID49IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUucG9ydE51bWJlcikgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wcmlvcml0eSkgPj0gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3ID0gISFjYW5kWzBdID8gY2FuZFswXS5jYW5kaWRhdGUgOiAnRVJST1I6IENhbm5vdCBmaW5kIHJlbW90ZSBjYW5kaWRhdGUgaW4gbGlzdCBvZiByZWNlaXZlZCBJQ0UgY2FuZGlkYXRlcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVtb3RlQ2FuZGlkYXRlID0gJ0VSUk9SOiBObyBhY3RpdmUgcmVtb3RlIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvb2dDYW5kaWRhdGVQYWlyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlOiBmaW5hbExvY2FsQ2FuZGlkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZTogZmluYWxSZW1vdGVDYW5kaWRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdTZWxlY3RlZCBJQ0UgY2FuZGlkYXRlIGluZm8gb25seSBhdmFpbGFibGUgZm9yIENocm9tZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZW5kU3RhdHNUb0h0dHBFbmRwb2ludChpbnN0cnVtZW50YXRpb24pOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBzZW5kUG9zdCA9IChqc29uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBodHRwOiBYTUxIdHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgY29uc3QgdXJsOiBzdHJpbmcgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmh0dHBFbmRwb2ludDtcbiAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIHVybCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcblxuICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7IC8vIENhbGwgYSBmdW5jdGlvbiB3aGVuIHRoZSBzdGF0ZSBjaGFuZ2VzLlxuICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQgJiYgaHR0cC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnV2ViUnRjIHN0YXRzIHN1Y2Nlc3NmdWxseSBzZW50IHRvICcgKyB1cmwgKyAnIGZvciBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0dHAuc2VuZChqc29uKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmID0gKHN0YXRzKSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc3RhdHMuZm9yRWFjaCgoc3RhdCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKChzdGF0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBvdXRib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQubmFja0NvdW50ICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnN0YXJ0c1dpdGgoJ2luYm91bmQnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQucmVtb3RlSWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGppdCA9IHN0YXQuaml0dGVyICogMTAwMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6IGppdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IChzdGF0LnBhY2tldHNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogKHN0YXQucGFja2V0c0xvc3QgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6ICdieXRlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogJ3BhY2tldHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNEZWNvZGVkJ10gPSAoc3RhdC5mcmFtZXNEZWNvZGVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQubmFja0NvdW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0RlY29kZWQnXSA9ICdmcmFtZXMnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkID0gc3RhdC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQgPSBzdGF0Lm5hY2tDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QgPSBzdGF0LnBhY2tldHNMb3N0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChzdGF0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF2b2lkIGZpcmVmb3ggZW1wdHkgaW5ib3VuZC1ydHAgc3RhdGlzdGljc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaXNSZW1vdGUgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pZC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdvdXRib3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAoc3RhdC5ieXRlc1NlbnQgLSB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ2ZyYW1lc0VuY29kZWQnXSA9ICdmcmFtZXMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKHN0YXQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbSc6ICd3ZWJSdGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICd1bml0cyc6IHVuaXRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUG9zdChKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0YXRzKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gc3RhdHNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQudHlwZSA9PT0gJ3NzcmMnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqc29uID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnYnl0ZXNSZWNlaXZlZCcgaW4gc3RhdCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXQubWVkaWFUeXBlID09PSAnYXVkaW8nICYmICdhdWRpb091dHB1dExldmVsJyBpbiBzdGF0KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJyAmJiAncXBTdW0nIGluIHN0YXQpXG4gICAgICAgICAgICAgICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5ib3VuZC1ydHBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNJZCA9ICd3ZWJydGNfaW5ib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAoc3RhdC5ieXRlc1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5ieXRlc1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiBzdGF0Lmdvb2dKaXR0ZXJCdWZmZXJNcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAoc3RhdC5wYWNrZXRzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaml0dGVyOiAnbXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6ICdwYWNrZXRzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ25hY2tDb3VudCddID0gKHN0YXQuZ29vZ05hY2tzU2VudCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5uYWNrQ291bnQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWyduYWNrQ291bnQnXSA9ICdwYWNrZXRzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCA9IHN0YXQuZnJhbWVzRGVjb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQuZ29vZ05hY2tzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQgPSBzdGF0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNMb3N0ID0gc3RhdC5wYWNrZXRzTG9zdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJ2J5dGVzU2VudCcgaW4gc3RhdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG91dGJvdW5kLXJ0cFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19vdXRib3VuZF8nICsgc3RhdC5tZWRpYVR5cGUgKyAnXycgKyBzdGF0LnNzcmM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAoc3RhdC5wYWNrZXRzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0VuY29kZWQnXSA9IChzdGF0LmZyYW1lc0VuY29kZWQgLSB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkID0gc3RhdC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNTZW50ID0gc3RhdC5wYWNrZXRzU2VudDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdleGVjJzogaW5zdHJ1bWVudGF0aW9uLmV4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd0eXBlJzogbWV0cmljSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmdldFN0YXRzQWdub3N0aWModGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKSwgZiwgKGVycm9yKSA9PiB7IGNvbnNvbGUubG9nKGVycm9yKTsgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGFuZGFyZGl6ZVJlcG9ydChyZXNwb25zZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZSk7XG4gICAgICAgIGNvbnN0IHN0YW5kYXJkUmVwb3J0ID0ge307XG5cbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3BvbnNlKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2Vba2V5XSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3BvbnNlLnJlc3VsdCgpLmZvckVhY2gocmVwb3J0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0YW5kYXJkU3RhdHMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IHJlcG9ydC5pZCxcbiAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IHJlcG9ydC50aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgdHlwZTogcmVwb3J0LnR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXBvcnQubmFtZXMoKS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgc3RhbmRhcmRTdGF0c1tuYW1lXSA9IHJlcG9ydC5zdGF0KG5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdGFuZGFyZFJlcG9ydFtzdGFuZGFyZFN0YXRzLmlkXSA9IHN0YW5kYXJkU3RhdHM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdGFuZGFyZFJlcG9ydDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFN0YXRzQWdub3N0aWMocGMsIHN1Y2Nlc3NDYiwgZmFpbHVyZUNiKSB7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lIS5pbmRleE9mKCdGaXJlZm94JykgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBnZXRTdGF0cyB0YWtlcyBhcmdzIGluIGRpZmZlcmVudCBvcmRlciBpbiBDaHJvbWUgYW5kIEZpcmVmb3hcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cyhudWxsKS50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZhaWx1cmVDYik7XG4gICAgICAgIH0gZWxzZSBpZiAoKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0Nocm9tZScpICE9PSAtMSkgfHwgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ09wZXJhJykgIT09IC0xKSkge1xuICAgICAgICAgICAgLy8gSW4gQ2hyb21lLCB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cyBhcmUgcmV2ZXJzZWRcbiAgICAgICAgICAgIHJldHVybiBwYy5nZXRTdGF0cygocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXBvcnQgPSB0aGlzLnN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2IocmVwb3J0KTtcbiAgICAgICAgICAgIH0sIG51bGwsIGZhaWx1cmVDYik7XG4gICAgICAgIH1cbiAgICB9XG5cbn0iXX0= diff --git a/openvidu-mvc-node/views/session.ejs b/openvidu-mvc-node/views/session.ejs index fa6759fa..f66587a6 100644 --- a/openvidu-mvc-node/views/session.ejs +++ b/openvidu-mvc-node/views/session.ejs @@ -14,7 +14,7 @@ - + diff --git a/openvidu-recording-java/pom.xml b/openvidu-recording-java/pom.xml index 66c6d30d..c82f93d6 100644 --- a/openvidu-recording-java/pom.xml +++ b/openvidu-recording-java/pom.xml @@ -4,7 +4,7 @@ io.openvidu openvidu-recording-java - 1.1.0 + 2.2.0 jar openvidu-recording-java @@ -95,7 +95,7 @@ io.openvidu openvidu-java-client - 2.0.0 + 2.2.0 diff --git a/openvidu-recording-java/src/main/resources/static/index.html b/openvidu-recording-java/src/main/resources/static/index.html index 66679726..ba69e776 100644 --- a/openvidu-recording-java/src/main/resources/static/index.html +++ b/openvidu-recording-java/src/main/resources/static/index.html @@ -14,7 +14,7 @@ - + +